1 /* $NetBSD: master_sig.c,v 1.3 2020/03/18 19:05:16 christos 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 /* Wietse Venema 40 /* Google, Inc. 41 /* 111 8th Avenue 42 /* New York, NY 10011, USA 43 /*--*/ 44 45 /* System libraries. */ 46 47 #include <sys_defs.h> 48 #include <signal.h> 49 #include <unistd.h> 50 51 /* Utility library. */ 52 53 #include <msg.h> 54 #include <posix_signals.h> 55 #include <killme_after.h> 56 57 /* Application-specific. */ 58 59 #include "master.h" 60 61 #ifdef USE_SIG_RETURN 62 #include <sys/syscall.h> 63 #undef USE_SIG_PIPE 64 #else 65 #define USE_SIG_PIPE 66 #endif 67 68 /* Local stuff. */ 69 70 #ifdef USE_SIG_PIPE 71 #include <errno.h> 72 #include <fcntl.h> 73 #include <iostuff.h> 74 #include <events.h> 75 76 int master_sig_pipe[2]; 77 78 #define SIG_PIPE_WRITE_FD master_sig_pipe[1] 79 #define SIG_PIPE_READ_FD master_sig_pipe[0] 80 #endif 81 82 int master_gotsigchld; 83 int master_gotsighup; 84 85 #ifdef USE_SIG_RETURN 86 87 /* master_sighup - register arrival of hangup signal */ 88 89 static void master_sighup(int sig) 90 { 91 92 /* 93 * WARNING WARNING WARNING. 94 * 95 * This code runs at unpredictable moments, as a signal handler. Don't put 96 * any code here other than for setting a global flag. 97 */ 98 master_gotsighup = sig; 99 } 100 101 /* master_sigchld - register arrival of child death signal */ 102 103 static void master_sigchld(int sig, int code, struct sigcontext * scp) 104 { 105 106 /* 107 * WARNING WARNING WARNING. 108 * 109 * This code runs at unpredictable moments, as a signal handler. Don't put 110 * any code here other than for setting a global flag, or code that is 111 * intended to be run within a signal handler. 112 */ 113 master_gotsigchld = sig; 114 if (scp != NULL && scp->sc_syscall == SYS_select) { 115 scp->sc_syscall_action = SIG_RETURN; 116 #ifndef SA_RESTART 117 } else if (scp != NULL) { 118 scp->sc_syscall_action = SIG_RESTART; 119 #endif 120 } 121 } 122 123 #else 124 125 /* master_sighup - register arrival of hangup signal */ 126 127 static void master_sighup(int sig) 128 { 129 int saved_errno = errno; 130 131 /* 132 * WARNING WARNING WARNING. 133 * 134 * This code runs at unpredictable moments, as a signal handler. Don't put 135 * any code here other than for setting a global flag, or code that is 136 * intended to be run within a signal handler. Restore errno in case we 137 * are interrupting the epilog of a failed system call. 138 */ 139 master_gotsighup = sig; 140 if (write(SIG_PIPE_WRITE_FD, "", 1) != 1) 141 msg_warn("write to SIG_PIPE_WRITE_FD failed: %m"); 142 errno = saved_errno; 143 } 144 145 /* master_sigchld - force wakeup from select() */ 146 147 static void master_sigchld(int unused_sig) 148 { 149 int saved_errno = errno; 150 151 /* 152 * WARNING WARNING WARNING. 153 * 154 * This code runs at unpredictable moments, as a signal handler. Don't put 155 * any code here other than for setting a global flag, or code that is 156 * intended to be run within a signal handler. Restore errno in case we 157 * are interrupting the epilog of a failed system call. 158 */ 159 master_gotsigchld = 1; 160 if (write(SIG_PIPE_WRITE_FD, "", 1) != 1) 161 msg_warn("write to SIG_PIPE_WRITE_FD failed: %m"); 162 errno = saved_errno; 163 } 164 165 /* master_sig_event - called upon return from select() */ 166 167 static void master_sig_event(int unused_event, void *unused_context) 168 { 169 char c[1]; 170 171 while (read(SIG_PIPE_READ_FD, c, 1) > 0) 172 /* void */ ; 173 } 174 175 #endif 176 177 /* master_sigdeath - die, women and children first */ 178 179 static void master_sigdeath(int sig) 180 { 181 const char *myname = "master_sigdeath"; 182 struct sigaction action; 183 pid_t pid = getpid(); 184 185 /* 186 * Set alarm clock here for suicide after 5s. 187 */ 188 killme_after(5); 189 190 /* 191 * Terminate all processes in our process group, except ourselves. 192 */ 193 sigemptyset(&action.sa_mask); 194 action.sa_flags = 0; 195 action.sa_handler = SIG_IGN; 196 if (sigaction(SIGTERM, &action, (struct sigaction *) 0) < 0) 197 msg_fatal("%s: sigaction: %m", myname); 198 if (kill(-pid, SIGTERM) < 0) 199 msg_fatal("%s: kill process group: %m", myname); 200 201 /* 202 * XXX We're running from a signal handler, and should not call complex 203 * routines at all, but it would be even worse to silently terminate 204 * without informing the sysadmin. For this reason, msg(3) was made safe 205 * for usage by signal handlers that terminate the process. 206 */ 207 msg_info("terminating on signal %d", sig); 208 209 /* 210 * Undocumented: when a process runs with PID 1, Linux won't deliver a 211 * signal unless the process specifies a handler (i.e. SIG_DFL is treated 212 * as SIG_IGN). 213 */ 214 if (init_mode) 215 /* Don't call exit() from a signal handler. */ 216 _exit(0); 217 218 /* 219 * Deliver the signal to ourselves and clean up. XXX We're running as a 220 * signal handler and really should not be doing complicated things... 221 */ 222 sigemptyset(&action.sa_mask); 223 action.sa_flags = 0; 224 action.sa_handler = SIG_DFL; 225 if (sigaction(sig, &action, (struct sigaction *) 0) < 0) 226 msg_fatal("%s: sigaction: %m", myname); 227 if (kill(pid, sig) < 0) 228 msg_fatal("%s: kill myself: %m", myname); 229 } 230 231 /* master_sigsetup - set up signal handlers */ 232 233 void master_sigsetup(void) 234 { 235 const char *myname = "master_sigsetup"; 236 struct sigaction action; 237 static int sigs[] = { 238 SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGSEGV, SIGTERM, 239 }; 240 unsigned i; 241 242 sigemptyset(&action.sa_mask); 243 action.sa_flags = 0; 244 245 /* 246 * Prepare to kill our children when we receive any of the above signals. 247 */ 248 action.sa_handler = master_sigdeath; 249 for (i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++) 250 if (sigaction(sigs[i], &action, (struct sigaction *) 0) < 0) 251 msg_fatal("%s: sigaction(%d): %m", myname, sigs[i]); 252 253 #ifdef USE_SIG_PIPE 254 if (pipe(master_sig_pipe)) 255 msg_fatal("pipe: %m"); 256 non_blocking(SIG_PIPE_WRITE_FD, NON_BLOCKING); 257 non_blocking(SIG_PIPE_READ_FD, NON_BLOCKING); 258 close_on_exec(SIG_PIPE_WRITE_FD, CLOSE_ON_EXEC); 259 close_on_exec(SIG_PIPE_READ_FD, CLOSE_ON_EXEC); 260 event_enable_read(SIG_PIPE_READ_FD, master_sig_event, (void *) 0); 261 #endif 262 263 /* 264 * Intercept SIGHUP (re-read config file) and SIGCHLD (child exit). 265 */ 266 #ifdef SA_RESTART 267 action.sa_flags |= SA_RESTART; 268 #endif 269 action.sa_handler = master_sighup; 270 if (sigaction(SIGHUP, &action, (struct sigaction *) 0) < 0) 271 msg_fatal("%s: sigaction(%d): %m", myname, SIGHUP); 272 273 action.sa_flags |= SA_NOCLDSTOP; 274 action.sa_handler = master_sigchld; 275 if (sigaction(SIGCHLD, &action, (struct sigaction *) 0) < 0) 276 msg_fatal("%s: sigaction(%d): %m", myname, SIGCHLD); 277 } 278