aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl/libxl_exec.c
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2011-05-24 15:57:24 +0100
committerIan Campbell <ian.campbell@citrix.com>2011-05-24 15:57:24 +0100
commit3b6eaa3e341771827a9eca6c3eb8ee72593a3f56 (patch)
treeee3e7e5f03c3c58dd51fea9af49b2be38c8ad2d8 /tools/libxl/libxl_exec.c
parentdec144fc05e319d768736c35ab18f7057b411afe (diff)
downloadxen-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.c60
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,