From: Ian Jackson <ian.jackson@eu.citrix.com>
To: xen-devel@lists.xen.org
Cc: Jim Fehlig <jfehlig@suse.com>,
Ian Jackson <Ian.Jackson@eu.citrix.com>,
Ian Campbell <ian.campbell@citrix.com>,
Bamvor Jian Zhang <bjzhang@suse.com>
Subject: [PATCH 3/3] libxl: event system: properly register the SIGCHLD self-pipe
Date: Tue, 5 Nov 2013 19:19:13 +0000 [thread overview]
Message-ID: <1383679153-3137-4-git-send-email-ian.jackson@eu.citrix.com> (raw)
In-Reply-To: <1383679153-3137-1-git-send-email-ian.jackson@eu.citrix.com>
An application which uses libxl_osevent_register_hooks, and doesn't
use libxl_sigchld_owner_mainloop, would never properly experience the
deaths of its (libxl) children.
This is because the SIGCHLD self pipe would be handled using ad-hoc
code in beforepoll_internal and afterpoll_internal. However, this is
no good if application is using the fd registration system instead; in
that case these functions would not be called and nothing would deal
with readability of the self pipe.
Fix this as follows:
The SIGCHLD self pipe now is now dealt with by a standard libxl__ev_fd
handler, which is registered and deregistered along with the SIGCHLD
handler itself. The handler function subsumes the ad-hoc response
code removed from beforepoll_internal, and the functionality of
libxl__fork_selfpipe_woken.
This is also tidier as the SIGCHLD self pipe is no longer touched
outside libxl_fork.c other than in ctx initialisation and teardown.
(The ad-hoc arrangements for poller->wakeup_pipe in
beforepoll_internal and afterpoll_internal are OK because the
libxl__poller mechanism exists to wake up threads which are sitting
inside libxl's poll loop, so is not applicable to the application's
event loop.)
Reported-by: Bamvor Jian Zhang <bjzhang@suse.com>
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Bamvor Jian Zhang <bjzhang@suse.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Jim Fehlig <jfehlig@suse.com>
---
tools/libxl/libxl.c | 2 ++
tools/libxl/libxl_event.c | 12 ----------
tools/libxl/libxl_fork.c | 52 ++++++++++++++++++++++++++++++++----------
tools/libxl/libxl_internal.h | 3 +--
4 files changed, 43 insertions(+), 26 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index d0a87d2..23e5a40 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -65,6 +65,7 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
ctx->childproc_user = 0;
ctx->sigchld_selfpipe[0] = -1;
+ libxl__ev_fd_init(&ctx->sigchld_selfpipe_efd);
/* The mutex is special because we can't idempotently destroy it */
@@ -146,6 +147,7 @@ int libxl_ctx_free(libxl_ctx *ctx)
for (i = 0; i < ctx->watch_nslots; i++)
assert(!libxl__watch_slot_contents(gc, i));
libxl__ev_fd_deregister(gc, &ctx->watch_efd);
+ libxl__ev_fd_deregister(gc, &ctx->sigchld_selfpipe_efd);
/* Now there should be no more events requested from the application: */
diff --git a/tools/libxl/libxl_event.c b/tools/libxl/libxl_event.c
index 0fe4428..b732816 100644
--- a/tools/libxl/libxl_event.c
+++ b/tools/libxl/libxl_event.c
@@ -774,10 +774,6 @@ static int beforepoll_internal(libxl__gc *gc, libxl__poller *poller,
\
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{ \
@@ -999,14 +995,6 @@ static void afterpoll_internal(libxl__egc *egc, libxl__poller *poller,
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)
diff --git a/tools/libxl/libxl_fork.c b/tools/libxl/libxl_fork.c
index 335ca40..aad1652 100644
--- a/tools/libxl/libxl_fork.c
+++ b/tools/libxl/libxl_fork.c
@@ -155,6 +155,9 @@ int libxl__carefd_fd(const libxl__carefd *cf)
* 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 e = libxl__self_pipe_wakeup(sigchld_owner->sigchld_selfpipe[1]);
@@ -175,10 +178,18 @@ static void sigchld_removehandler_core(void)
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 */
@@ -195,6 +206,15 @@ 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) {
@@ -235,18 +255,9 @@ static bool chldmode_ours(libxl_ctx *ctx, bool creating)
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))
+ if (!chldmode_ours(CTX, 0))
libxl__sigchld_removehandler(gc);
}
@@ -293,12 +304,29 @@ int libxl_childproc_reaped(libxl_ctx *ctx, pid_t pid, int status)
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);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index bd2eeed..1e60333 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -353,6 +353,7 @@ struct libxl__ctx {
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;
@@ -840,8 +841,6 @@ _hidden void libxl__poller_wakeup(libxl__egc *egc, libxl__poller *p);
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 */
--
1.7.10.4
next prev parent reply other threads:[~2013-11-05 19:19 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-05 9:22 [PATCH 0/2] question on libxl ao Bamvor Jian Zhang
2013-11-05 9:22 ` [PATCH 1/2] expose child fd in order to handle child exit in libvirt Bamvor Jian Zhang
2013-11-05 16:05 ` [PATCH 0/2] question on libxl ao [and 1 more messages] Ian Jackson
2013-11-05 19:19 ` [PATCH 0/3] libxl: event system: SIGCHLD related fixes Ian Jackson
2013-11-05 19:19 ` [PATCH 1/3] libxl: event system: pass gc, not just ctx, to internal sigchld manipulators Ian Jackson
2013-11-06 10:30 ` Ian Campbell
2013-11-05 19:19 ` [PATCH 2/3] libxl: event system: Make libxl_sigchld_owner_libxl_always work Ian Jackson
2013-11-06 10:34 ` Ian Campbell
2013-11-05 19:19 ` Ian Jackson [this message]
2013-11-06 10:36 ` [PATCH 3/3] libxl: event system: properly register the SIGCHLD self-pipe Ian Campbell
2013-11-06 10:38 ` [PATCH 0/3] libxl: event system: SIGCHLD related fixes Ian Campbell
2013-11-06 12:08 ` Ian Jackson
2013-11-12 18:27 ` [PATCH v2 " Ian Jackson
2013-11-12 18:27 ` [PATCH 1/3] libxl: event system: pass gc, not just ctx, to internal sigchld manipulators Ian Jackson
2013-11-12 18:27 ` [PATCH 2/3] libxl: event system: Make libxl_sigchld_owner_libxl_always work Ian Jackson
2013-11-12 18:27 ` [PATCH 3/3] libxl: event system: properly register the SIGCHLD self-pipe Ian Jackson
2013-11-13 10:02 ` [PATCH v2 0/3] libxl: event system: SIGCHLD related fixes Ian Campbell
2013-11-21 18:49 ` Ian Jackson
2013-11-20 4:28 ` Jim Fehlig
2013-11-20 15:22 ` 答复: " Bamvor Jian Zhang
2013-11-20 16:40 ` 答复: Re: [PAT CH " Ian Jackson
2013-11-07 3:00 ` [PATCH 0/2] question on libxl ao [and 1 more messages] Bamvor Jian Zhang
2013-11-05 19:23 ` [PATCH 0/2] question on libxl ao [and 1 more messages] " Ian Jackson
2013-11-05 9:22 ` [PATCH 2/2] call ao_how callback explicitly Bamvor Jian Zhang
2013-11-05 15:51 ` Ian Jackson
2013-11-07 14:51 ` Bamvor Jian Zhang
2013-11-07 17:03 ` Ian Jackson
2013-11-08 13:17 ` Bamvor Jian Zhang
2013-11-08 16:07 ` Ian Jackson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1383679153-3137-4-git-send-email-ian.jackson@eu.citrix.com \
--to=ian.jackson@eu.citrix.com \
--cc=bjzhang@suse.com \
--cc=ian.campbell@citrix.com \
--cc=jfehlig@suse.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).