2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Signal handlers for Bacula daemons
22 * Kern Sibbald, April 2000
24 * Note, we probably should do a core dump for the serious
25 * signals such as SIGBUS, SIGPFE, ...
26 * Also, for SIGHUP and SIGUSR1, we should re-read the
27 * configuration file. However, since this is a "general"
28 * routine, we leave it to the individual daemons to
29 * tweek their signals after calling this routine.
42 extern char my_name[];
43 extern char fail_time[];
46 extern bool prt_kaboom;
48 static const char *sig_names[BA_NSIG+1];
50 typedef void (SIG_HANDLER)(int sig);
51 static SIG_HANDLER *exit_handler;
54 static pid_t main_pid = 0;
56 const char *get_signal_name(int sig)
58 if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
59 return _("Invalid signal number");
61 return sig_names[sig];
65 /* defined in jcr.c */
66 extern void dbg_print_jcr(FILE *fp);
67 /* defined in plugins.c */
68 extern void dbg_print_plugin(FILE *fp);
69 /* defined in lockmgr.c */
70 extern void dbg_print_lock(FILE *fp);
75 * This function should be used ONLY after a violent signal. We walk through the
76 * JCR chain without locking, Bacula should not be running.
78 static void dbg_print_bacula()
82 snprintf(buf, sizeof(buf), "%s/%s.%d.lockdump",
83 working_directory, my_name, (int)getpid());
84 FILE *fp = fopen(buf, "a+") ;
89 fprintf(stderr, "Dumping: %s\n", buf);
91 /* Print also BDB and RWLOCK structure
92 * Can add more info about JCR with dbg_jcr_add_hook()
103 printf("\n\n ==== lockdump output ====\n\n");
104 while (fgets(buf, (int)sizeof(buf), fp) != NULL) {
107 printf(" ==== End baktrace output ====\n\n");
112 printf("\n\n ==== lockdump output ====\n\n");
113 snprintf(buf1, sizeof(buf1), "/bin/cat %s", buf);
115 printf(" ==== End baktrace output ====\n\n");
123 * Handle signals here
125 extern "C" void signal_handler(int sig)
127 static int already_dead = 0;
131 /* If we come back more than once, get out fast! */
135 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
136 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
137 if (sig == SIGCHLD || sig == SIGUSR2) {
140 /* FreeBSD seems to generate a signal of 0, which is of course undefined */
145 /* Don't use Emsg here as it may lock and thus block us */
146 if (sig == SIGTERM || sig == SIGINT) {
147 syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name);
149 fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
150 syslog(LOG_DAEMON|LOG_ERR,
151 _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
152 /* Edit current time for showing in the dump */
154 bstrftimes(fail_time, 30, now);
158 if (sig != SIGTERM && sig != SIGINT) {
159 struct sigaction sigdefault;
160 static char *argv[5];
161 static char pid_buf[20];
162 static char btpath[400];
165 int exelen = strlen(exepath);
167 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s at %s. Attempting traceback.\n"),
168 exename, my_name, sig, get_signal_name(sig), fail_time);
169 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
171 if (exelen + 12 > (int)sizeof(btpath)) {
172 bstrncpy(btpath, "btraceback", sizeof(btpath));
174 bstrncpy(btpath, exepath, sizeof(btpath));
175 if (IsPathSeparator(btpath[exelen-1])) {
176 btpath[exelen-1] = 0;
178 bstrncat(btpath, "/btraceback", sizeof(btpath));
180 if (!IsPathSeparator(exepath[exelen - 1])) {
181 strcat(exepath, "/");
183 strcat(exepath, exename);
184 if (!working_directory) {
185 working_directory = buf;
188 if (*working_directory == 0) {
189 strcpy((char *)working_directory, "/tmp/");
191 if (chdir(working_directory) != 0) { /* dump in working directory */
193 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
194 strcpy((char *)working_directory, "/tmp/");
196 unlink("./core"); /* get rid of any old core file */
198 #ifdef DEVELOPER /* When DEVELOPER not set, this is done below */
199 /* print information about the current state into working/<file>.lockdump */
204 sprintf(pid_buf, "%d", (int)main_pid);
205 Dmsg1(300, "Working=%s\n", working_directory);
206 Dmsg1(300, "btpath=%s\n", btpath);
207 Dmsg1(300, "exepath=%s\n", exepath);
208 switch (pid = fork()) {
210 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
213 argv[0] = btpath; /* path to btraceback */
214 argv[1] = exepath; /* path to exe */
216 argv[3] = (char *)working_directory;
217 argv[4] = (char *)NULL;
218 fprintf(stderr, _("Calling: %s %s %s %s\n"), btpath, exepath, pid_buf,
220 if (execv(btpath, argv) != 0) {
222 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
225 default: /* parent */
229 /* Parent continue here, waiting for child */
230 sigdefault.sa_flags = 0;
231 sigdefault.sa_handler = SIG_DFL;
232 sigfillset(&sigdefault.sa_mask);
234 sigaction(sig, &sigdefault, NULL);
236 Dmsg0(500, "Doing waitpid\n");
237 waitpid(pid, &chld_status, 0); /* wait for child to produce dump */
238 Dmsg0(500, "Done waitpid\n");
240 Dmsg0(500, "Doing sleep\n");
243 if (WEXITSTATUS(chld_status) == 0) {
244 fprintf(stderr, _("It looks like the traceback worked...\n"));
246 fprintf(stderr, _("The btraceback call returned %d\n"),
247 WEXITSTATUS(chld_status));
249 /* If we want it printed, do so */
253 snprintf(buf, sizeof(buf), "%s/%s.%s.traceback", working_directory, my_name, pid_buf);
254 fd = fopen(buf, "r");
256 printf("\n\n ==== Traceback output ====\n\n");
257 while (fgets(buf, (int)sizeof(buf), fd) != NULL) {
261 printf(" ==== End traceback output ====\n\n");
266 snprintf(buf, sizeof(buf), "/bin/cat %s/%s.%s.traceback", working_directory, my_name, pid_buf);
267 fprintf(stderr, "\n\n ==== Traceback output ====\n\n");
269 fprintf(stderr, " ==== End traceback output ====\n\n");
273 #ifndef DEVELOPER /* When DEVELOPER set, this is done above */
274 /* print information about the current state into working/<file>.lockdump */
281 Dmsg0(500, "Done exit_handler\n");
285 * Init stack dump by saving main process id --
286 * needed by debugger to attach to this program.
288 void init_stack_dump(void)
290 main_pid = getpid(); /* save main thread's pid */
296 void init_signals(void terminate(int sig))
298 struct sigaction sighandle;
299 struct sigaction sigignore;
300 struct sigaction sigdefault;
304 exit_handler = terminate;
305 if (BA_NSIG < _sys_nsig)
306 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
308 for (i=0; i<_sys_nsig; i++)
309 sig_names[i] = _sys_siglist[i];
311 exit_handler = terminate;
312 sig_names[0] = _("UNKNOWN SIGNAL");
313 sig_names[SIGHUP] = _("Hangup");
314 sig_names[SIGINT] = _("Interrupt");
315 sig_names[SIGQUIT] = _("Quit");
316 sig_names[SIGILL] = _("Illegal instruction");;
317 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
318 sig_names[SIGABRT] = _("Abort");
320 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
323 sig_names[SIGIOT] = _("IOT trap");
325 sig_names[SIGBUS] = _("BUS error");
326 sig_names[SIGFPE] = _("Floating-point exception");
327 sig_names[SIGKILL] = _("Kill, unblockable");
328 sig_names[SIGUSR1] = _("User-defined signal 1");
329 sig_names[SIGSEGV] = _("Segmentation violation");
330 sig_names[SIGUSR2] = _("User-defined signal 2");
331 sig_names[SIGPIPE] = _("Broken pipe");
332 sig_names[SIGALRM] = _("Alarm clock");
333 sig_names[SIGTERM] = _("Termination");
335 sig_names[SIGSTKFLT] = _("Stack fault");
337 sig_names[SIGCHLD] = _("Child status has changed");
338 sig_names[SIGCONT] = _("Continue");
339 sig_names[SIGSTOP] = _("Stop, unblockable");
340 sig_names[SIGTSTP] = _("Keyboard stop");
341 sig_names[SIGTTIN] = _("Background read from tty");
342 sig_names[SIGTTOU] = _("Background write to tty");
343 sig_names[SIGURG] = _("Urgent condition on socket");
344 sig_names[SIGXCPU] = _("CPU limit exceeded");
345 sig_names[SIGXFSZ] = _("File size limit exceeded");
346 sig_names[SIGVTALRM] = _("Virtual alarm clock");
347 sig_names[SIGPROF] = _("Profiling alarm clock");
348 sig_names[SIGWINCH] = _("Window size change");
349 sig_names[SIGIO] = _("I/O now possible");
351 sig_names[SIGPWR] = _("Power failure restart");
354 sig_names[SIGWAITING] = _("No runnable lwp");
357 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
360 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
363 sig_names[SIGTHAW] = _("Checkpoint Thaw");
366 sig_names[SIGCANCEL] = _("Thread Cancellation");
369 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
374 /* Now setup signal handlers */
375 sighandle.sa_flags = 0;
376 sighandle.sa_handler = signal_handler;
377 sigfillset(&sighandle.sa_mask);
378 sigignore.sa_flags = 0;
379 sigignore.sa_handler = SIG_IGN;
380 sigfillset(&sigignore.sa_mask);
381 sigdefault.sa_flags = 0;
382 sigdefault.sa_handler = SIG_DFL;
383 sigfillset(&sigdefault.sa_mask);
386 sigaction(SIGPIPE, &sigignore, NULL);
387 sigaction(SIGCHLD, &sighandle, NULL);
388 sigaction(SIGCONT, &sigignore, NULL);
389 sigaction(SIGPROF, &sigignore, NULL);
390 sigaction(SIGWINCH, &sigignore, NULL);
391 sigaction(SIGIO, &sighandle, NULL);
393 sigaction(SIGINT, &sighandle, NULL);
394 sigaction(SIGXCPU, &sigdefault, NULL);
395 sigaction(SIGXFSZ, &sigdefault, NULL);
397 sigaction(SIGHUP, &sigignore, NULL);
398 sigaction(SIGQUIT, &sighandle, NULL);
399 sigaction(SIGILL, &sighandle, NULL);
400 sigaction(SIGTRAP, &sighandle, NULL);
401 sigaction(SIGABRT, &sighandle, NULL);
403 sigaction(SIGEMT, &sighandle, NULL);
406 sigaction(SIGIOT, &sighandle, NULL);
408 sigaction(SIGBUS, &sighandle, NULL);
409 sigaction(SIGFPE, &sighandle, NULL);
410 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
411 sigaction(SIGUSR1, &sighandle, NULL);
412 sigaction(SIGSEGV, &sighandle, NULL);
413 sigaction(SIGUSR2, &sighandle, NULL);
414 sigaction(SIGALRM, &sighandle, NULL);
415 sigaction(SIGTERM, &sighandle, NULL);
417 sigaction(SIGSTKFLT, &sighandle, NULL);
419 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
420 sigaction(SIGTSTP, &sighandle, NULL);
421 sigaction(SIGTTIN, &sighandle, NULL);
422 sigaction(SIGTTOU, &sighandle, NULL);
423 sigaction(SIGURG, &sighandle, NULL);
424 sigaction(SIGVTALRM, &sighandle, NULL);
426 sigaction(SIGPWR, &sighandle, NULL);
429 sigaction(SIGWAITING,&sighandle, NULL);
432 sigaction(SIGLWP, &sighandle, NULL);
435 sigaction(SIGFREEZE, &sighandle, NULL);
438 sigaction(SIGTHAW, &sighandle, NULL);
441 sigaction(SIGCANCEL, &sighandle, NULL);
444 sigaction(SIGLOST, &sighandle, NULL);