Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / master / master_sig.c
blob7462200309776d2519ec9d80ea1e36049dc19d2f
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* master_sig 3
6 /* SUMMARY
7 /* Postfix master - signal processing
8 /* SYNOPSIS
9 /* #include "master.h"
11 /* int master_gotsighup;
12 /* int master_gotsigchld;
14 /* int master_sigsetup()
15 /* DESCRIPTION
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.
25 /* DIAGNOSTICS
26 /* BUGS
27 /* Need a way to register cleanup actions.
28 /* SEE ALSO
29 /* LICENSE
30 /* .ad
31 /* .fi
32 /* The Secure Mailer license must be distributed with this software.
33 /* AUTHOR(S)
34 /* Wietse Venema
35 /* IBM T.J. Watson Research
36 /* P.O. Box 704
37 /* Yorktown Heights, NY 10598, USA
38 /*--*/
40 /* System libraries. */
42 #include <sys_defs.h>
43 #include <signal.h>
44 #include <unistd.h>
46 /* Utility library. */
48 #include <msg.h>
49 #include <posix_signals.h>
50 #include <killme_after.h>
52 /* Application-specific. */
54 #include "master.h"
56 #ifdef USE_SIG_RETURN
57 #include <sys/syscall.h>
58 #endif
60 #ifndef USE_SIG_RETURN
61 #define USE_SIG_PIPE
62 #endif
64 /* Local stuff. */
66 #ifdef USE_SIG_PIPE
67 #include <errno.h>
68 #include <fcntl.h>
69 #include <iostuff.h>
70 #include <events.h>
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]
76 #endif
78 int master_gotsigchld;
79 int master_gotsighup;
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 */
97 #ifdef USE_SIG_RETURN
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;
112 #ifndef SA_RESTART
113 } else if (scp != NULL) {
114 scp->sc_syscall_action = SIG_RESTART;
115 #endif
119 #else
121 #ifdef USE_SIG_PIPE
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");
139 errno = saved_errno;
142 /* master_sig_event - called upon return from select() */
144 static void master_sig_event(int unused_event, char *unused_context)
146 char c[1];
148 while (read(SIG_PIPE_READ_FD, c, 1) > 0)
149 /* void */ ;
150 master_gotsigchld = 1;
153 #else
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;
167 #endif
168 #endif
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.
181 killme_after(5);
184 * Terminate all processes in our process group, except ourselves.
186 sigemptyset(&action.sa_mask);
187 action.sa_flags = 0;
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);
207 action.sa_flags = 0;
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,
224 unsigned i;
226 sigemptyset(&action.sa_mask);
227 action.sa_flags = 0;
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]);
237 #ifdef USE_SIG_PIPE
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);
245 #endif
248 * Intercept SIGHUP (re-read config file) and SIGCHLD (child exit).
250 #ifdef SA_RESTART
251 action.sa_flags |= SA_RESTART;
252 #endif
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);