[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 06/12] libxl: fork: Provide libxl_childproc_sigchld_occurred
Applications exist which don't keep track of all their child processes in a manner suitable for coherent dispatch of their termination. In such a situation, nothing in the whole process may call wait, or waitpid(-1,,). Doing so reaps processes belonging to other parts of the application and there is then no way to deliver the exit status to the right place. To facilitate this, provide a facility for such an application to ask libxl to call waitpid on each of its children individually. Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> Cc: Jim Fehlig <jfehlig@xxxxxxxx> Cc: Ian Campbell <Ian.Campbell@xxxxxxxxxx> Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- tools/libxl/libxl_event.h | 29 +++++++++++++++++++++++++---- tools/libxl/libxl_fork.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/tools/libxl/libxl_event.h b/tools/libxl/libxl_event.h index 4f72c4b..3c93955 100644 --- a/tools/libxl/libxl_event.h +++ b/tools/libxl/libxl_event.h @@ -482,9 +482,10 @@ typedef enum { * all children, including those not spawned by libxl. */ 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. */ + /* Application promises to discover when SIGCHLD occurs and call + * libxl_childproc_exited or libxl_childproc_sigchld_occurred (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 @@ -542,7 +543,8 @@ void libxl_childproc_setmode(libxl_ctx *ctx, const libxl_childproc_hooks *hooks, /* * This function is for an application which owns SIGCHLD and which - * therefore reaps all of the process's children. + * reaps all of the process's children, and dispatches the exit status + * to the correct place inside the application. * * May be called only by an application which has called setmode with * chldowner == libxl_sigchld_owner_mainloop. If pid was a process started @@ -558,6 +560,25 @@ void libxl_childproc_setmode(libxl_ctx *ctx, const libxl_childproc_hooks *hooks, int libxl_childproc_reaped(libxl_ctx *ctx, pid_t, int status) LIBXL_EXTERNAL_CALLERS_ONLY; +/* + * This function is for an application which owns SIGCHLD but which + * doesn't keep track of all of its own children in a manner suitable + * for reaping all of them and then dispatching them. + * + * Such an the application must notify libxl, by calling this + * function, that a SIGCHLD occurred. libxl will then check all its + * children, reap any that are ready, and take any action necessary - + * but it will not reap anything else. + * + * May be called only by an application which has called setmode with + * chldowner == libxl_sigchld_owner_mainloop. + * + * May NOT be called from within a signal handler which might + * interrupt any libxl operation (just like libxl_childproc_reaped). + */ +void libxl_childproc_sigchld_occurred(libxl_ctx *ctx) + LIBXL_EXTERNAL_CALLERS_ONLY; + /* * An application which initialises a libxl_ctx in a parent process diff --git a/tools/libxl/libxl_fork.c b/tools/libxl/libxl_fork.c index 85db2fb..b2325e0 100644 --- a/tools/libxl/libxl_fork.c +++ b/tools/libxl/libxl_fork.c @@ -330,6 +330,51 @@ int libxl_childproc_reaped(libxl_ctx *ctx, pid_t pid, int status) return rc; } +static void childproc_checkall(libxl__egc *egc) +{ + EGC_GC; + libxl__ev_child *ch; + + for (;;) { + int status; + pid_t got; + + LIBXL_LIST_FOREACH(ch, &CTX->children, entry) { + got = checked_waitpid(egc, ch->pid, &status); + if (got) + goto found; + } + /* not found */ + return; + + found: + if (got == -1) { + LIBXL__EVENT_DISASTER + (egc, "waitpid() gave ECHILD but we have a child", + ECHILD, 0); + /* it must have finished but we don't know its status */ + status = 255<<8; /* no wait.h macro for this! */ + assert(WIFEXITED(status)); + assert(WEXITSTATUS(status)==255); + assert(!WIFSIGNALED(status)); + assert(!WIFSTOPPED(status)); + } + childproc_reaped_ours(egc, ch, status); + /* we need to restart the loop, as children may have been edited */ + } +} + +void libxl_childproc_sigchld_occurred(libxl_ctx *ctx) +{ + EGC_INIT(ctx); + CTX_LOCK; + assert(CTX->childproc_hooks->chldowner + == libxl_sigchld_owner_mainloop); + childproc_checkall(egc); + CTX_UNLOCK; + EGC_FREE; +} + static void sigchld_selfpipe_handler(libxl__egc *egc, libxl__ev_fd *ev, int fd, short events, short revents) { -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |