\
REQUIRE_FD(poller->wakeup_pipe[0], POLLIN, BODY); \
\
- int selfpipe = libxl__fork_selfpipe_active(CTX); \
- if (selfpipe >= 0) \
- REQUIRE_FD(selfpipe, POLLIN, BODY); \
- \
}while(0)
#define REQUIRE_FD(req_fd_, req_events_, BODY) do{ \
if (e) LIBXL__EVENT_DISASTER(egc, "read wakeup", e, 0);
}
- int selfpipe = libxl__fork_selfpipe_active(CTX);
- if (selfpipe >= 0 &&
- afterpoll_check_fd(poller,fds,nfds, selfpipe, POLLIN)) {
- int e = libxl__self_pipe_eatall(selfpipe);
- if (e) LIBXL__EVENT_DISASTER(egc, "read sigchld pipe", e, 0);
- libxl__fork_selfpipe_woken(egc);
- }
-
for (;;) {
libxl__ev_time *etime = LIBXL_TAILQ_FIRST(&CTX->etimes);
if (!etime)
* Actual child process handling
*/
+static void sigchld_selfpipe_handler(libxl__egc *egc, libxl__ev_fd *ev,
+ int fd, short events, short revents);
+
static void sigchld_handler(int signo)
{
int esave = errno;
void libxl__sigchld_removehandler(libxl__gc *gc) /* non-reentrant */
{
+ int rc;
+
atfork_lock();
if (sigchld_owner == CTX)
sigchld_removehandler_core();
atfork_unlock();
+
+ if (libxl__ev_fd_isregistered(&CTX->sigchld_selfpipe_efd)) {
+ rc = libxl__ev_fd_modify(gc, &CTX->sigchld_selfpipe_efd, 0);
+ if (rc)
+ libxl__ev_fd_deregister(gc, &CTX->sigchld_selfpipe_efd);
+ }
}
int libxl__sigchld_installhandler(libxl__gc *gc) /* non-reentrant */
goto out;
}
}
+ if (!libxl__ev_fd_isregistered(&CTX->sigchld_selfpipe_efd)) {
+ rc = libxl__ev_fd_register(gc, &CTX->sigchld_selfpipe_efd,
+ sigchld_selfpipe_handler,
+ CTX->sigchld_selfpipe[0], POLLIN);
+ if (rc) goto out;
+ } else {
+ rc = libxl__ev_fd_modify(gc, &CTX->sigchld_selfpipe_efd, POLLIN);
+ if (rc) goto out;
+ }
atfork_lock();
if (sigchld_owner != CTX) {
abort();
}
-int libxl__fork_selfpipe_active(libxl_ctx *ctx)
-{
- /* Returns the fd to read, or -1 */
- if (!chldmode_ours(ctx, 0))
- return -1;
-
- return ctx->sigchld_selfpipe[0];
-}
-
static void perhaps_removehandler(libxl__gc *gc)
{
if (!chldmode_ours(CTX, 0))
return rc;
}
-void libxl__fork_selfpipe_woken(libxl__egc *egc)
+static void sigchld_selfpipe_handler(libxl__egc *egc, libxl__ev_fd *ev,
+ int fd, short events, short revents)
{
/* May make callbacks into the application for child processes.
- * ctx must be locked EXACTLY ONCE */
+ * So, this function may unlock and relock the CTX. This is OK
+ * because event callback functions are always called with the CTX
+ * locked exactly once, and from code which copes with reentrancy.
+ * (See also the comment in afterpoll_internal.) */
EGC_GC;
+ int selfpipe = CTX->sigchld_selfpipe[0];
+
+ if (revents & ~POLLIN) {
+ LOG(ERROR, "unexpected poll event 0x%x on SIGCHLD self pipe", revents);
+ LIBXL__EVENT_DISASTER(egc,
+ "unexpected poll event on SIGCHLD self pipe",
+ 0, 0);
+ }
+ assert(revents & POLLIN);
+
+ int e = libxl__self_pipe_eatall(selfpipe);
+ if (e) LIBXL__EVENT_DISASTER(egc, "read sigchld pipe", e, 0);
+
while (chldmode_ours(CTX, 0) /* in case the app changes the mode */) {
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
const libxl_childproc_hooks *childproc_hooks;
void *childproc_user;
int sigchld_selfpipe[2]; /* [0]==-1 means handler not installed */
+ libxl__ev_fd sigchld_selfpipe_efd;
LIBXL_LIST_HEAD(, libxl__ev_child) children;
libxl_version_info version_info;
extern const libxl_childproc_hooks libxl__childproc_default_hooks;
int libxl__sigchld_installhandler(libxl__gc*); /* non-reentrant; logs errs */
void libxl__sigchld_removehandler(libxl__gc*); /* non-reentrant */
-int libxl__fork_selfpipe_active(libxl_ctx *ctx); /* returns read fd or -1 */
-void libxl__fork_selfpipe_woken(libxl__egc *egc);
int libxl__self_pipe_wakeup(int fd); /* returns 0 or -1 setting errno */
int libxl__self_pipe_eatall(int fd); /* returns 0 or -1 setting errno */