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.
This commit is contained in:
Přemysl Eric Janouch 2015-07-08 00:01:33 +02:00
parent 4d7a74b890
commit 24a082b5d8

40
kike.c
View File

@ -25,6 +25,8 @@
#include "kike-replies.c" #include "kike-replies.c"
#include <nl_types.h> #include <nl_types.h>
enum { PIPE_READ, PIPE_WRITE };
// FIXME: don't use time_t to compute time deltas // FIXME: don't use time_t to compute time deltas
// --- Configuration (application-specific) ------------------------------------ // --- Configuration (application-specific) ------------------------------------
@ -3838,18 +3840,34 @@ on_signal_pipe_readable (const struct pollfd *fd, struct server_context *ctx)
} }
static void static void
daemonize (void) daemonize (struct server_context *ctx)
{ {
print_status ("daemonizing..."); print_status ("daemonizing...");
if (chdir ("/")) if (chdir ("/"))
exit_fatal ("%s: %s", "chdir", strerror (errno)); 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; pid_t pid;
if ((pid = fork ()) < 0) if ((pid = fork ()) < 0)
exit_fatal ("%s: %s", "fork", strerror (errno)); exit_fatal ("%s: %s", "fork", strerror (errno));
else if (pid) 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); exit (EXIT_SUCCESS);
}
setsid (); setsid ();
signal (SIGHUP, SIG_IGN); signal (SIGHUP, SIG_IGN);
@ -3862,6 +3880,15 @@ daemonize (void)
openlog (PROGRAM_NAME, LOG_NDELAY | LOG_NOWAIT | LOG_PID, 0); openlog (PROGRAM_NAME, LOG_NDELAY | LOG_NOWAIT | LOG_PID, 0);
g_log_message_real = log_message_syslog; 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; // XXX: we may close our own descriptors this way, crippling ourselves;
// there is no real guarantee that we will start with all three // there is no real guarantee that we will start with all three
// descriptors open. In theory we could try to enumerate the descriptors // 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_motd (&ctx, &e)
|| !irc_initialize_catalog (&ctx, &e) || !irc_initialize_catalog (&ctx, &e)
|| !irc_parse_config (&ctx, &e) || !irc_parse_config (&ctx, &e)
|| !irc_lock_pid_file (&ctx, &e)
|| !irc_setup_listen_fds (&ctx, &e)) || !irc_setup_listen_fds (&ctx, &e))
{ exit_fatal ("%s", e->message);
print_error ("%s", e->message);
error_free (e);
exit (EXIT_FAILURE);
}
if (!g_debug_mode) if (!g_debug_mode)
daemonize (); daemonize (&ctx);
else if (!irc_lock_pid_file (&ctx, &e))
exit_fatal ("%s", e->message);
ctx.polling = true; ctx.polling = true;
while (ctx.polling) while (ctx.polling)