7 /* Postfix master - signal processing
11 /* int master_gotsighup;
12 /* int master_gotsigchld;
14 /* int master_sigsetup()
16 /* This module implements the master process signal handling interface.
18 /* master_gotsighup (master_gotsigchld) is set to SIGHUP (SIGCHLD)
19 /* when the process receives a hangup (child death) signal.
21 /* master_sigsetup() enables processing of hangup and child death signals.
22 /* Receipt of SIGINT, SIGQUIT, SIGSEGV, SIGILL, or SIGTERM
23 /* is interpreted as a request for termination. Child processes are
24 /* notified of the master\'s demise by sending them a SIGTERM signal.
27 /* Need a way to register cleanup actions.
32 /* The Secure Mailer license must be distributed with this software.
35 /* IBM T.J. Watson Research
37 /* Yorktown Heights, NY 10598, USA
40 /* System libraries. */
46 /* Utility library. */
49 #include <posix_signals.h>
50 #include <killme_after.h>
52 /* Application-specific. */
57 #include <sys/syscall.h>
60 #ifndef USE_SIG_RETURN
72 int master_sig_pipe
[2];
74 #define SIG_PIPE_WRITE_FD master_sig_pipe[1]
75 #define SIG_PIPE_READ_FD master_sig_pipe[0]
78 int master_gotsigchld
;
81 /* master_sighup - register arrival of hangup signal */
83 static void master_sighup(int sig
)
87 * WARNING WARNING WARNING.
89 * This code runs at unpredictable moments, as a signal handler. Don't put
90 * any code here other than for setting a global flag.
92 master_gotsighup
= sig
;
95 /* master_sigchld - register arrival of child death signal */
99 static void master_sigchld(int sig
, int code
, struct sigcontext
* scp
)
103 * WARNING WARNING WARNING.
105 * This code runs at unpredictable moments, as a signal handler. Don't put
106 * any code here other than for setting a global flag, or code that is
107 * intended to be run within a signal handler.
109 master_gotsigchld
= sig
;
110 if (scp
!= NULL
&& scp
->sc_syscall
== SYS_select
) {
111 scp
->sc_syscall_action
= SIG_RETURN
;
113 } else if (scp
!= NULL
) {
114 scp
->sc_syscall_action
= SIG_RESTART
;
123 /* master_sigchld - force wakeup from select() */
125 static void master_sigchld(int unused_sig
)
127 int saved_errno
= errno
;
130 * WARNING WARNING WARNING.
132 * This code runs at unpredictable moments, as a signal handler. Don't put
133 * any code here other than for setting a global flag, or code that is
134 * intended to be run within a signal handler. Restore errno in case we
135 * are interrupting the epilog of a failed system call.
137 if (write(SIG_PIPE_WRITE_FD
, "", 1) != 1)
138 msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
142 /* master_sig_event - called upon return from select() */
144 static void master_sig_event(int unused_event
, char *unused_context
)
148 while (read(SIG_PIPE_READ_FD
, c
, 1) > 0)
150 master_gotsigchld
= 1;
155 static void master_sigchld(int sig
)
159 * WARNING WARNING WARNING.
161 * This code runs at unpredictable moments, as a signal handler. Don't put
162 * any code here other than for setting a global flag.
164 master_gotsigchld
= sig
;
170 /* master_sigdeath - die, women and children first */
172 static void master_sigdeath(int sig
)
174 const char *myname
= "master_sigdeath";
175 struct sigaction action
;
176 pid_t pid
= getpid();
179 * Set alarm clock here for suicide after 5s.
184 * Terminate all processes in our process group, except ourselves.
186 sigemptyset(&action
.sa_mask
);
188 action
.sa_handler
= SIG_IGN
;
189 if (sigaction(SIGTERM
, &action
, (struct sigaction
*) 0) < 0)
190 msg_fatal("%s: sigaction: %m", myname
);
191 if (kill(-pid
, SIGTERM
) < 0)
192 msg_fatal("%s: kill process group: %m", myname
);
195 * XXX We're running from a signal handler, and should not call complex
196 * routines at all, but it would be even worse to silently terminate
197 * without informing the sysadmin. For this reason, msg(3) was made safe
198 * for usage by signal handlers that terminate the process.
200 msg_info("terminating on signal %d", sig
);
203 * Deliver the signal to ourselves and clean up. XXX We're running as a
204 * signal handler and really should not be doing complicated things...
206 sigemptyset(&action
.sa_mask
);
208 action
.sa_handler
= SIG_DFL
;
209 if (sigaction(sig
, &action
, (struct sigaction
*) 0) < 0)
210 msg_fatal("%s: sigaction: %m", myname
);
211 if (kill(pid
, sig
) < 0)
212 msg_fatal("%s: kill myself: %m", myname
);
215 /* master_sigsetup - set up signal handlers */
217 void master_sigsetup(void)
219 const char *myname
= "master_sigsetup";
220 struct sigaction action
;
221 static int sigs
[] = {
222 SIGINT
, SIGQUIT
, SIGILL
, SIGBUS
, SIGSEGV
, SIGTERM
,
226 sigemptyset(&action
.sa_mask
);
230 * Prepare to kill our children when we receive any of the above signals.
232 action
.sa_handler
= master_sigdeath
;
233 for (i
= 0; i
< sizeof(sigs
) / sizeof(sigs
[0]); i
++)
234 if (sigaction(sigs
[i
], &action
, (struct sigaction
*) 0) < 0)
235 msg_fatal("%s: sigaction(%d): %m", myname
, sigs
[i
]);
238 if (pipe(master_sig_pipe
))
239 msg_fatal("pipe: %m");
240 non_blocking(SIG_PIPE_WRITE_FD
, NON_BLOCKING
);
241 non_blocking(SIG_PIPE_READ_FD
, NON_BLOCKING
);
242 close_on_exec(SIG_PIPE_WRITE_FD
, CLOSE_ON_EXEC
);
243 close_on_exec(SIG_PIPE_READ_FD
, CLOSE_ON_EXEC
);
244 event_enable_read(SIG_PIPE_READ_FD
, master_sig_event
, (char *) 0);
248 * Intercept SIGHUP (re-read config file) and SIGCHLD (child exit).
251 action
.sa_flags
|= SA_RESTART
;
253 action
.sa_handler
= master_sighup
;
254 if (sigaction(SIGHUP
, &action
, (struct sigaction
*) 0) < 0)
255 msg_fatal("%s: sigaction(%d): %m", myname
, SIGHUP
);
257 action
.sa_flags
|= SA_NOCLDSTOP
;
258 action
.sa_handler
= master_sigchld
;
259 if (sigaction(SIGCHLD
, &action
, (struct sigaction
*) 0) < 0)
260 msg_fatal("%s: sigaction(%d): %m", myname
, SIGCHLD
);