[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 3/3] libxenlight: check for early failures of qemu-dm (v3)



This patch doesn't correctly write the qemu pid on xenstore.
Could you please fix and resend it?

On Wed, 18 Nov 2009, Ian Jackson wrote:
> 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 (!)
> 
> Changes since v2 of this patch:
>  * Various other changes split out into earlier patches in this series
>  * xl.c's create_domain checking for errors in its libxl calls
>    deferred for a future patch to avoid rebase churn.
>  * New libxl_spawn_... abstraction.
> 
> Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
> ---
>  tools/libxl/libxl.c          |   94 +++++++++++++++++----
>  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             |   19 ++++-
>  7 files changed, 344 insertions(+), 40 deletions(-)
> 
> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> index 421628c..29143cf 100644
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -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,16 +524,41 @@ static char ** libxl_build_device_model_args(struct 
> libxl_ctx *ctx,
>      return (char **) flexarray_contents(dm_args);
>  }
> 
> +struct libxl_device_model_starting {
> +    struct libxl_spawn_starting for_spawn; /* first! */
> +    char *dom_path;
> +    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];
> +
> +    clone = *ctx;
> +    clone.xsh = xs_daemon_open();
> +    /* we mustn't use the parent's handle in the child */
> +
> +    kvs[0] = libxl_sprintf(ctx, "image/device-model-pid");
> +    kvs[1] = libxl_sprintf(ctx, "%d", innerchild);
> +    kvs[2] = NULL;
> +    libxl_xs_writev(ctx, XBT_NULL, 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)
> +                              libxl_device_nic *vifs, int num_vifs,
> +                              libxl_device_model_starting **starting_r)
>  {
>      char *dom_path, *path, *logfile, *logfile_new;
> -    char *kvs[3];
>      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)
> @@ -559,18 +588,50 @@ int libxl_create_device_model(struct libxl_ctx *ctx,
>      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;
> +        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 rc;
> +}
> 
> -    return 0;
> +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 +978,13 @@ static int libxl_build_xenpv_qemu_args(struct libxl_ctx 
> *ctx,
>  }
> 
>  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 +1257,7 @@ int libxl_device_pci_add(struct libxl_ctx *ctx, 
> uint32_t domid, libxl_device_pci
> 
>      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 +1271,7 @@ int libxl_device_pci_add(struct libxl_ctx *ctx, 
> uint32_t domid, libxl_device_pci
>                             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 +1345,7 @@ int libxl_device_pci_remove(struct libxl_ctx *ctx, 
> uint32_t domid, libxl_device_
> 
>      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 +1355,7 @@ int libxl_device_pci_remove(struct libxl_ctx *ctx, 
> uint32_t domid, libxl_device_
>                         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 --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index ac4c79e..29ffde2 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -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 @@ int libxl_domain_unpause(struct libxl_ctx *ctx, 
> uint32_t domid);
>  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 --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
> index 451233f..39932a6 100644
> --- a/tools/libxl/libxl_device.c
> +++ b/tools/libxl/libxl_device.c
> @@ -287,12 +287,17 @@ int libxl_device_pci_flr(struct libxl_ctx *ctx, 
> unsigned int domain, unsigned in
>      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 libxl_ctx *ctx, 
> uint32_t domid, char *sta
>                  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 --git a/tools/libxl/libxl_exec.c b/tools/libxl/libxl_exec.c
> index 5186ac8..6a3373e 100644
> --- a/tools/libxl/libxl_exec.c
> +++ b/tools/libxl/libxl_exec.c
> @@ -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 --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 046e51d..957bd9e 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -135,7 +135,11 @@ int libxl_device_generic_add(struct libxl_ctx *ctx, 
> libxl_device *device,
>                               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, uint32_t domid,
>                           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 --git a/tools/libxl/osdeps.c b/tools/libxl/osdeps.c
> index ad96480..b146a9d 100644
> --- a/tools/libxl/osdeps.c
> +++ b/tools/libxl/osdeps.c
> @@ -13,6 +13,8 @@
>   * GNU Lesser General Public License for more details.
>   */
> 
> +#include "libxl_osdeps.h"
> +
>  #include <unistd.h>
>  #include <stdarg.h>
>  #include <stdio.h>
> diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c
> index 727fe4a..6d43f8b 100644
> --- a/tools/libxl/xl.c
> +++ b/tools/libxl/xl.c
> @@ -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, const char *filename)
>      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, const char *filename)
>      }
>      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, const char 
> *filename)
>              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);
> 
>  }
> --
> 1.5.6.5
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel
> 

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.