diff options
author | Ian Campbell <ian.campbell@citrix.com> | 2011-05-24 15:57:24 +0100 |
---|---|---|
committer | Ian Campbell <ian.campbell@citrix.com> | 2011-05-24 15:57:24 +0100 |
commit | 3b6eaa3e341771827a9eca6c3eb8ee72593a3f56 (patch) | |
tree | ee3e7e5f03c3c58dd51fea9af49b2be38c8ad2d8 /tools/libxl/libxl_exec.c | |
parent | dec144fc05e319d768736c35ab18f7057b411afe (diff) | |
download | xen-3b6eaa3e341771827a9eca6c3eb8ee72593a3f56.tar.gz xen-3b6eaa3e341771827a9eca6c3eb8ee72593a3f56.tar.bz2 xen-3b6eaa3e341771827a9eca6c3eb8ee72593a3f56.zip |
libxl: add statup checks to libxl__wait_for_device_model
When the device model is starting up push checks for spawn failure down into
libxl__wait_for_device_model, allowing us to fail more quickly when the device
model fails to start (e.g. due to a missing library or an early setup error
etc).
In order to allow the select loop in libxl__wait_for_device_model to wake when
the child dies add pipe between the parent and the intermediate process which
the intermediate process can use to signal the parent.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
Diffstat (limited to 'tools/libxl/libxl_exec.c')
-rw-r--r-- | tools/libxl/libxl_exec.c | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/tools/libxl/libxl_exec.c b/tools/libxl/libxl_exec.c index 70b54259a6..ce6e93f4f0 100644 --- a/tools/libxl/libxl_exec.c +++ b/tools/libxl/libxl_exec.c @@ -26,6 +26,7 @@ #include <sys/types.h> #include <sys/wait.h> #include <signal.h> /* for SIGKILL */ +#include <fcntl.h> #include "libxl.h" #include "libxl_internal.h" @@ -91,6 +92,22 @@ void libxl_report_child_exitstatus(libxl_ctx *ctx, } } +static int libxl__set_fd_flag(libxl__gc *gc, int fd, int flag) +{ + int flags; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return ERROR_FAIL; + + flags |= flag; + + if (fcntl(fd, F_SETFL, flags) == -1) + return ERROR_FAIL; + + return 0; +} + int libxl__spawn_spawn(libxl__gc *gc, libxl__spawn_starting *for_spawn, const char *what, @@ -100,22 +117,33 @@ int libxl__spawn_spawn(libxl__gc *gc, { libxl_ctx *ctx = libxl__gc_owner(gc); pid_t child, got; - int status; + int status, rc; pid_t intermediate; + int pipes[2]; + unsigned char dummy = 0; if (for_spawn) { for_spawn->what = strdup(what); if (!for_spawn->what) return ERROR_NOMEM; + + if (libxl_pipe(ctx, pipes) < 0) + goto err_parent; + if (libxl__set_fd_flag(gc, pipes[0], O_NONBLOCK) < 0 || + libxl__set_fd_flag(gc, pipes[1], O_NONBLOCK) < 0) + goto err_parent_pipes; } intermediate = libxl_fork(ctx); - if (intermediate ==-1) { - if (for_spawn) free(for_spawn->what); - return ERROR_FAIL; - } + if (intermediate ==-1) + goto err_parent_pipes; + if (intermediate) { /* parent */ - if (for_spawn) for_spawn->intermediate = intermediate; + if (for_spawn) { + for_spawn->intermediate = intermediate; + for_spawn->fd = pipes[0]; + close(pipes[1]); + } return 1; } @@ -124,8 +152,10 @@ int libxl__spawn_spawn(libxl__gc *gc, child = fork(); if (child == -1) exit(255); - if (!child) + if (!child) { + if (for_spawn) close(pipes[1]); return 0; /* caller runs child code */ + } intermediate_hook(hook_data, child); @@ -134,9 +164,23 @@ int libxl__spawn_spawn(libxl__gc *gc, got = call_waitpid(ctx->waitpid_instead, child, &status, 0); assert(got == child); - _exit(WIFEXITED(status) ? WEXITSTATUS(status) : + rc = (WIFEXITED(status) ? WEXITSTATUS(status) : WIFSIGNALED(status) && WTERMSIG(status) < 127 ? WTERMSIG(status)+128 : -1); + if (for_spawn) + write(pipes[1], &dummy, sizeof(dummy)); + _exit(rc); + + err_parent_pipes: + if (for_spawn) { + close(pipes[0]); + close(pipes[1]); + } + + err_parent: + if (for_spawn) free(for_spawn->what); + + return ERROR_FAIL; } static void report_spawn_intermediate_status(libxl__gc *gc, |