5
/* Postfix master - signal processing
9
/* int master_gotsighup;
10
/* int master_gotsigchld;
12
/* int master_sigsetup()
14
/* This module implements the master process signal handling interface.
16
/* master_gotsighup (master_gotsigchld) is set to SIGHUP (SIGCHLD)
17
/* when the process receives a hangup (child death) signal.
19
/* master_sigsetup() enables processing of hangup and child death signals.
20
/* Receipt of SIGINT, SIGQUIT, SIGSEGV, SIGILL, or SIGTERM
21
/* is interpreted as a request for termination. Child processes are
22
/* notified of the master\'s demise by sending them a SIGTERM signal.
25
/* Need a way to register cleanup actions.
30
/* The Secure Mailer license must be distributed with this software.
33
/* IBM T.J. Watson Research
35
/* Yorktown Heights, NY 10598, USA
38
/* System libraries. */
44
/* Utility library. */
47
#include <posix_signals.h>
49
/* Application-specific. */
54
#include <sys/syscall.h>
57
#ifndef USE_SIG_RETURN
69
int master_sig_pipe[2];
71
#define SIG_PIPE_WRITE_FD master_sig_pipe[1]
72
#define SIG_PIPE_READ_FD master_sig_pipe[0]
75
int master_gotsigchld;
78
/* master_sighup - register arrival of hangup signal */
80
static void master_sighup(int sig)
84
* WARNING WARNING WARNING.
86
* This code runs at unpredictable moments, as a signal handler. Don't put
87
* any code here other than for setting a global flag.
89
master_gotsighup = sig;
92
/* master_sigchld - register arrival of child death signal */
96
static void master_sigchld(int sig, int code, struct sigcontext * scp)
100
* WARNING WARNING WARNING.
102
* This code runs at unpredictable moments, as a signal handler. Don't put
103
* any code here other than for setting a global flag, or code that is
104
* intended to be run within a signal handler.
106
master_gotsigchld = sig;
107
if (scp != NULL && scp->sc_syscall == SYS_select) {
108
scp->sc_syscall_action = SIG_RETURN;
110
} else if (scp != NULL) {
111
scp->sc_syscall_action = SIG_RESTART;
120
/* master_sigchld - force wakeup from select() */
122
static void master_sigchld(int unused_sig)
124
int saved_errno = errno;
127
* WARNING WARNING WARNING.
129
* This code runs at unpredictable moments, as a signal handler. Don't put
130
* any code here other than for setting a global flag, or code that is
131
* intended to be run within a signal handler. Restore errno in case we
132
* are interrupting the epilog of a failed system call.
134
if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
135
msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
139
/* master_sig_event - called upon return from select() */
141
static void master_sig_event(int unused_event, char *unused_context)
145
while (read(SIG_PIPE_READ_FD, c, 1) > 0)
147
master_gotsigchld = 1;
152
static void master_sigchld(int sig)
156
* WARNING WARNING WARNING.
158
* This code runs at unpredictable moments, as a signal handler. Don't put
159
* any code here other than for setting a global flag.
161
master_gotsigchld = sig;
167
/* master_sigdeath - die, women and children first */
169
static void master_sigdeath(int sig)
171
char *myname = "master_sigdeath";
172
struct sigaction action;
173
pid_t pid = getpid();
176
* XXX We're running from a signal handler, and really should not call
177
* any msg() routines at all, but it would be even worse to silently
178
* terminate without informing the sysadmin.
180
msg_info("terminating on signal %d", sig);
183
* Terminate all processes in our process group, except ourselves.
185
sigemptyset(&action.sa_mask);
187
action.sa_handler = SIG_IGN;
188
if (sigaction(SIGTERM, &action, (struct sigaction *) 0) < 0)
189
msg_fatal("%s: sigaction: %m", myname);
190
if (kill(-pid, SIGTERM) < 0)
191
msg_fatal("%s: kill process group: %m", myname);
194
* Deliver the signal to ourselves and clean up. XXX We're running as a
195
* signal handler and really should not be doing complicated things...
197
sigemptyset(&action.sa_mask);
199
action.sa_handler = SIG_DFL;
200
if (sigaction(sig, &action, (struct sigaction *) 0) < 0)
201
msg_fatal("%s: sigaction: %m", myname);
202
if (kill(pid, sig) < 0)
203
msg_fatal("%s: kill myself: %m", myname);
206
/* master_sigsetup - set up signal handlers */
208
void master_sigsetup(void)
210
char *myname = "master_sigsetup";
211
struct sigaction action;
212
static int sigs[] = {
213
SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGSEGV, SIGTERM,
217
sigemptyset(&action.sa_mask);
221
* Prepare to kill our children when we receive any of the above signals.
223
action.sa_handler = master_sigdeath;
224
for (i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++)
225
if (sigaction(sigs[i], &action, (struct sigaction *) 0) < 0)
226
msg_fatal("%s: sigaction(%d): %m", myname, sigs[i]);
229
if (pipe(master_sig_pipe))
230
msg_fatal("pipe: %m");
231
non_blocking(SIG_PIPE_WRITE_FD, NON_BLOCKING);
232
non_blocking(SIG_PIPE_READ_FD, NON_BLOCKING);
233
close_on_exec(SIG_PIPE_WRITE_FD, CLOSE_ON_EXEC);
234
close_on_exec(SIG_PIPE_READ_FD, CLOSE_ON_EXEC);
235
event_enable_read(SIG_PIPE_READ_FD, master_sig_event, (char *) 0);
239
* Intercept SIGHUP (re-read config file) and SIGCHLD (child exit).
242
action.sa_flags |= SA_RESTART;
244
action.sa_handler = master_sighup;
245
if (sigaction(SIGHUP, &action, (struct sigaction *) 0) < 0)
246
msg_fatal("%s: sigaction(%d): %m", myname, SIGHUP);
248
action.sa_flags |= SA_NOCLDSTOP;
249
action.sa_handler = master_sigchld;
250
if (sigaction(SIGCHLD, &action, (struct sigaction *) 0) < 0)
251
msg_fatal("%s: sigaction(%d): %m", myname, SIGCHLD);