Add 'daemonize': a program that spawns a process and waits for an event
authorDan Cross <>
Thu, 6 Oct 2016 19:25:09 +0000 (15:25 -0400)
committerBarret Rhoden <>
Thu, 6 Oct 2016 19:39:23 +0000 (15:39 -0400)
Consider the typical 'fork-without-exec' pattern: often, a program
wants to do some initialization, acquire some resources, etc, and
then background itself by forking and exiting in the parent.  We
don't have great support for this, as e.g. reference counts on resources
created by the parent can keep processes alive when they should die.
(cf, `ipconfig` currently, where we acquire a DHCP lease in the
foreground before going into a loop in the background to maintain
the lease, but the parent process stays in the "DYING" state forever.)

Barret and I discussed this at length.  A possible solution is to have
a program that invokes the target process in the background and then
waits for an event from that process and then itself exits.  Note that
this requires a protocol between the two: any place where we exit in
the child needs to send an event, and the parent needs to get an event
or it blocks.

I think a generalization of 'wait' where we can send arbitrary messages
with payloads, more along the lines of our existing event support but
specialized to process control, would be nice but it's more work than
what we've got right now.  Think of something analogous to 'wait' but
that accepts a payload, paired with a 'background' call of some kind
that signals to a possibly-waiting parent that we're going off on our

Change-Id: I531f1be3076786a638d57db1c660f9b768f5545e
Signed-off-by: Dan Cross <>
Signed-off-by: Barret Rhoden <>
tests/daemonize.c [new file with mode: 0644]

diff --git a/tests/daemonize.c b/tests/daemonize.c
new file mode 100644 (file)
index 0000000..f7422e1
--- /dev/null
@@ -0,0 +1,41 @@
+#include <parlib/event.h>
+#include <parlib/parlib.h>
+#include <parlib/uthread.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+static void ev_handler(struct event_msg *msg, unsigned int ev_type, void *data)
+       int rv;
+       assert(msg != NULL);
+       assert(ev_type == EV_USER_IPI);
+       (void)data;
+       rv = msg->ev_arg1;
+       exit(rv);
+int main(int argc, char *argv[], char *envp[])
+       struct event_queue *evq, *triggered;
+       pid_t pid;
+       struct event_msg msg;
+       register_ev_handler(EV_USER_IPI, ev_handler, 0);
+       evq = get_eventq(EV_MBOX_UCQ);
+       register_kevent_q(evq, EV_USER_IPI);
+       pid = create_child_with_stdfds(argv[1], argc - 1, argv + 1, envp);
+       if (pid < 0) {
+               perror("child creation failed");
+               exit(-1);
+       }
+       sys_proc_run(pid);
+       uthread_sleep_forever();
+       return -1;