aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl/libxl_event.h
diff options
context:
space:
mode:
authorIan Jackson <Ian.Jackson@eu.citrix.com>2012-05-11 18:58:56 +0100
committerIan Jackson <Ian.Jackson@eu.citrix.com>2012-05-11 18:58:56 +0100
commit1133a72c733788a3a4f37c761a99d57f3540618f (patch)
tree750053a99b2c3a8a5e09c5eb814cbd24cc1194a1 /tools/libxl/libxl_event.h
parentd2037c4acfb56930ff37f984de8440cc765f1acc (diff)
downloadxen-1133a72c733788a3a4f37c761a99d57f3540618f.tar.gz
xen-1133a72c733788a3a4f37c761a99d57f3540618f.tar.bz2
xen-1133a72c733788a3a4f37c761a99d57f3540618f.zip
of SIGCHLD. The application can tell us whether it wants to own
SIGCHLD or not; if it does, it has to tell us about deaths of our children. Currently there are no callers in libxl which use these facilities. All code in libxl which forks needs to be converted and libxl_fork needse to be be abolished. Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> Committed-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Diffstat (limited to 'tools/libxl/libxl_event.h')
-rw-r--r--tools/libxl/libxl_event.h147
1 files changed, 142 insertions, 5 deletions
diff --git a/tools/libxl/libxl_event.h b/tools/libxl/libxl_event.h
index 2d2196f34a..713d96d1ed 100644
--- a/tools/libxl/libxl_event.h
+++ b/tools/libxl/libxl_event.h
@@ -163,11 +163,6 @@ void libxl_event_register_callbacks(libxl_ctx *ctx,
* After libxl_ctx_free, all corresponding evgen handles become
* invalid and must no longer be passed to evdisable.
*
- * Events enabled with evenable prior to a fork and libxl_ctx_postfork
- * are no longer generated after the fork/postfork; however the evgen
- * structures are still valid and must be passed to evdisable if the
- * memory they use should not be leaked.
- *
* Applications should ensure that they eventually retrieve every
* event using libxl_event_check or libxl_event_wait, since events
* which occur but are not retreived by the application will be queued
@@ -372,6 +367,148 @@ void libxl_osevent_occurred_fd(libxl_ctx *ctx, void *for_libxl,
void libxl_osevent_occurred_timeout(libxl_ctx *ctx, void *for_libxl);
+/*======================================================================*/
+
+/*
+ * Subprocess handling.
+ *
+ * Unfortunately the POSIX interface makes this very awkward.
+ *
+ * There are two possible arrangements for collecting statuses from
+ * wait/waitpid.
+ *
+ * For naive programs:
+ *
+ * libxl will keep a SIGCHLD handler installed whenever it has an
+ * active (unreaped) child. It will reap all children with
+ * wait(); any children it does not recognise will be passed to
+ * the application via an optional callback (and will result in
+ * logged warnings if no callback is provided or the callback
+ * denies responsibility for the child).
+ *
+ * libxl may have children whenever:
+ *
+ * - libxl is performing an operation which can be made
+ * asynchronous; ie one taking a libxl_asyncop_how, even
+ * if NULL is passed indicating that the operation is
+ * synchronous; or
+ *
+ * - events of any kind are being generated, as requested
+ * by libxl_evenable_....
+ *
+ * A multithreaded application which is naive in this sense may
+ * block SIGCHLD on some of its threads, but there must be at
+ * least one thread that has SIGCHLD unblocked. libxl will not
+ * modify the blocking flag for SIGCHLD (except that it may create
+ * internal service threads with all signals blocked).
+ *
+ * A naive program must only have at any one time only
+ * one libxl context which might have children.
+ *
+ * For programs which run their own children alongside libxl's:
+ *
+ * A program which does this must call libxl_childproc_setmode.
+ * There are two options:
+ *
+ * libxl_sigchld_owner_mainloop:
+ * The application must install a SIGCHLD handler and reap (at
+ * least) all of libxl's children and pass their exit status
+ * to libxl by calling libxl_childproc_exited.
+ *
+ * libxl_sigchld_owner_libxl_always:
+ * The application expects libxl to reap all of its children,
+ * and provides a callback to be notified of their exit
+ * statues.
+ *
+ * An application which fails to call setmode, or which passes 0 for
+ * hooks, while it uses any libxl operation which might
+ * create or use child processes (see above):
+ * - Must not have any child processes running.
+ * - Must not install a SIGCHLD handler.
+ * - Must not reap any children.
+ */
+
+
+typedef enum {
+ /* libxl owns SIGCHLD whenever it has a child. */
+ libxl_sigchld_owner_libxl,
+
+ /* Application promises to call libxl_childproc_exited but NOT
+ * from within a signal handler. libxl will not itself arrange to
+ * (un)block or catch SIGCHLD. */
+ libxl_sigchld_owner_mainloop,
+
+ /* libxl owns SIGCHLD all the time, and the application is
+ * relying on libxl's event loop for reaping its own children. */
+ libxl_sigchld_owner_libxl_always,
+} libxl_sigchld_owner;
+
+typedef struct {
+ libxl_sigchld_owner chldowner;
+
+ /* All of these are optional: */
+
+ /* Called by libxl instead of fork. Should behave exactly like
+ * fork, including setting errno etc. May NOT reenter into libxl.
+ * Application may use this to discover pids of libxl's children,
+ * for example.
+ */
+ pid_t (*fork_replacement)(void *user);
+
+ /* With libxl_sigchld_owner_libxl, called by libxl when it has
+ * reaped a pid. (Not permitted with _owner_mainloop.)
+ *
+ * Should return 0 if the child was recognised by the application
+ * (or if the application does not keep those kind of records),
+ * ERROR_UNKNOWN_CHILD if the application knows that the child is not
+ * the application's; if it returns another error code it is a
+ * disaster as described for libxl_event_register_callbacks.
+ * (libxl will report unexpected children to its error log.)
+ *
+ * If not supplied, the application is assumed not to start
+ * any children of its own.
+ *
+ * This function is NOT called from within the signal handler.
+ * Rather it will be called from inside a libxl's event handling
+ * code and thus only when libxl is running, for example from
+ * within libxl_event_wait. (libxl uses the self-pipe trick
+ * to implement this.)
+ *
+ * childproc_exited_callback may call back into libxl, but it
+ * is best to avoid making long-running libxl calls as that might
+ * stall the calling event loop while the nested operation
+ * completes.
+ */
+ int (*reaped_callback)(pid_t, int status, void *user);
+} libxl_childproc_hooks;
+
+/* hooks may be 0 in which is equivalent to &{ libxl_sigchld_owner_libxl, 0, 0 }
+ *
+ * May not be called when libxl might have any child processes, or the
+ * behaviour is undefined. So it is best to call this at
+ * initialisation.
+ */
+void libxl_childproc_setmode(libxl_ctx *ctx, const libxl_childproc_hooks *hooks,
+ void *user);
+
+/*
+ * This function is for an application which owns SIGCHLD and which
+ * therefore reaps all of the process's children.
+ *
+ * May be called only by an application which has called setmode with
+ * chldowner == libxl_sigchld_owner_mainloop. If pid was a process started
+ * by this instance of libxl, returns 0 after doing whatever
+ * processing is appropriate. Otherwise silently returns
+ * ERROR_UNKNOWN_CHILD. No other error returns are possible.
+ *
+ * May NOT be called from within a signal handler which might
+ * interrupt any libxl operation. The application will almost
+ * certainly need to use the self-pipe trick (or a working pselect or
+ * ppoll) to implement this.
+ */
+int libxl_childproc_reaped(libxl_ctx *ctx, pid_t, int status);
+
+
/*
* An application which initialises a libxl_ctx in a parent process
* and then forks a child which does not quickly exec, must