summaryrefslogtreecommitdiff
path: root/kike.c
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2015-07-08 00:01:33 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2015-07-08 00:04:09 +0200
commit24a082b5d896085553676ea2afe836ad03b643e0 (patch)
tree44fe229d411fe6a8c552a6c25b984dbb84f84ef2 /kike.c
parent4d7a74b890bbfe98c45abc5274f1b99cbca9751d (diff)
downloadxK-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.c40
1 files 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 <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)