The exim rpm in the contrib section of Red Hat rotates each logfile
(mainlog, rejectlog, paniclog, processlog) separately, and sends a
SIGHUP after each one. The effect of this is to send 4 SIGHUPs close
succession. Sometimes, between 0.1% and 1% of the time, this will kill
the exim daemon process. (I know that even one SIGHUP is unnecessary,
but exim ought to tolerate them.)
The first SIGHUP arrives and triggers the signal handler in the normal
way. sighup_seen is set and is detected in the main loop in daemon.c;
exim responds by reexecing itself.
The SIGHUP handler is still set when it execs, but obviously the
handler can't survive exec. The kernel will reset the handler back to
SIG_DFL.
One of the subsequent SIGHUPs may arrive between the exec and the
setting of the SIGHUP handler in exim.c. The default behaviour of
SIGHUP is to terminate the process, so the new exim daemon dies.
Nothing is logged unless you have process accounting turned on.
The fix is very simple: set the handler to SIG_IGN, which can survive
exec, to prevent the signal from being delivered while exim is not yet
ready. This has no bad effects since one of the first things that exim
does is to set SIGHUP to SIG_IGN anyway.
Peter Benie
--- exim-3.33/src/daemon.c~ Wed Aug 15 12:09:08 2001
+++ exim-3.33/src/daemon.c Mon Nov 5 15:49:32 2001
@@ -1363,6 +1363,7 @@
for (sk = 0; sk < listen_socket_count; sk++) close(listen_sockets[sk]);
alarm(0);
sighup_argv[0] = exim_path;
+ signal(SIGHUP, SIG_IGN);
execv(exim_path, sighup_argv);
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "pid %d: exec of %s failed: %s",
getpid(), exim_path, strerror(errno));