2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Signal handlers for Bacula daemons
23 * Kern Sibbald, April 2000
25 * Note, we probably should do a core dump for the serious
26 * signals such as SIGBUS, SIGPFE, ...
27 * Also, for SIGHUP and SIGUSR1, we should re-read the
28 * configuration file. However, since this is a "general"
29 * routine, we leave it to the individual daemons to
30 * tweek their signals after calling this routine.
43 extern char my_name[];
44 extern char fail_time[];
47 extern bool prt_kaboom;
49 static const char *sig_names[BA_NSIG+1];
51 typedef void (SIG_HANDLER)(int sig);
52 static SIG_HANDLER *exit_handler;
55 static pid_t main_pid = 0;
57 const char *get_signal_name(int sig)
59 if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
60 return _("Invalid signal number");
62 return sig_names[sig];
66 /* defined in jcr.c */
67 extern void dbg_print_jcr(FILE *fp);
68 /* defined in plugins.c */
69 extern void dbg_print_plugin(FILE *fp);
70 /* defined in lockmgr.c */
71 extern void dbg_print_lock(FILE *fp);
76 * This function should be used ONLY after a violent signal. We walk through the
77 * JCR chain without locking, Bacula should not be running.
79 static void dbg_print_bacula()
83 snprintf(buf, sizeof(buf), "%s/%s.%d.lockdump",
84 working_directory, my_name, (int)getpid());
85 FILE *fp = fopen(buf, "a+") ;
90 fprintf(stderr, "Dumping: %s\n", buf);
92 /* Print also BDB and RWLOCK structure
93 * Can add more info about JCR with dbg_jcr_add_hook()
104 printf("\n\n ==== lockdump output ====\n\n");
105 while (fgets(buf, (int)sizeof(buf), fp) != NULL) {
108 printf(" ==== End baktrace output ====\n\n");
113 printf("\n\n ==== lockdump output ====\n\n");
114 snprintf(buf1, sizeof(buf1), "/bin/cat %s", buf);
116 printf(" ==== End baktrace output ====\n\n");
124 * Handle signals here
126 extern "C" void signal_handler(int sig)
128 static int already_dead = 0;
132 /* If we come back more than once, get out fast! */
136 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
137 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
138 if (sig == SIGCHLD || sig == SIGUSR2) {
141 /* FreeBSD seems to generate a signal of 0, which is of course undefined */
146 /* Don't use Emsg here as it may lock and thus block us */
147 if (sig == SIGTERM || sig == SIGINT) {
148 syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name);
150 fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
151 syslog(LOG_DAEMON|LOG_ERR,
152 _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
153 /* Edit current time for showing in the dump */
155 bstrftimes(fail_time, 30, now);
159 if (sig != SIGTERM && sig != SIGINT) {
160 struct sigaction sigdefault;
161 static char *argv[5];
162 static char pid_buf[20];
163 static char btpath[400];
166 int exelen = strlen(exepath);
168 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s at %s. Attempting traceback.\n"),
169 exename, my_name, sig, get_signal_name(sig), fail_time);
170 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
172 if (exelen + 12 > (int)sizeof(btpath)) {
173 bstrncpy(btpath, "btraceback", sizeof(btpath));
175 bstrncpy(btpath, exepath, sizeof(btpath));
176 if (IsPathSeparator(btpath[exelen-1])) {
177 btpath[exelen-1] = 0;
179 bstrncat(btpath, "/btraceback", sizeof(btpath));
181 if (!IsPathSeparator(exepath[exelen - 1])) {
182 strcat(exepath, "/");
184 strcat(exepath, exename);
185 if (!working_directory) {
186 working_directory = buf;
189 if (*working_directory == 0) {
190 strcpy((char *)working_directory, "/tmp/");
192 if (chdir(working_directory) != 0) { /* dump in working directory */
194 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
195 strcpy((char *)working_directory, "/tmp/");
197 unlink("./core"); /* get rid of any old core file */
199 #ifdef DEVELOPER /* When DEVELOPER not set, this is done below */
200 /* print information about the current state into working/<file>.lockdump */
205 sprintf(pid_buf, "%d", (int)main_pid);
206 Dmsg1(300, "Working=%s\n", working_directory);
207 Dmsg1(300, "btpath=%s\n", btpath);
208 Dmsg1(300, "exepath=%s\n", exepath);
209 switch (pid = fork()) {
211 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
214 argv[0] = btpath; /* path to btraceback */
215 argv[1] = exepath; /* path to exe */
217 argv[3] = (char *)working_directory;
218 argv[4] = (char *)NULL;
219 fprintf(stderr, _("Calling: %s %s %s %s\n"), btpath, exepath, pid_buf,
221 if (execv(btpath, argv) != 0) {
223 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
226 default: /* parent */
230 /* Parent continue here, waiting for child */
231 sigdefault.sa_flags = 0;
232 sigdefault.sa_handler = SIG_DFL;
233 sigfillset(&sigdefault.sa_mask);
235 sigaction(sig, &sigdefault, NULL);
237 Dmsg0(500, "Doing waitpid\n");
238 waitpid(pid, &chld_status, 0); /* wait for child to produce dump */
239 Dmsg0(500, "Done waitpid\n");
241 Dmsg0(500, "Doing sleep\n");
244 if (WEXITSTATUS(chld_status) == 0) {
245 fprintf(stderr, _("It looks like the traceback worked...\n"));
247 fprintf(stderr, _("The btraceback call returned %d\n"),
248 WEXITSTATUS(chld_status));
250 /* If we want it printed, do so */
254 snprintf(buf, sizeof(buf), "%s/%s.%s.traceback", working_directory, my_name, pid_buf);
255 fd = fopen(buf, "r");
257 printf("\n\n ==== Traceback output ====\n\n");
258 while (fgets(buf, (int)sizeof(buf), fd) != NULL) {
262 printf(" ==== End traceback output ====\n\n");
267 snprintf(buf, sizeof(buf), "/bin/cat %s/%s.%s.traceback", working_directory, my_name, pid_buf);
268 fprintf(stderr, "\n\n ==== Traceback output ====\n\n");
270 fprintf(stderr, " ==== End traceback output ====\n\n");
274 #ifndef DEVELOPER /* When DEVELOPER set, this is done above */
275 /* print information about the current state into working/<file>.lockdump */
282 Dmsg0(500, "Done exit_handler\n");
286 * Init stack dump by saving main process id --
287 * needed by debugger to attach to this program.
289 void init_stack_dump(void)
291 main_pid = getpid(); /* save main thread's pid */
297 void init_signals(void terminate(int sig))
299 struct sigaction sighandle;
300 struct sigaction sigignore;
301 struct sigaction sigdefault;
305 exit_handler = terminate;
306 if (BA_NSIG < _sys_nsig)
307 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
309 for (i=0; i<_sys_nsig; i++)
310 sig_names[i] = _sys_siglist[i];
312 exit_handler = terminate;
313 sig_names[0] = _("UNKNOWN SIGNAL");
314 sig_names[SIGHUP] = _("Hangup");
315 sig_names[SIGINT] = _("Interrupt");
316 sig_names[SIGQUIT] = _("Quit");
317 sig_names[SIGILL] = _("Illegal instruction");;
318 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
319 sig_names[SIGABRT] = _("Abort");
321 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
324 sig_names[SIGIOT] = _("IOT trap");
326 sig_names[SIGBUS] = _("BUS error");
327 sig_names[SIGFPE] = _("Floating-point exception");
328 sig_names[SIGKILL] = _("Kill, unblockable");
329 sig_names[SIGUSR1] = _("User-defined signal 1");
330 sig_names[SIGSEGV] = _("Segmentation violation");
331 sig_names[SIGUSR2] = _("User-defined signal 2");
332 sig_names[SIGPIPE] = _("Broken pipe");
333 sig_names[SIGALRM] = _("Alarm clock");
334 sig_names[SIGTERM] = _("Termination");
336 sig_names[SIGSTKFLT] = _("Stack fault");
338 sig_names[SIGCHLD] = _("Child status has changed");
339 sig_names[SIGCONT] = _("Continue");
340 sig_names[SIGSTOP] = _("Stop, unblockable");
341 sig_names[SIGTSTP] = _("Keyboard stop");
342 sig_names[SIGTTIN] = _("Background read from tty");
343 sig_names[SIGTTOU] = _("Background write to tty");
344 sig_names[SIGURG] = _("Urgent condition on socket");
345 sig_names[SIGXCPU] = _("CPU limit exceeded");
346 sig_names[SIGXFSZ] = _("File size limit exceeded");
347 sig_names[SIGVTALRM] = _("Virtual alarm clock");
348 sig_names[SIGPROF] = _("Profiling alarm clock");
349 sig_names[SIGWINCH] = _("Window size change");
350 sig_names[SIGIO] = _("I/O now possible");
352 sig_names[SIGPWR] = _("Power failure restart");
355 sig_names[SIGWAITING] = _("No runnable lwp");
358 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
361 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
364 sig_names[SIGTHAW] = _("Checkpoint Thaw");
367 sig_names[SIGCANCEL] = _("Thread Cancellation");
370 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
375 /* Now setup signal handlers */
376 sighandle.sa_flags = 0;
377 sighandle.sa_handler = signal_handler;
378 sigfillset(&sighandle.sa_mask);
379 sigignore.sa_flags = 0;
380 sigignore.sa_handler = SIG_IGN;
381 sigfillset(&sigignore.sa_mask);
382 sigdefault.sa_flags = 0;
383 sigdefault.sa_handler = SIG_DFL;
384 sigfillset(&sigdefault.sa_mask);
387 sigaction(SIGPIPE, &sigignore, NULL);
388 sigaction(SIGCHLD, &sighandle, NULL);
389 sigaction(SIGCONT, &sigignore, NULL);
390 sigaction(SIGPROF, &sigignore, NULL);
391 sigaction(SIGWINCH, &sigignore, NULL);
392 sigaction(SIGIO, &sighandle, NULL);
394 sigaction(SIGINT, &sighandle, NULL);
395 sigaction(SIGXCPU, &sigdefault, NULL);
396 sigaction(SIGXFSZ, &sigdefault, NULL);
398 sigaction(SIGHUP, &sigignore, NULL);
399 sigaction(SIGQUIT, &sighandle, NULL);
400 sigaction(SIGILL, &sighandle, NULL);
401 sigaction(SIGTRAP, &sighandle, NULL);
402 sigaction(SIGABRT, &sighandle, NULL);
404 sigaction(SIGEMT, &sighandle, NULL);
407 sigaction(SIGIOT, &sighandle, NULL);
409 sigaction(SIGBUS, &sighandle, NULL);
410 sigaction(SIGFPE, &sighandle, NULL);
411 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
412 sigaction(SIGUSR1, &sighandle, NULL);
413 sigaction(SIGSEGV, &sighandle, NULL);
414 sigaction(SIGUSR2, &sighandle, NULL);
415 sigaction(SIGALRM, &sighandle, NULL);
416 sigaction(SIGTERM, &sighandle, NULL);
418 sigaction(SIGSTKFLT, &sighandle, NULL);
420 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
421 sigaction(SIGTSTP, &sighandle, NULL);
422 sigaction(SIGTTIN, &sighandle, NULL);
423 sigaction(SIGTTOU, &sighandle, NULL);
424 sigaction(SIGURG, &sighandle, NULL);
425 sigaction(SIGVTALRM, &sighandle, NULL);
427 sigaction(SIGPWR, &sighandle, NULL);
430 sigaction(SIGWAITING,&sighandle, NULL);
433 sigaction(SIGLWP, &sighandle, NULL);
436 sigaction(SIGFREEZE, &sighandle, NULL);
439 sigaction(SIGTHAW, &sighandle, NULL);
442 sigaction(SIGCANCEL, &sighandle, NULL);
445 sigaction(SIGLOST, &sighandle, NULL);