2 * Signal handlers for Bacula daemons
4 * Kern Sibbald, April 2000
8 * Note, we probably should do a core dump for the serious
9 * signals such as SIGBUS, SIGPFE, ...
10 * Also, for SIGHUP and SIGUSR1, we should re-read the
11 * configuration file. However, since this is a "general"
12 * routine, we leave it to the individual daemons to
13 * tweek their signals after calling this routine.
18 Copyright (C) 2000-2004 Kern Sibbald and John Walker
20 This program is free software; you can redistribute it and/or
21 modify it under the terms of the GNU General Public License as
22 published by the Free Software Foundation; either version 2 of
23 the License, or (at your option) any later version.
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 General Public License for more details.
30 You should have received a copy of the GNU General Public
31 License along with this program; if not, write to the Free
32 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
46 extern char my_name[];
50 static const char *sig_names[BA_NSIG+1];
52 typedef void (SIG_HANDLER)(int sig);
53 static SIG_HANDLER *exit_handler;
56 static pid_t main_pid = 0;
58 const char *get_signal_name(int sig)
60 if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
61 return _("Invalid signal number");
63 return sig_names[sig];
70 extern "C" void signal_handler(int sig)
72 static int already_dead = 0;
74 /* If we come back more than once, get out fast! */
78 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
79 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
80 if (sig == SIGCHLD || sig == SIGUSR2) {
85 // Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
87 Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, sig_names[sig]);
92 struct sigaction sigdefault;
94 static char pid_buf[20];
95 static char btpath[400];
98 int exelen = strlen(exepath);
100 fprintf(stderr, _("Kaboom! %s, %s got signal %d. Attempting traceback.\n"),
101 exename, my_name, sig);
102 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
104 if (exelen + 12 > (int)sizeof(btpath)) {
105 bstrncpy(btpath, "btraceback", sizeof(btpath));
107 bstrncpy(btpath, exepath, sizeof(btpath));
108 if (btpath[exelen-1] == '/') {
109 btpath[exelen-1] = 0;
111 bstrncat(btpath, "/btraceback", sizeof(btpath));
113 if (exepath[exelen-1] != '/') {
114 strcat(exepath, "/");
116 strcat(exepath, exename);
117 if (!working_directory) {
118 working_directory = buf;
121 if (*working_directory == 0) {
122 strcpy((char *)working_directory, "/tmp/");
124 if (chdir(working_directory) != 0) { /* dump in working directory */
126 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.strerror());
127 strcpy((char *)working_directory, "/tmp/");
129 unlink("./core"); /* get rid of any old core file */
130 sprintf(pid_buf, "%d", (int)main_pid);
131 Dmsg1(300, "Working=%s\n", working_directory);
132 Dmsg1(300, "btpath=%s\n", btpath);
133 Dmsg1(300, "exepath=%s\n", exepath);
134 switch (pid = fork()) {
136 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
139 argv[0] = btpath; /* path to btraceback */
140 argv[1] = exepath; /* path to exe */
142 argv[3] = (char *)NULL;
143 fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
144 if (execv(btpath, argv) != 0) {
145 printf(_("execv: %s failed: ERR=%s\n"), btpath, strerror(errno));
148 default: /* parent */
151 /* Parent continue here, waiting for child */
152 sigdefault.sa_flags = 0;
153 sigdefault.sa_handler = SIG_DFL;
154 sigfillset(&sigdefault.sa_mask);
156 sigaction(sig, &sigdefault, NULL);
158 Dmsg0(500, "Doing waitpid\n");
159 waitpid(pid, NULL, 0); /* wait for child to produce dump */
160 fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
161 Dmsg0(500, "Done waitpid\n");
162 exit_handler(sig); /* clean up if possible */
163 Dmsg0(500, "Done exit_handler\n");
165 Dmsg0(500, "Doing sleep\n");
168 fprintf(stderr, _("It looks like the traceback worked ...\n"));
176 * Init stack dump by saving main process id --
177 * needed by debugger to attach to this program.
179 void init_stack_dump(void)
181 main_pid = getpid(); /* save main thread's pid */
187 void init_signals(void terminate(int sig))
189 struct sigaction sighandle;
190 struct sigaction sigignore;
191 struct sigaction sigdefault;
195 exit_handler = terminate;
196 if (BA_NSIG < _sys_nsig)
197 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
199 for (i=0; i<_sys_nsig; i++)
200 sig_names[i] = _sys_siglist[i];
202 exit_handler = terminate;
203 sig_names[0] = _("UNKNOWN SIGNAL");
204 sig_names[SIGHUP] = _("Hangup");
205 sig_names[SIGINT] = _("Interrupt");
206 sig_names[SIGQUIT] = _("Quit");
207 sig_names[SIGILL] = _("Illegal instruction");;
208 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
209 sig_names[SIGABRT] = _("Abort");
211 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
214 sig_names[SIGIOT] = _("IOT trap");
216 sig_names[SIGBUS] = _("BUS error");
217 sig_names[SIGFPE] = _("Floating-point exception");
218 sig_names[SIGKILL] = _("Kill, unblockable");
219 sig_names[SIGUSR1] = _("User-defined signal 1");
220 sig_names[SIGSEGV] = _("Segmentation violation");
221 sig_names[SIGUSR2] = _("User-defined signal 2");
222 sig_names[SIGPIPE] = _("Broken pipe");
223 sig_names[SIGALRM] = _("Alarm clock");
224 sig_names[SIGTERM] = _("Termination");
226 sig_names[SIGSTKFLT] = _("Stack fault");
228 sig_names[SIGCHLD] = _("Child status has changed");
229 sig_names[SIGCONT] = _("Continue");
230 sig_names[SIGSTOP] = _("Stop, unblockable");
231 sig_names[SIGTSTP] = _("Keyboard stop");
232 sig_names[SIGTTIN] = _("Background read from tty");
233 sig_names[SIGTTOU] = _("Background write to tty");
234 sig_names[SIGURG] = _("Urgent condition on socket");
235 sig_names[SIGXCPU] = _("CPU limit exceeded");
236 sig_names[SIGXFSZ] = _("File size limit exceeded");
237 sig_names[SIGVTALRM] = _("Virtual alarm clock");
238 sig_names[SIGPROF] = _("Profiling alarm clock");
239 sig_names[SIGWINCH] = _("Window size change");
240 sig_names[SIGIO] = _("I/O now possible");
242 sig_names[SIGPWR] = _("Power failure restart");
245 sig_names[SIGWAITING] = _("No runnable lwp");
248 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
251 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
254 sig_names[SIGTHAW] = _("Checkpoint Thaw");
257 sig_names[SIGCANCEL] = _("Thread Cancellation");
260 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
265 /* Now setup signal handlers */
266 sighandle.sa_flags = 0;
267 sighandle.sa_handler = signal_handler;
268 sigfillset(&sighandle.sa_mask);
269 sigignore.sa_flags = 0;
270 sigignore.sa_handler = SIG_IGN;
271 sigfillset(&sigignore.sa_mask);
272 sigdefault.sa_flags = 0;
273 sigdefault.sa_handler = SIG_DFL;
274 sigfillset(&sigdefault.sa_mask);
277 sigaction(SIGPIPE, &sigignore, NULL);
278 sigaction(SIGCHLD, &sighandle, NULL);
279 sigaction(SIGCONT, &sigignore, NULL);
280 sigaction(SIGPROF, &sigignore, NULL);
281 sigaction(SIGWINCH, &sigignore, NULL);
282 sigaction(SIGIO, &sighandle, NULL);
284 sigaction(SIGINT, &sigdefault, NULL);
285 sigaction(SIGXCPU, &sigdefault, NULL);
286 sigaction(SIGXFSZ, &sigdefault, NULL);
288 sigaction(SIGHUP, &sigignore, NULL);
289 sigaction(SIGQUIT, &sighandle, NULL);
290 sigaction(SIGILL, &sighandle, NULL);
291 sigaction(SIGTRAP, &sighandle, NULL);
292 /* sigaction(SIGABRT, &sighandle, NULL); */
294 sigaction(SIGEMT, &sighandle, NULL);
297 /* sigaction(SIGIOT, &sighandle, NULL); used by debugger */
299 sigaction(SIGBUS, &sighandle, NULL);
300 sigaction(SIGFPE, &sighandle, NULL);
301 sigaction(SIGKILL, &sighandle, NULL);
302 sigaction(SIGUSR1, &sighandle, NULL);
303 sigaction(SIGSEGV, &sighandle, NULL);
304 sigaction(SIGUSR2, &sighandle, NULL);
305 sigaction(SIGALRM, &sighandle, NULL);
306 sigaction(SIGTERM, &sighandle, NULL);
308 sigaction(SIGSTKFLT, &sighandle, NULL);
310 sigaction(SIGSTOP, &sighandle, NULL);
311 sigaction(SIGTSTP, &sighandle, NULL);
312 sigaction(SIGTTIN, &sighandle, NULL);
313 sigaction(SIGTTOU, &sighandle, NULL);
314 sigaction(SIGURG, &sighandle, NULL);
315 sigaction(SIGVTALRM, &sighandle, NULL);
317 sigaction(SIGPWR, &sighandle, NULL);
320 sigaction(SIGWAITING,&sighandle, NULL);
323 sigaction(SIGLWP, &sighandle, NULL);
326 sigaction(SIGFREEZE, &sighandle, NULL);
329 sigaction(SIGTHAW, &sighandle, NULL);
332 sigaction(SIGCANCEL, &sighandle, NULL);
335 sigaction(SIGLOST, &sighandle, NULL);