I wrote:
> commit 6704f959a0ea543f6bbf07e0a58e8b84cdef2236
> Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
> Date: Wed Nov 18 15:24:17 2009 +0000
But apparently I was having a bad day yesterday. I generated that
patch without first committing all of my changes :-(.
Here is the real version.
commit eb5d75cb1157ccdedf0c292e647b0a26790a164c
Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Date: Wed Nov 18 15:24:17 2009 +0000
libxenlight: check for early failures of qemu-dm (v4)
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 v3 of this patch:
* Fixed bug which prevented qemu-dm from being properly killed on domain
shutdown. (Failure to set dom_path in dm starting state.)
* Slightly tidy some memory allocation and error handling in
dm_xenstore_record_pid.
Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 421628c..107a8ee 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,25 +524,50 @@ 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; /* 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)
+ libxl_device_nic *vifs, int num_vifs,
+ libxl_device_model_starting **starting_r)
{
- char *dom_path, *path, *logfile, *logfile_new;
- char *kvs[3];
+ 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);
xs_mkdir(ctx->xsh, XBT_NULL, path);
@@ -559,18 +588,54 @@ 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;
+
+ (*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 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 +982,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 +1261,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 +1275,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 +1349,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 +1359,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);
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|