diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2015-07-08 00:01:33 +0200 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2015-07-08 00:04:09 +0200 |
commit | 24a082b5d896085553676ea2afe836ad03b643e0 (patch) | |
tree | 44fe229d411fe6a8c552a6c25b984dbb84f84ef2 /kike.c | |
parent | 4d7a74b890bbfe98c45abc5274f1b99cbca9751d (diff) | |
download | xK-24a082b5d896085553676ea2afe836ad03b643e0.tar.gz xK-24a082b5d896085553676ea2afe836ad03b643e0.tar.xz xK-24a082b5d896085553676ea2afe836ad03b643e0.zip |
kike: fix daemonization
First of all, we used to write the wrong PID in the file.
Second of all, systemd needs some extra BS to not kill us immediately.
Diffstat (limited to 'kike.c')
-rw-r--r-- | kike.c | 40 |
1 files changed, 32 insertions, 8 deletions
@@ -25,6 +25,8 @@ #include "kike-replies.c" #include <nl_types.h> +enum { PIPE_READ, PIPE_WRITE }; + // FIXME: don't use time_t to compute time deltas // --- Configuration (application-specific) ------------------------------------ @@ -3838,18 +3840,34 @@ on_signal_pipe_readable (const struct pollfd *fd, struct server_context *ctx) } static void -daemonize (void) +daemonize (struct server_context *ctx) { print_status ("daemonizing..."); if (chdir ("/")) exit_fatal ("%s: %s", "chdir", strerror (errno)); + // Because of systemd, we need to exit the parent process _after_ writing + // a PID file, otherwise our grandchild would receive a SIGTERM + int sync_pipe[2]; + if (pipe (sync_pipe)) + exit_fatal ("%s: %s", "pipe", strerror (errno)); + pid_t pid; if ((pid = fork ()) < 0) exit_fatal ("%s: %s", "fork", strerror (errno)); else if (pid) + { + // Wait until all write ends of the pipe are closed, which can mean + // either success or failure, we don't need to care + xclose (sync_pipe[PIPE_WRITE]); + + char dummy; + if (read (sync_pipe[PIPE_READ], &dummy, 1) < 0) + exit_fatal ("%s: %s", "read", strerror (errno)); + exit (EXIT_SUCCESS); + } setsid (); signal (SIGHUP, SIG_IGN); @@ -3862,6 +3880,15 @@ daemonize (void) openlog (PROGRAM_NAME, LOG_NDELAY | LOG_NOWAIT | LOG_PID, 0); g_log_message_real = log_message_syslog; + // Write the PID file (if so configured) and get rid of the pipe, so that + // the read() in our grandparent finally returns zero (no write ends) + struct error *e = NULL; + if (!irc_lock_pid_file (ctx, &e)) + exit_fatal ("%s", e->message); + + xclose (sync_pipe[PIPE_READ]); + xclose (sync_pipe[PIPE_WRITE]); + // XXX: we may close our own descriptors this way, crippling ourselves; // there is no real guarantee that we will start with all three // descriptors open. In theory we could try to enumerate the descriptors @@ -3948,16 +3975,13 @@ main (int argc, char *argv[]) || !irc_initialize_motd (&ctx, &e) || !irc_initialize_catalog (&ctx, &e) || !irc_parse_config (&ctx, &e) - || !irc_lock_pid_file (&ctx, &e) || !irc_setup_listen_fds (&ctx, &e)) - { - print_error ("%s", e->message); - error_free (e); - exit (EXIT_FAILURE); - } + exit_fatal ("%s", e->message); if (!g_debug_mode) - daemonize (); + daemonize (&ctx); + else if (!irc_lock_pid_file (&ctx, &e)) + exit_fatal ("%s", e->message); ctx.polling = true; while (ctx.polling) |