]> xenbits.xensource.com Git - xen.git/commitdiff
libxl: child processes cleanups
authorIan Jackson <ian.jackson@eu.citrix.com>
Fri, 11 May 2012 17:59:06 +0000 (18:59 +0100)
committerIan Jackson <ian.jackson@eu.citrix.com>
Fri, 11 May 2012 17:59:06 +0000 (18:59 +0100)
Abolish libxl_fork.  Its only callers were in xl.  Its functionality
is now moved elsewhere, as follows:

* The "logging version of fork", which is what it was billed as, is now
  xl_fork, which also dies on failure.

* Closing the xenstore handle in the child is now done in
  libxl__ev_child_fork, which is the only remaining place where fork
  is called in libxl.

* We provide a new function libxl__ev_child_xenstore_reopen for
  in-libxl children to make the ctx useable for xenstore again.

* Consequently libxl__spawn_record_pid now no longer needs to mess
  about with its own xenstore handle.  As a bonus it can now just use
  libxl__xs_write.

Also, since we have now converted all the forkers in libxl, we can
always honour the fork_replacement childproc hook - so do so.

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>
tools/libxl/libxl_exec.c
tools/libxl/libxl_fork.c
tools/libxl/libxl_internal.h
tools/libxl/libxl_utils.c
tools/libxl/libxl_utils.h
tools/libxl/xl.c
tools/libxl/xl.h
tools/libxl/xl_cmdimpl.c

index 882c048faf2548692545e73dd59205d50fd862b9..b46b8939ae1e77696597270c9c2db9851bec2cbd 100644 (file)
@@ -127,34 +127,23 @@ void libxl_report_child_exitstatus(libxl_ctx *ctx,
     }
 }
 
-int libxl__spawn_record_pid(libxl__gc *gc, libxl__spawn_state *spawn,
-                            pid_t innerchild)
+int libxl__spawn_record_pid(libxl__gc *gc, libxl__spawn_state *spawn, pid_t pid)
 {
-    struct xs_handle *xsh = NULL;
-    const char *pid = NULL;
-    int rc, xsok;
+    int r, rc;
 
-    pid = GCSPRINTF("%d", innerchild);
+    rc = libxl__ev_child_xenstore_reopen(gc, spawn->what);
+    if (rc) goto out;
 
-    /* we mustn't use the parent's handle in the child */
-    xsh = xs_daemon_open();
-    if (!xsh) {
-        LOGE(ERROR, "write %s = %s: xenstore reopen failed",
-             spawn->pidpath, pid);
-        rc = ERROR_FAIL;  goto out;
-    }
-
-    xsok = xs_write(xsh, XBT_NULL, spawn->pidpath, pid, strlen(pid));
-    if (!xsok) {
+    r = libxl__xs_write(gc, XBT_NULL, spawn->pidpath, "%d", pid);
+    if (r) {
         LOGE(ERROR,
-             "write %s = %s: xenstore write failed", spawn->pidpath, pid);
+             "write %s = %d: xenstore write failed", spawn->pidpath, pid);
         rc = ERROR_FAIL;  goto out;
     }
 
     rc = 0;
 
 out:
-    if (xsh) xs_daemon_close(xsh);
     return rc ? SIGTERM : 0;
 }
 
@@ -302,7 +291,15 @@ int libxl__spawn_spawn(libxl__egc *egc, libxl__spawn_state *ss)
 
     /* we are now the middle process */
 
-    child = fork();
+    pid_t (*fork_replacement)(void*) =
+        CTX->childproc_hooks
+        ? CTX->childproc_hooks->fork_replacement
+        : 0;
+    child =
+        fork_replacement
+        ? fork_replacement(CTX->childproc_user)
+        : fork();
+
     if (child == -1)
         exit(255);
     if (!child) {
index 35c8bdd7f396971664324cd3626a77a55bf1a3ed..9ff99e0bfb4ba34a0a847d0d977696efb765150d 100644 (file)
@@ -347,7 +347,12 @@ pid_t libxl__ev_child_fork(libxl__gc *gc, libxl__ev_child *ch,
 
     if (!pid) {
         /* woohoo! */
-        return 0; /* Yes, CTX is left locked in the child. */
+        if (CTX->xsh) {
+            xs_daemon_destroy_postfork(CTX->xsh);
+            CTX->xsh = NULL; /* turns mistakes into crashes */
+        }
+        /* Yes, CTX is left locked in the child. */
+        return 0;
     }
 
     ch->pid = pid;
@@ -395,6 +400,24 @@ const libxl_childproc_hooks libxl__childproc_default_hooks = {
     libxl_sigchld_owner_libxl, 0, 0
 };
 
+int libxl__ev_child_xenstore_reopen(libxl__gc *gc, const char *what) {
+    int rc;
+
+    assert(!CTX->xsh);
+    CTX->xsh = xs_daemon_open();
+    if (!CTX->xsh) {
+        LOGE(ERROR, "%s: xenstore reopen failed", what);
+        rc = ERROR_FAIL;  goto out;
+    }
+
+    libxl_fd_set_cloexec(CTX, xs_fileno(CTX->xsh), 1);
+
+    return 0;
+
+ out:
+    return rc;
+}
+
 /*
  * Local variables:
  * mode: C
index 9f3f759fea6a9d48c89ebdc25a9db120a27c359c..83fabea6ef8148d9be0e4b685afdc5d84d8c8239 100644 (file)
@@ -640,6 +640,11 @@ static inline void libxl__ev_child_init(libxl__ev_child *childw_out)
 static inline int libxl__ev_child_inuse(libxl__ev_child *childw_out)
                 { return childw_out->pid >= 0; }
 
+/* Useable (only) in the child to once more make the ctx useable for
+ * xenstore operations.  logs failure in the form "what: <error
+ * message>". */
+_hidden int libxl__ev_child_xenstore_reopen(libxl__gc *gc, const char *what);
+
 
 /*
  * Other event-handling support provided by the libxl event core to
index f0d94c6828bf1b4cec63e119e7f3370d56c892e1..858410e7bc8e4284b5e5e063624ad6409643a83b 100644 (file)
@@ -444,27 +444,6 @@ int libxl__remove_directory(libxl__gc *gc, const char *dirpath)
     return rc;
 }
 
-pid_t libxl_fork(libxl_ctx *ctx)
-{
-    pid_t pid;
-
-    pid = fork();
-    if (pid == -1) {
-        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "fork failed");
-        return -1;
-    }
-
-    if (!pid) {
-        if (ctx->xsh) xs_daemon_destroy_postfork(ctx->xsh);
-        ctx->xsh = 0;
-        /* This ensures that anyone who forks but doesn't exec,
-         * and doesn't reinitialise the libxl_ctx, is OK.
-         * It also means they can safely call libxl_ctx_free. */
-    }
-
-    return pid;
-}
-
 int libxl_pipe(libxl_ctx *ctx, int pipes[2])
 {
     if (pipe(pipes) < 0) {
index 2b47622171a9d4e99bd7b01e2af3b08001c9ba12..74beb52a6766d150c0b213e71add389dd243f179 100644 (file)
@@ -47,9 +47,8 @@ int libxl_write_exactly(libxl_ctx *ctx, int fd, const void *data,
    * logged using filename (which is only used for logging) and what
    * (which may be 0). */
 
-pid_t libxl_fork(libxl_ctx *ctx);
 int libxl_pipe(libxl_ctx *ctx, int pipes[2]);
-  /* Just like fork(2), pipe(2), but log errors. */
+  /* Just like pipe(2), but log errors. */
 
 void libxl_report_child_exitstatus(libxl_ctx *ctx, xentoollog_level,
                                    const char *what, pid_t pid, int status);
index a6ffd25ff7cac742084cb227afd50d0ce1eaccd0..d4db1f8b8b37ae29f4e224a76ec99a7789b16108 100644 (file)
@@ -105,6 +105,18 @@ void postfork(void)
     }
 }
 
+pid_t xl_fork(libxl_ctx *ctx) {
+    pid_t pid;
+
+    pid = fork();
+    if (pid == -1) {
+        perror("fork failed");
+        exit(-1);
+    }
+
+    return pid;
+}
+
 int main(int argc, char **argv)
 {
     int opt = 0;
index f0d0ec8870d1dc67cb148a8a87a5ccdf4fbe3f38..2b6714af3683f5634b7fcbb1c20938c9d2a43b88 100644 (file)
@@ -104,6 +104,7 @@ struct cmd_spec *cmdtable_lookup(const char *s);
 
 extern libxl_ctx *ctx;
 extern xentoollog_logger_stdiostream *logger;
+pid_t xl_fork(libxl_ctx *ctx); /* like fork, but prints and dies if it fails */
 void postfork(void);
 
 /* global options */
index b91a2d5911e9b767c62c869d54b21c9300bdf1b9..efaf3de04750d6a5631ca80334795bb543720996 100644 (file)
@@ -1736,7 +1736,7 @@ start:
         pid_t child1, got_child;
         int nullfd;
 
-        child1 = libxl_fork(ctx);
+        child1 = xl_fork(ctx);
         if (child1) {
             printf("Daemon running with PID %d\n", child1);
 
@@ -2779,8 +2779,7 @@ static void migrate_domain(const char *domain_spec, const char *rune,
     MUST( libxl_pipe(ctx, sendpipe) );
     MUST( libxl_pipe(ctx, recvpipe) );
 
-    child = libxl_fork(ctx);
-    if (child==-1) exit(1);
+    child = xl_fork(ctx);
 
     if (!child) {
         dup2(sendpipe[0], 0);