X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=daemon.c;h=4e15824f350989ea7d695d0c995bbc2160656b11;hp=7c625bbea9d84c5ac9b37a22253346576cbb7183;hb=80541d0f045e1ed57332800eff9832e0a5b72ddf;hpb=f80453b693e6d3ce5450755310faf5e5d6e5c143 diff --git a/daemon.c b/daemon.c index 7c625bbe..4e15824f 100644 --- a/daemon.c +++ b/daemon.c @@ -155,10 +155,6 @@ 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. * @@ -166,30 +162,42 @@ static void dummy_sighandler(__a_unused int s) * * 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. + * Otherwise, a pipe is created prior to the fork() and the parent tries to + * read a single byte from the reading end of the pipe. The child is supposed + * to write to the writing end of the pipe after it completed its setup + * procedure successfully. This behaviour is useful to let the parent process + * die with an error if the child process aborts early, since in this case the + * read() will return non-positive. + * + * \return This function either succeeds or calls exit(3). If parent_waits is + * true, the return value is the file descriptor of the writing end of the + * pipe. Otherwise the function returns zero. * * \sa fork(2), setsid(2), dup(2), pause(2). */ -void daemonize(bool parent_waits) +int daemonize(bool parent_waits) { pid_t pid; - int null; + int null, pipe_fd[2]; - PARA_INFO_LOG("daemonizing\n"); + if (parent_waits && pipe(pipe_fd) < 0) + goto err; + PARA_INFO_LOG("subsequent log messages go to %s\n", me->logfile_name? + me->logfile_name : "/dev/null"); pid = fork(); if (pid < 0) goto err; - if (pid) { + if (pid) { /* parent exits */ if (parent_waits) { - signal(SIGTERM, dummy_sighandler); - signal(SIGCHLD, dummy_sighandler); - pause(); + char c; + close(pipe_fd[1]); + exit(read(pipe_fd[0], &c, 1) <= 0? + EXIT_FAILURE : EXIT_SUCCESS); } - exit(EXIT_SUCCESS); /* parent exits */ + exit(EXIT_SUCCESS); } + if (parent_waits) + close(pipe_fd[0]); /* become session leader */ if (setsid() < 0) goto err; @@ -205,7 +213,7 @@ void daemonize(bool parent_waits) if (dup2(null, STDERR_FILENO) < 0) goto err; close(null); - return; + return parent_waits? pipe_fd[1] : 0; err: PARA_EMERG_LOG("fatal: %s\n", strerror(errno)); exit(EXIT_FAILURE); @@ -366,8 +374,6 @@ time_t daemon_get_uptime(const struct timeval *current_time) * \param current_time See a \ref daemon_get_uptime(). * * \return A dynamically allocated string of the form "days:hours:minutes". - * - * \sa server_uptime. */ __malloc char *daemon_get_uptime_str(const struct timeval *current_time) {