}
}
-int libxl__spawn_record_pid(libxl__gc *gc, libxl__spawn_state *spawn,
- pid_t innerchild)
+int libxl__spawn_record_pid(libxl__gc *gc, libxl__spawn_state *spawn, pid_t pid)
{
- struct xs_handle *xsh = NULL;
- const char *pid = NULL;
- int rc, xsok;
+ int r, rc;
- pid = GCSPRINTF("%d", innerchild);
+ rc = libxl__ev_child_xenstore_reopen(gc, spawn->what);
+ if (rc) goto out;
- /* we mustn't use the parent's handle in the child */
- xsh = xs_daemon_open();
- if (!xsh) {
- LOGE(ERROR, "write %s = %s: xenstore reopen failed",
- spawn->pidpath, pid);
- rc = ERROR_FAIL; goto out;
- }
-
- xsok = xs_write(xsh, XBT_NULL, spawn->pidpath, pid, strlen(pid));
- if (!xsok) {
+ r = libxl__xs_write(gc, XBT_NULL, spawn->pidpath, "%d", pid);
+ if (r) {
LOGE(ERROR,
- "write %s = %s: xenstore write failed", spawn->pidpath, pid);
+ "write %s = %d: xenstore write failed", spawn->pidpath, pid);
rc = ERROR_FAIL; goto out;
}
rc = 0;
out:
- if (xsh) xs_daemon_close(xsh);
return rc ? SIGTERM : 0;
}
/* we are now the middle process */
- child = fork();
+ pid_t (*fork_replacement)(void*) =
+ CTX->childproc_hooks
+ ? CTX->childproc_hooks->fork_replacement
+ : 0;
+ child =
+ fork_replacement
+ ? fork_replacement(CTX->childproc_user)
+ : fork();
+
if (child == -1)
exit(255);
if (!child) {
if (!pid) {
/* woohoo! */
- return 0; /* Yes, CTX is left locked in the child. */
+ if (CTX->xsh) {
+ xs_daemon_destroy_postfork(CTX->xsh);
+ CTX->xsh = NULL; /* turns mistakes into crashes */
+ }
+ /* Yes, CTX is left locked in the child. */
+ return 0;
}
ch->pid = pid;
libxl_sigchld_owner_libxl, 0, 0
};
+int libxl__ev_child_xenstore_reopen(libxl__gc *gc, const char *what) {
+ int rc;
+
+ assert(!CTX->xsh);
+ CTX->xsh = xs_daemon_open();
+ if (!CTX->xsh) {
+ LOGE(ERROR, "%s: xenstore reopen failed", what);
+ rc = ERROR_FAIL; goto out;
+ }
+
+ libxl_fd_set_cloexec(CTX, xs_fileno(CTX->xsh), 1);
+
+ return 0;
+
+ out:
+ return rc;
+}
+
/*
* Local variables:
* mode: C
static inline int libxl__ev_child_inuse(libxl__ev_child *childw_out)
{ return childw_out->pid >= 0; }
+/* Useable (only) in the child to once more make the ctx useable for
+ * xenstore operations. logs failure in the form "what: <error
+ * message>". */
+_hidden int libxl__ev_child_xenstore_reopen(libxl__gc *gc, const char *what);
+
/*
* Other event-handling support provided by the libxl event core to
return rc;
}
-pid_t libxl_fork(libxl_ctx *ctx)
-{
- pid_t pid;
-
- pid = fork();
- if (pid == -1) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "fork failed");
- return -1;
- }
-
- if (!pid) {
- if (ctx->xsh) xs_daemon_destroy_postfork(ctx->xsh);
- ctx->xsh = 0;
- /* This ensures that anyone who forks but doesn't exec,
- * and doesn't reinitialise the libxl_ctx, is OK.
- * It also means they can safely call libxl_ctx_free. */
- }
-
- return pid;
-}
-
int libxl_pipe(libxl_ctx *ctx, int pipes[2])
{
if (pipe(pipes) < 0) {
* logged using filename (which is only used for logging) and what
* (which may be 0). */
-pid_t libxl_fork(libxl_ctx *ctx);
int libxl_pipe(libxl_ctx *ctx, int pipes[2]);
- /* Just like fork(2), pipe(2), but log errors. */
+ /* Just like pipe(2), but log errors. */
void libxl_report_child_exitstatus(libxl_ctx *ctx, xentoollog_level,
const char *what, pid_t pid, int status);
}
}
+pid_t xl_fork(libxl_ctx *ctx) {
+ pid_t pid;
+
+ pid = fork();
+ if (pid == -1) {
+ perror("fork failed");
+ exit(-1);
+ }
+
+ return pid;
+}
+
int main(int argc, char **argv)
{
int opt = 0;
extern libxl_ctx *ctx;
extern xentoollog_logger_stdiostream *logger;
+pid_t xl_fork(libxl_ctx *ctx); /* like fork, but prints and dies if it fails */
void postfork(void);
/* global options */
pid_t child1, got_child;
int nullfd;
- child1 = libxl_fork(ctx);
+ child1 = xl_fork(ctx);
if (child1) {
printf("Daemon running with PID %d\n", child1);
MUST( libxl_pipe(ctx, sendpipe) );
MUST( libxl_pipe(ctx, recvpipe) );
- child = libxl_fork(ctx);
- if (child==-1) exit(1);
+ child = xl_fork(ctx);
if (!child) {
dup2(sendpipe[0], 0);