From: Andre Noll Date: Sat, 12 Nov 2011 13:37:01 +0000 (+0100) Subject: daemon: Introduce parent_waits flag for daemonize(). X-Git-Tag: v0.4.9~7 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=25ca796b;p=paraslash.git daemon: Introduce parent_waits flag for daemonize(). In daemon mode, para_server should not detach from the console until it is listening on its command socket. The previous approach turned out to be buggy and has been reverted in the previous commit. This second attempt tries to get it right. It adds a boolean parameter "parent_waits" to daemonize(). After daemonize() has forked, the parent process does not exit immediately if parent_waits is true but waits until the child process sends SIGTERM to its parent, or exits. para_server makes use of the new flag in server_init(). The daemon process (child) sends SIGTERM to its parent after the command socket has been initialized. para_audiod, on the other hand, does not need this feature, so it calls daemonize() with parent_waits == false to get the old behaviour. --- diff --git a/audiod.c b/audiod.c index 4864c855..8008e2cb 100644 --- a/audiod.c +++ b/audiod.c @@ -1381,7 +1381,7 @@ int main(int argc, char *argv[]) init_command_task(cmd_task); if (conf.daemon_given) - daemonize(); + daemonize(false /* parent exits immediately */); register_task(&sig_task->task); register_task(&cmd_task->task); diff --git a/daemon.c b/daemon.c index ffdec4e3..541e44de 100644 --- 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; diff --git a/daemon.h b/daemon.h index d5583f58..3fe72ea9 100644 --- a/daemon.h +++ b/daemon.h @@ -1,7 +1,7 @@ /** \file daemon.h exported symbols from daemon.c */ -void daemonize(void); +void daemonize(bool parent_waits); void daemon_open_log_or_die(void); void daemon_close_log(void); void log_welcome(const char *whoami); diff --git a/server.c b/server.c index 82f48e00..7f020c8f 100644 --- a/server.c +++ b/server.c @@ -493,7 +493,7 @@ static void server_init(int argc, char **argv) init_user_list(user_list_file); /* become daemon */ if (conf.daemon_given) - daemonize(); + daemonize(true /* parent waits for SIGTERM */); PARA_NOTICE_LOG("initializing audio format handlers\n"); afh_init(); @@ -519,6 +519,8 @@ static void server_init(int argc, char **argv) PARA_NOTICE_LOG("initializing virtual streaming system\n"); init_vss_task(afs_socket); init_server_command_task(argc, argv); + if (conf.daemon_given) + kill(getppid(), SIGTERM); PARA_NOTICE_LOG("server init complete\n"); }