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@eu.citrix.com>
Cc: Jim Fehlig <jfehlig@suse.com>
Cc: Ian Campbell <Ian.Campbell@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
Ian Jackson authored and Ian Jackson committed 2014-02-06 14:20:19 +00:00
1 parent 7916a9023c
commit ee84b79fbd
2 files changed
+70 -4

No files matched your search

+25 -4
View File
@@ -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
+45
View File
@@ -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)
{
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.