diff options
| -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) | 
