From 8388a96f4eec1bd3adcd7cb753f6a6b3b2f7d05e Mon Sep 17 00:00:00 2001 From: Alex Bligh Date: Mon, 10 Sep 2012 21:12:56 +0100 Subject: [PATCH] Improve daemonize - fix trac issue 178, debian bug http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=685637 --- src/daemon.c | 123 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 41 deletions(-) diff --git a/src/daemon.c b/src/daemon.c index f952d67..55ae2b2 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include @@ -347,6 +349,67 @@ void guacd_handle_connection_xml(int fd, char* xmlconfig) { return; } +void daemonize () { + const char *devnull = "/dev/null"; + + /* Fork once to ensure we aren't the process group leader */ + int i = fork (); + if (i < 0) { + fprintf (stderr, "Unable to fork\n"); + _exit (1); + } + + /* Exit if we are the parent */ + if (i > 0) + _exit (0); /* parent exits */ + + /* Start a new session */ + setsid (); + + /* Fork again so the session group leader exits */ + i = fork (); + if (i < 0) { + fprintf (stderr, "Unable to fork\n"); + _exit (1); + } + + /* Exit if we are the parent */ + if (i > 0) + _exit (0); /* parent exits */ + + if (chdir ("/") <0) { + fprintf (stderr, "Unable to chdir /\n"); + _exit (1); + } + + /* Now close all FDs and reopen the 3 stdxxx to /dev/null */ + for (i = getdtablesize () - 1; i >= 0; i--) + close (i); + + i = open (devnull, O_RDWR); + if (i == -1) { + fprintf (stderr, "Unable to open /dev/null\n"); + _exit (1); + } + i = open (devnull, O_RDONLY); + if (i != 0) { + dup2 (i, 0); + close (i); + } + i = open (devnull, O_WRONLY); + if (i != 1) { + dup2 (i, 1); + close (i); + } + i = open (devnull, O_WRONLY); + if (i != 2) { + dup2 (i, 2); + close (i); + } +} + + + int main(int argc, char* argv[]) { /* Server */ @@ -379,9 +442,6 @@ int main(int argc, char* argv[]) { /* General */ int retval; - /* Daemon Process */ - pid_t daemon_pid; - xml_init(); /* Parse arguments */ @@ -414,9 +474,28 @@ int main(int argc, char* argv[]) { } } + /* Daemonize before we start opening sockets, as this closes FDs */ + if (!foreground) + daemonize(); + + if (pidfile != NULL) { + /* Attempt to open pidfile and write PID */ + FILE* pidf = fopen(pidfile, "w"); + if (pidf) { + fprintf(pidf, "%d\n", getpid()); + fclose(pidf); + } else { + /* Warn on failure */ + guacd_log_error("Could not write PID file: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + } + /* Set up logging prefix */ strncpy(log_prefix, basename(argv[0]), sizeof(log_prefix)); + /* Open log as early as we can */ + openlog(NULL, LOG_PID, LOG_DAEMON); /* Get addresses for binding */ if ((retval = getaddrinfo(listen_address, listen_port, &hints, &addresses))) { @@ -481,44 +560,6 @@ int main(int argc, char* argv[]) { exit(EXIT_FAILURE); } - if (!foreground) { - - /* Fork into background */ - daemon_pid = fork(); - - /* If error, fail */ - if (daemon_pid == -1) { - guacd_log_error("Error forking daemon process: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - - /* If parent, write PID file and exit */ - else if (daemon_pid != 0) { - - if (pidfile != NULL) { - - /* Attempt to open pidfile and write PID */ - FILE* pidf = fopen(pidfile, "w"); - if (pidf) { - fprintf(pidf, "%d\n", daemon_pid); - fclose(pidf); - } - - /* Warn on failure */ - else { - guacd_log_error("Could not write PID file: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - - } - - exit(EXIT_SUCCESS); - } - } - - /* Open log */ - openlog(NULL, LOG_PID, LOG_DAEMON); - /* Ignore SIGPIPE */ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { guacd_log_info("Could not set handler for SIGPIPE to ignore. SIGPIPE may cause termination of the daemon."); -- 1.7.10.4