From 24a082b5d896085553676ea2afe836ad03b643e0 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Wed, 8 Jul 2015 00:01:33 +0200
Subject: 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.
---
kike.c | 40 ++++++++++++++++++++++++++++++++--------
1 file changed, 32 insertions(+), 8 deletions(-)
diff --git a/kike.c b/kike.c
index 768126b..b4f4434 100644
--- a/kike.c
+++ b/kike.c
@@ -25,6 +25,8 @@
#include "kike-replies.c"
#include
+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)
--
cgit v1.2.3-70-g09d2