WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] libxenlight: check for early failures of

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] libxenlight: check for early failures of qemu-dm
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sun, 22 Nov 2009 23:35:37 -0800
Delivery-date: Sun, 22 Nov 2009 23:37:15 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1258959711 0
# Node ID 2f7cb671ef3846bc252e7c72fe88b9264f02149f
# Parent  20063cea1606072ee5f69669daaf5a4e8db98ca2
libxenlight: check for early failures of qemu-dm

This patch makes xl create check whether qemu-dm has started
correctly, and causes it to fail immediately with appropriate errors
if not.  There are other bugfixes too.

More specifically:

 * libxl_create_device_model forks twice rather than once so that the
   process which calls libxl does not end up being the actual parent
   of qemu.  That avoids the need for the qemu-dm process to be reaped
   at some indefinite time in the future.

 * The first fork generates an intermediate process which is
   responsible for writing the qemu-dm pid to xenstore and then merely
   waits to collect and report on qemu-dm's exit status during
   startup.  New arguments to libxl_create_device_model allow the
   preservation of its pid so that a later call can check whether the
   startup is successful.

 * The core of this functionality (the double fork, waitpid, signal
   handling and so forth) is abstracted away into a new facility
   libxl_spawn_... in libxl_exec.c.

Consequential changes:

 * libxl_wait_for_device_model now takes a callback function parameter
   which is called repeatedly in the loop iteration and allows the
   caller to abort the wait.

 * libxl_exec no longer calls fork; there is a new libxl_fork.

 * There is a hook to override waitpid, which will be necessary for
   some callers.

Remaining problems and other issues I noticed or we found:

 * The error handling is rather inconsistent still and lacking in
   places.

 * destroy_device_model can kill random dom0 processes (!)

Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
---
 tools/libxl/libxl.c          |  114 ++++++++++++++++++++-----
 tools/libxl/libxl.h          |   20 ++++
 tools/libxl/libxl_device.c   |   11 ++
 tools/libxl/libxl_exec.c     |  189 +++++++++++++++++++++++++++++++++++++++----
 tools/libxl/libxl_internal.h |   49 ++++++++++-
 tools/libxl/osdeps.c         |    2 
 tools/libxl/xl.c             |   21 ++++
 7 files changed, 357 insertions(+), 49 deletions(-)

diff -r 20063cea1606 -r 2f7cb671ef38 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Mon Nov 23 07:00:08 2009 +0000
+++ b/tools/libxl/libxl.c       Mon Nov 23 07:01:51 2009 +0000
@@ -23,10 +23,12 @@
 #include <sys/types.h>
 #include <fcntl.h>
 #include <sys/select.h>
+#include <sys/wait.h>
 #include <signal.h>
 #include <unistd.h> /* for write, unlink and close */
 #include <stdint.h>
 #include <inttypes.h>
+#include <assert.h>
 
 #include "libxl.h"
 #include "libxl_utils.h"
@@ -43,6 +45,8 @@ int libxl_ctx_init(struct libxl_ctx *ctx
 
     ctx->xch = xc_interface_open();
     ctx->xsh = xs_daemon_open();
+
+    ctx->waitpid_instead= libxl_waitpid_instead_default;
     return 0;
 }
 
@@ -520,23 +524,48 @@ static char ** libxl_build_device_model_
     return (char **) flexarray_contents(dm_args);
 }
 
+struct libxl_device_model_starting {
+    struct libxl_spawn_starting for_spawn; /* first! */
+    char *dom_path; /* from libxl_malloc, only for dm_xenstore_record_pid */
+    int domid;
+};
+
+void dm_xenstore_record_pid(struct libxl_ctx *ctx, void *for_spawn,
+                            pid_t innerchild) {
+    struct libxl_device_model_starting *starting = for_spawn;
+    struct libxl_ctx clone;
+    char *kvs[3];
+    int rc;
+
+    clone = *ctx;
+    clone.xsh = xs_daemon_open();
+    /* we mustn't use the parent's handle in the child */
+
+    kvs[0] = "image/device-model-pid";
+    kvs[1] = libxl_sprintf(ctx, "%d", innerchild);
+    kvs[2] = NULL;
+    rc = libxl_xs_writev(ctx, XBT_NULL, starting->dom_path, kvs);
+    if (rc) XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
+                         "Couldn't record device model pid %ld at %s/%s",
+                         (unsigned long)innerchild, starting->dom_path, kvs);
+}
+
 int libxl_create_device_model(struct libxl_ctx *ctx,
                               libxl_device_model_info *info,
-                              libxl_device_nic *vifs, int num_vifs)
-{
-    char *dom_path, *path, *logfile, *logfile_new;
-    char *kvs[3];
+                              libxl_device_nic *vifs, int num_vifs,
+                              libxl_device_model_starting **starting_r)
+{
+    char *path, *logfile, *logfile_new;
     struct stat stat_buf;
-    int logfile_w, null, pid;
-    int i;
+    int logfile_w, null;
+    int i, rc;
     char **args;
+    struct libxl_spawn_starting buf_spawn, *for_spawn;
+
+    *starting_r= 0;
 
     args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
     if (!args)
-        return ERROR_FAIL;
-
-    dom_path = libxl_xs_get_dompath(ctx, info->domid);
-    if (!dom_path)
         return ERROR_FAIL;
 
     path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid);
@@ -559,17 +588,53 @@ int libxl_create_device_model(struct lib
     logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", 
info->dom_name);
     logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
     null = open("/dev/null", O_RDONLY);
-    pid = libxl_exec(ctx, null, logfile_w, logfile_w, info->device_model, 
args);
+
+    if (starting_r) {
+        *starting_r= libxl_calloc(ctx, sizeof(**starting_r), 1);
+        if (!*starting_r) return ERROR_NOMEM;
+        (*starting_r)->domid= info->domid;
+
+        (*starting_r)->dom_path = libxl_xs_get_dompath(ctx, info->domid);
+        if (!(*starting_r)->dom_path) { free(*starting_r); return ERROR_FAIL; }
+
+        for_spawn= &(*starting_r)->for_spawn;
+    } else {
+        for_spawn= &buf_spawn;
+    }
+    rc = libxl_spawn_spawn(ctx, for_spawn, "device model",
+                           dm_xenstore_record_pid);
+    if (rc < 0) goto xit;
+    if (!rc) { /* inner child */
+        libxl_exec(ctx, null, logfile_w, logfile_w,
+                   info->device_model, args);
+    }
+
+    rc = 0;
+ xit:
     close(null);
     close(logfile_w);
 
-    kvs[0] = libxl_sprintf(ctx, "image/device-model-pid");
-    kvs[1] = libxl_sprintf(ctx, "%d", pid);
-    kvs[2] = NULL;
-    libxl_xs_writev(ctx, XBT_NULL, dom_path, kvs);
-
-    return 0;
-}
+    return rc;
+}
+
+int libxl_detach_device_model(struct libxl_ctx *ctx,
+                              libxl_device_model_starting *starting) {
+    int rc;
+    rc = libxl_spawn_detach(ctx, &starting->for_spawn);
+    libxl_free(ctx, starting);
+    return rc;
+}
+
+
+int libxl_confirm_device_model_startup(struct libxl_ctx *ctx,
+                                       libxl_device_model_starting *starting) {
+    int problem = libxl_wait_for_device_model(ctx, starting->domid, "running",
+                                              libxl_spawn_check,
+                                              &starting->for_spawn);
+    int detach = libxl_detach_device_model(ctx, starting);
+    return problem ? problem : detach;
+}
+
 
 
/******************************************************************************/
 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk)
@@ -917,12 +982,13 @@ static int libxl_build_xenpv_qemu_args(s
 }
 
 int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb,
-                            int num_console, libxl_device_console *console)
+                            int num_console, libxl_device_console *console,
+                            struct libxl_device_model_starting **starting_r)
 {
     libxl_device_model_info info;
 
     libxl_build_xenpv_qemu_args(ctx, vfb, num_console, console, &info);
-    libxl_create_device_model(ctx, &info, NULL, 0);
+    libxl_create_device_model(ctx, &info, NULL, 0, starting_r);
     return 0;
 }
 
@@ -1195,7 +1261,7 @@ int libxl_device_pci_add(struct libxl_ct
 
     hvm = is_hvm(ctx, domid);
     if (hvm) {
-        if (libxl_wait_for_device_model(ctx, domid, "running") < 0) {
+        if (libxl_wait_for_device_model(ctx, domid, "running", 0,0) < 0) {
             return -1;
         }
         snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/state", 
domid);
@@ -1209,7 +1275,7 @@ int libxl_device_pci_add(struct libxl_ct
                            pcidev->bus, pcidev->dev, pcidev->func);
         snprintf(path, sizeof(path), 
"/local/domain/0/device-model/%d/command", domid);
         xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
-        if (libxl_wait_for_device_model(ctx, domid, "pci-inserted") < 0)
+        if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", 0,0) < 0)
             XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
         snprintf(path, sizeof(path), 
"/local/domain/0/device-model/%d/parameter", domid);
         vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
@@ -1283,7 +1349,7 @@ int libxl_device_pci_remove(struct libxl
 
     hvm = is_hvm(ctx, domid);
     if (hvm) {
-        if (libxl_wait_for_device_model(ctx, domid, "running") < 0) {
+        if (libxl_wait_for_device_model(ctx, domid, "running", 0,0) < 0) {
             return -1;
         }
         snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/state", 
domid);
@@ -1293,7 +1359,7 @@ int libxl_device_pci_remove(struct libxl
                        pcidev->bus, pcidev->dev, pcidev->func);
         snprintf(path, sizeof(path), 
"/local/domain/0/device-model/%d/command", domid);
         xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem"));
-        if (libxl_wait_for_device_model(ctx, domid, "pci-removed") < 0) {
+        if (libxl_wait_for_device_model(ctx, domid, "pci-removed", 0,0) < 0) {
             XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
             return -1;
         }
diff -r 20063cea1606 -r 2f7cb671ef38 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Mon Nov 23 07:00:08 2009 +0000
+++ b/tools/libxl/libxl.h       Mon Nov 23 07:01:51 2009 +0000
@@ -41,6 +41,11 @@ struct libxl_ctx {
     /* mini-GC */
     int alloc_maxsize;
     void **alloc_ptrs;
+
+    /* for callers who reap children willy-nilly; caller must only
+     * set this after libxl_init and before any other call - or
+     * may leave them untouched */
+    int (*waitpid_instead)(pid_t pid, int *status, int flags);
 };
 
 typedef struct {
@@ -235,11 +240,22 @@ struct libxl_dominfo * libxl_domain_list
 struct libxl_dominfo * libxl_domain_list(struct libxl_ctx *ctx, int 
*nb_domain);
 xc_dominfo_t * libxl_domain_infolist(struct libxl_ctx *ctx, int *nb_domain);
 
+typedef struct libxl_device_model_starting libxl_device_model_starting;
 int libxl_create_device_model(struct libxl_ctx *ctx,
                               libxl_device_model_info *info,
-                              libxl_device_nic *vifs, int num_vifs);
+                              libxl_device_nic *vifs, int num_vifs,
+                              libxl_device_model_starting **starting_r);
 int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb,
-                            int num_console, libxl_device_console *console);
+                            int num_console, libxl_device_console *console,
+                            libxl_device_model_starting **starting_r);
+  /* Caller must either: pass starting_r==0, or on successful
+   * return pass *starting_r (which will be non-0) to
+   * libxl_confirm_device_model or libxl_detach_device_model. */
+int libxl_confirm_device_model_startup(struct libxl_ctx *ctx,
+                              libxl_device_model_starting *starting);
+int libxl_detach_device_model(struct libxl_ctx *ctx,
+                              libxl_device_model_starting *starting);
+  /* DM is detached even if error is returned */
 
 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk);
 int libxl_device_disk_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid);
diff -r 20063cea1606 -r 2f7cb671ef38 tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c        Mon Nov 23 07:00:08 2009 +0000
+++ b/tools/libxl/libxl_device.c        Mon Nov 23 07:01:51 2009 +0000
@@ -287,12 +287,17 @@ int libxl_device_pci_flr(struct libxl_ct
     return -1;
 }
 
-int libxl_wait_for_device_model(struct libxl_ctx *ctx, uint32_t domid, char 
*state)
+int libxl_wait_for_device_model(struct libxl_ctx *ctx,
+                                uint32_t domid, char *state,
+                                int (*check_callback)(struct libxl_ctx *ctx,
+                                                      void *userdata),
+                                void *check_callback_userdata)
 {
     char path[50];
     char *p;
     int watchdog = 100;
     unsigned int len;
+    int rc;
 
     snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/state", 
domid);
     while (watchdog > 0) {
@@ -310,6 +315,10 @@ int libxl_wait_for_device_model(struct l
                 watchdog--;
             }
         }
+        if (check_callback) {
+            rc = check_callback(ctx, check_callback_userdata);
+            if (rc) return rc;
+        }
     }
     XL_LOG(ctx, XL_LOG_ERROR, "Device Model not ready");
     return -1;
diff -r 20063cea1606 -r 2f7cb671ef38 tools/libxl/libxl_exec.c
--- a/tools/libxl/libxl_exec.c  Mon Nov 23 07:00:08 2009 +0000
+++ b/tools/libxl/libxl_exec.c  Mon Nov 23 07:01:51 2009 +0000
@@ -18,34 +18,191 @@
 #include "libxl_osdeps.h"
 
 #include <stdio.h>
+#include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 #include "libxl.h"
 #include "libxl_internal.h"
 
-int libxl_exec(struct libxl_ctx *ctx, int stdinfd, int stdoutfd, int stderrfd,
-               char *arg0, char **args)
+pid_t libxl_fork(struct libxl_ctx *ctx)
 {
-    int pid, i;
+    pid_t pid;
 
     pid = fork();
     if (pid == -1) {
         XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "fork failed");
         return -1;
     }
-    if (pid == 0) {
-        /* child */
-        if (stdinfd != -1)
-            dup2(stdinfd, STDIN_FILENO);
-        if (stdoutfd != -1)
-            dup2(stdoutfd, STDOUT_FILENO);
-        if (stderrfd != -1)
-            dup2(stderrfd, STDERR_FILENO);
-        for (i = 4; i < 256; i++)
-            close(i);
-        execv(arg0, args);
-        exit(256);
-    }
+
     return pid;
 }
+
+void libxl_exec(struct libxl_ctx *ctx, int stdinfd, int stdoutfd, int stderrfd,
+                char *arg0, char **args)
+     /* call this in the child */
+{
+    int i;
+
+    if (stdinfd != -1)
+        dup2(stdinfd, STDIN_FILENO);
+    if (stdoutfd != -1)
+        dup2(stdoutfd, STDOUT_FILENO);
+    if (stderrfd != -1)
+        dup2(stderrfd, STDERR_FILENO);
+    for (i = 4; i < 256; i++)
+        close(i);
+    execv(arg0, args);
+    XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "exec %s failed", arg0);
+    _exit(-1);
+}
+
+void libxl_report_child_exitstatus(struct libxl_ctx *ctx,
+                                   const char *what, pid_t pid, int status) {
+    /* treats all exit statuses as errors; if that's not what you want,
+     * check status yourself first */
+
+    if (WIFEXITED(status)) {
+        int st= WEXITSTATUS(status);
+        if (st)
+            XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] exited"
+                   " with error status %d", what, (unsigned long)pid, st);
+        else
+            XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] unexpectedly"
+                   " exited status zero", what, (unsigned long)pid);
+    } else if (WIFSIGNALED(status)) {
+        int sig= WTERMSIG(status);
+        const char *str= strsignal(sig);
+        const char *coredump= WCOREDUMP(status) ? " (core dumped)" : "";
+        if (str)
+            XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] died due to"
+                   " fatal signal %s%s", what, (unsigned long)pid,
+                   str, coredump);
+        else
+            XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] died due to unknown"
+                   " fatal signal number %d%s", what, (unsigned long)pid,
+                   sig, coredump);
+    } else {
+        XL_LOG(ctx, XL_LOG_ERROR, "%s [%ld] gave unknown"
+               " wait status 0x%x", what, (unsigned long)pid, status);
+    }
+}
+
+pid_t libxl_waitpid_instead_default(pid_t pid, int *status, int flags) {
+    return waitpid(pid,status,flags);
+}
+
+
+
+int libxl_spawn_spawn(struct libxl_ctx *ctx,
+                      struct libxl_spawn_starting *for_spawn,
+                      const char *what,
+                      void (*intermediate_hook)(struct libxl_ctx *ctx,
+                                                void *for_spawn,
+                                                pid_t innerchild)) {
+    pid_t child, got;
+    int status;
+    pid_t intermediate;
+
+    if (for_spawn) {
+        for_spawn->what= strdup(what);
+        if (!for_spawn->what) return ERROR_NOMEM;
+    }
+
+    intermediate = libxl_fork(ctx);
+    if (intermediate==-1) {
+        if (for_spawn) free(for_spawn->what);
+        return ERROR_FAIL;
+    }
+    if (intermediate) {
+        /* parent */
+        if (for_spawn) for_spawn->intermediate= intermediate;
+        return 1;
+    }
+
+    /* we are now the intermediate process */
+
+    child = libxl_fork(ctx);
+    if (!child) return 0; /* caller runs child code */
+    if (child<0) exit(255);
+
+    intermediate_hook(ctx, for_spawn, child);
+
+    if (!for_spawn) _exit(0); /* just detach then */
+
+    got = ctx->waitpid_instead(child, &status, 0);
+    assert(got == child);
+
+    libxl_report_child_exitstatus(ctx, what, child, status);
+    _exit(WIFEXITED(status) ? WEXITSTATUS(status) :
+          WIFSIGNALED(status) && WTERMSIG(status)<127
+          ? WTERMSIG(status)+128 : -1);
+}
+
+static void report_spawn_intermediate_status(struct libxl_ctx *ctx,
+                                 struct libxl_spawn_starting *for_spawn,
+                                 int status) {
+    if (!WIFEXITED(status)) {
+        /* intermediate process did the logging itself if it exited */
+        char *intermediate_what=
+            libxl_sprintf(ctx,
+                          "%s intermediate process (startup monitor)",
+                          for_spawn->what);
+        libxl_report_child_exitstatus(ctx, intermediate_what,
+                                      for_spawn->intermediate, status);
+    }
+}
+
+int libxl_spawn_detach(struct libxl_ctx *ctx,
+                       struct libxl_spawn_starting *for_spawn) {
+    int r, status;
+    pid_t got;
+    int rc = 0;
+
+    if (!for_spawn) return 0;
+
+    if (for_spawn->intermediate) {
+        r = kill(for_spawn->intermediate, SIGKILL);
+        if (r) {
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
+                         "could not kill %s intermediate process [%ld]",
+                         for_spawn->what,
+                         (unsigned long)for_spawn->intermediate);
+            abort(); /* things are very wrong */
+        }
+        got = ctx->waitpid_instead(for_spawn->intermediate, &status, 0);
+        assert(got == for_spawn->intermediate);
+        if (!(WIFSIGNALED(status) && WTERMSIG(status)==SIGKILL)) {
+            report_spawn_intermediate_status(ctx, for_spawn, status);
+            rc = ERROR_FAIL;
+        }
+        for_spawn->intermediate = 0;
+    }
+
+    free(for_spawn->what);
+    for_spawn->what = 0;
+
+    return rc;
+}
+
+int libxl_spawn_check(struct libxl_ctx *ctx, void *for_spawn_void) {
+    struct libxl_spawn_starting *for_spawn = for_spawn_void;
+    pid_t got;
+    int status;
+
+    if (!for_spawn) return 0;
+
+    assert(for_spawn->intermediate);
+    got = ctx->waitpid_instead(for_spawn->intermediate, &status, WNOHANG);
+    if (!got) return 0;
+
+    assert(got == for_spawn->intermediate);
+    report_spawn_intermediate_status(ctx, for_spawn, status);
+
+    for_spawn->intermediate= 0;
+    return ERROR_FAIL;
+}
diff -r 20063cea1606 -r 2f7cb671ef38 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Mon Nov 23 07:00:08 2009 +0000
+++ b/tools/libxl/libxl_internal.h      Mon Nov 23 07:01:51 2009 +0000
@@ -135,7 +135,11 @@ int libxl_device_generic_add(struct libx
                              char **bents, char **fents);
 int libxl_device_destroy(struct libxl_ctx *ctx, char *be_path, int force);
 int libxl_devices_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
-int libxl_wait_for_device_model(struct libxl_ctx *ctx, uint32_t domid, char 
*state);
+int libxl_wait_for_device_model(struct libxl_ctx *ctx,
+                                uint32_t domid, char *state,
+                                int (*check_callback)(struct libxl_ctx *ctx,
+                                                      void *userdata),
+                                void *check_callback_userdata);
 int libxl_wait_for_backend(struct libxl_ctx *ctx, char *be_path, char *state);
 int libxl_device_pci_flr(struct libxl_ctx *ctx, unsigned int domain, unsigned 
int bus,
                          unsigned int dev, unsigned int func);
@@ -146,8 +150,47 @@ int hvm_build_set_params(int handle, uin
                          int vcpus, int store_evtchn, unsigned long 
*store_mfn);
 
 /* xl_exec */
-int libxl_exec(struct libxl_ctx *ctx, int stdinfd, int stdoutfd, int stderrfd,
-               char *arg0, char **args);
+
+ /* higher-level double-fork and separate detach eg as for device models */
+
+struct libxl_spawn_starting {
+    /* put this in your own stateu structure as returned to application */
+    /* all fields are private to libxl_spawn_... */
+    pid_t intermediate;
+    char *what; /* malloc'd in spawn_spawn */
+};
+
+int libxl_spawn_spawn(struct libxl_ctx *ctx,
+                      struct libxl_spawn_starting *for_spawn,
+                      const char *what,
+                      void (*intermediate_hook)(struct libxl_ctx *ctx,
+                                                void *for_spawn,
+                                                pid_t innerchild));
+  /* Logs errors.  A copy of "what" is taken.  Return values:
+   *  < 0   error, for_spawn need not be detached
+   *   +1   caller is now the inner child, should probably call libxl_exec
+   *    0   caller is the parent, must call detach on *for_spawn eventually
+   * Caller, may pass 0 for for_spawn, in which case no need to detach.
+   */
+int libxl_spawn_detach(struct libxl_ctx *ctx,
+                       struct libxl_spawn_starting *for_spawn);
+  /* Logs errors.  Idempotent, but only permitted after successful
+   * call to libxl_spawn_spawn, and no point calling it again if it fails. */
+int libxl_spawn_check(struct libxl_ctx *ctx,
+                      void *for_spawn);
+  /* Logs errors but also returns them.
+   * for_spawn must actually be a  struct libxl_spawn_starting*  but
+   * we take void* so you can pass this function directly to
+   * libxl_wait_for_device_model.  Caller must still call detach. */
+
+ /* low-level stuff, for synchronous subprocesses etc. */
+
+pid_t libxl_fork(struct libxl_ctx *ctx); // logs errors
+void libxl_exec(struct libxl_ctx *ctx, int stdinfd, int stdoutfd, int stderrfd,
+                char *arg0, char **args); // logs errors, never returns
+void libxl_log_child_exitstatus(struct libxl_ctx *ctx,
+                                const char *what, pid_t pid, int status);
+pid_t libxl_waitpid_instead_default(pid_t pid, int *status, int flags);
 
 #endif
 
diff -r 20063cea1606 -r 2f7cb671ef38 tools/libxl/osdeps.c
--- a/tools/libxl/osdeps.c      Mon Nov 23 07:00:08 2009 +0000
+++ b/tools/libxl/osdeps.c      Mon Nov 23 07:01:51 2009 +0000
@@ -12,6 +12,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  */
+
+#include "libxl_osdeps.h"
 
 #include <unistd.h>
 #include <stdarg.h>
diff -r 20063cea1606 -r 2f7cb671ef38 tools/libxl/xl.c
--- a/tools/libxl/xl.c  Mon Nov 23 07:00:08 2009 +0000
+++ b/tools/libxl/xl.c  Mon Nov 23 07:01:51 2009 +0000
@@ -699,6 +699,15 @@ skip_pci:
     config_destroy(&config);
 }
 
+#define MUST( call ) ({                                                 \
+        int must_rc = (call);                                           \
+        if (must_rc) {                                                  \
+            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
+                    __FILE__,__LINE__, must_rc, #call);                 \
+            exit(-must_rc);                                             \
+        }                                                               \
+    })
+
 static void create_domain(int debug, const char *filename)
 {
     struct libxl_ctx ctx;
@@ -715,6 +724,7 @@ static void create_domain(int debug, con
     libxl_device_console console;
     int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 
0;
     int i;
+    libxl_device_model_starting *dm_starting = 0;
 
     printf("Parsing config file %s\n", filename);
     parse_config_file(filename, &info1, &info2, &disks, &num_disks, &vifs, 
&num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, 
&dm_info);
@@ -736,7 +746,8 @@ static void create_domain(int debug, con
     }
     if (info1.hvm) {
         device_model_info_domid_fixup(&dm_info, domid);
-        libxl_create_device_model(&ctx, &dm_info, vifs, num_vifs);
+        MUST( libxl_create_device_model(&ctx, &dm_info, vifs, num_vifs,
+                                        &dm_starting) );
     } else {
         for (i = 0; i < num_vfbs; i++) {
             vfb_info_domid_fixup(vfbs + i, domid);
@@ -750,10 +761,14 @@ static void create_domain(int debug, con
             console.constype = CONSTYPE_IOEMU;
         libxl_device_console_add(&ctx, domid, &console);
         if (num_vfbs)
-            libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console);
-    }
+            libxl_create_xenpv_qemu(&ctx, vfbs, 1, &console, &dm_starting);
+    }
+
     for (i = 0; i < num_pcidevs; i++)
         libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
+    if (dm_starting)
+        MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) );
+
     libxl_domain_unpause(&ctx, domid);
 
 }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] libxenlight: check for early failures of qemu-dm, Xen patchbot-unstable <=