daemon: Introduce parent_waits flag for daemonize().
[paraslash.git] / daemon.c
index ffdec4e35f3e8cdbd113a780f6d6ade7faf9fcfe..541e44defedc3d17d609dc13b09cf18a94c493e0 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -142,14 +142,25 @@ static bool daemon_test_flag(unsigned flag)
        return me->flags & flag;
 }
 
+static void dummy_sighandler(__a_unused int s)
+{
+}
+
 /**
  * Do the usual stuff to become a daemon.
  *
- * Fork, become session leader, dup fd 0, 1, 2 to /dev/null.
+ * \param parent_waits Whether the parent process should pause before exit.
  *
- * \sa fork(2), setsid(2), dup(2).
+ * Fork, become session leader, cd to /, and dup fd 0, 1, 2 to /dev/null. If \a
+ * parent_waits is false, the parent process terminates immediately.
+ * Otherwise, it calls pause() to sleep until it receives \p SIGTERM or \p
+ * SIGCHLD and exits successfully thereafter. This behaviour is useful if the
+ * daemon process should not detach from the console until the child process
+ * has completed its setup.
+ *
+ * \sa fork(2), setsid(2), dup(2), pause(2).
  */
-void daemonize(void)
+void daemonize(bool parent_waits)
 {
        pid_t pid;
        int null;
@@ -158,8 +169,14 @@ void daemonize(void)
        pid = fork();
        if (pid < 0)
                goto err;
-       if (pid)
+       if (pid) {
+               if (parent_waits) {
+                       signal(SIGTERM, dummy_sighandler);
+                       signal(SIGCHLD, dummy_sighandler);
+                       pause();
+               }
                exit(EXIT_SUCCESS); /* parent exits */
+       }
        /* become session leader */
        if (setsid() < 0)
                goto err;