1 /* $NetBSD: master_sig.c,v 1.1.1.1 2009/06/23 10:08:49 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* master_sig 3 6 /* SUMMARY 7 /* Postfix master - signal processing 8 /* SYNOPSIS 9 /* #include "master.h" 10 /* 11 /* int master_gotsighup; 12 /* int master_gotsigchld; 13 /* 14 /* int master_sigsetup() 15 /* DESCRIPTION 16 /* This module implements the master process signal handling interface. 17 /* 18 /* master_gotsighup (master_gotsigchld) is set to SIGHUP (SIGCHLD) 19 /* when the process receives a hangup (child death) signal. 20 /* 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 /*--*/ 39 40 /* System libraries. */ 41 42 #include <sys_defs.h> 43 #include <signal.h> 44 #include <unistd.h> 45 46 /* Utility library. */ 47 48 #include <msg.h> 49 #include <posix_signals.h> 50 #include <killme_after.h> 51 52 /* Application-specific. */ 53 54 #include "master.h" 55 56 #ifdef USE_SIG_RETURN 57 #include <sys/syscall.h> 58 #endif 59 60 #ifndef USE_SIG_RETURN 61 #define USE_SIG_PIPE 62 #endif 63 64 /* Local stuff. */ 65 66 #ifdef USE_SIG_PIPE 67 #include <errno.h> 68 #include <fcntl.h> 69 #include <iostuff.h> 70 #include <events.h> 71 72 int master_sig_pipe[2]; 73 74 #define SIG_PIPE_WRITE_FD master_sig_pipe[1] 75 #define SIG_PIPE_READ_FD master_sig_pipe[0] 76 #endif 77 78 int master_gotsigchld; 79 int master_gotsighup; 80 81 /* master_sighup - register arrival of hangup signal */ 82 83 static void master_sighup(int sig) 84 { 85 86 /* 87 * WARNING WARNING WARNING. 88 * 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. 91 */ 92 master_gotsighup = sig; 93 } 94 95 /* master_sigchld - register arrival of child death signal */ 96 97 #ifdef USE_SIG_RETURN 98 99 static void master_sigchld(int sig, int code, struct sigcontext * scp) 100 { 101 102 /* 103 * WARNING WARNING WARNING. 104 * 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. 108 */ 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 116 } 117 } 118 119 #else 120 121 #ifdef USE_SIG_PIPE 122 123 /* master_sigchld - force wakeup from select() */ 124 125 static void master_sigchld(int unused_sig) 126 { 127 int saved_errno = errno; 128 129 /* 130 * WARNING WARNING WARNING. 131 * 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. 136 */ 137 if (write(SIG_PIPE_WRITE_FD, "", 1) != 1) 138 msg_warn("write to SIG_PIPE_WRITE_FD failed: %m"); 139 errno = saved_errno; 140 } 141 142 /* master_sig_event - called upon return from select() */ 143 144 static void master_sig_event(int unused_event, char *unused_context) 145 { 146 char c[1]; 147 148 while (read(SIG_PIPE_READ_FD, c, 1) > 0) 149 /* void */ ; 150 master_gotsigchld = 1; 151 } 152 153 #else 154 155 static void master_sigchld(int sig) 156 { 157 158 /* 159 * WARNING WARNING WARNING. 160 * 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. 163 */ 164 master_gotsigchld = sig; 165 } 166 167 #endif 168 #endif 169 170 /* master_sigdeath - die, women and children first */ 171 172 static void master_sigdeath(int sig) 173 { 174 const char *myname = "master_sigdeath"; 175 struct sigaction action; 176 pid_t pid = getpid(); 177 178 /* 179 * Set alarm clock here for suicide after 5s. 180 */ 181 killme_after(5); 182 183 /* 184 * Terminate all processes in our process group, except ourselves. 185 */ 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); 193 194 /* 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. 199 */ 200 msg_info("terminating on signal %d", sig); 201 202 /* 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... 205 */ 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); 213 } 214 215 /* master_sigsetup - set up signal handlers */ 216 217 void master_sigsetup(void) 218 { 219 const char *myname = "master_sigsetup"; 220 struct sigaction action; 221 static int sigs[] = { 222 SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGSEGV, SIGTERM, 223 }; 224 unsigned i; 225 226 sigemptyset(&action.sa_mask); 227 action.sa_flags = 0; 228 229 /* 230 * Prepare to kill our children when we receive any of the above signals. 231 */ 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]); 236 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 246 247 /* 248 * Intercept SIGHUP (re-read config file) and SIGCHLD (child exit). 249 */ 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); 256 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); 261 } 262