2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 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 Bacula® is a registered trademark of Kern Sibbald.
17 * Signal handlers for Bacula daemons
19 * Kern Sibbald, April 2000
21 * Note, we probably should do a core dump for the serious
22 * signals such as SIGBUS, SIGPFE, ...
23 * Also, for SIGHUP and SIGUSR1, we should re-read the
24 * configuration file. However, since this is a "general"
25 * routine, we leave it to the individual daemons to
26 * tweek their signals after calling this routine.
39 extern char my_name[];
40 extern char fail_time[];
43 extern bool prt_kaboom;
45 static const char *sig_names[BA_NSIG+1];
47 typedef void (SIG_HANDLER)(int sig);
48 static SIG_HANDLER *exit_handler;
51 static pid_t main_pid = 0;
53 const char *get_signal_name(int sig)
55 if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
56 return _("Invalid signal number");
58 return sig_names[sig];
62 /* defined in jcr.c */
63 extern void dbg_print_jcr(FILE *fp);
64 /* defined in plugins.c */
65 extern void dbg_print_plugin(FILE *fp);
66 /* defined in lockmgr.c */
67 extern void dbg_print_lock(FILE *fp);
72 * This function should be used ONLY after a violent signal. We walk through the
73 * JCR chain without locking, Bacula should not be running.
75 static void dbg_print_bacula()
79 snprintf(buf, sizeof(buf), "%s/%s.%d.lockdump",
80 working_directory, my_name, (int)getpid());
81 FILE *fp = fopen(buf, "a+") ;
86 fprintf(stderr, "Dumping: %s\n", buf);
88 /* Print also B_DB and RWLOCK structure
89 * Can add more info about JCR with dbg_jcr_add_hook()
100 printf("\n\n ==== lockdump output ====\n\n");
101 while (fgets(buf, (int)sizeof(buf), fp) != NULL) {
104 printf(" ==== End baktrace output ====\n\n");
109 printf("\n\n ==== lockdump output ====\n\n");
110 snprintf(buf1, sizeof(buf1), "/bin/cat %s", buf);
112 printf(" ==== End baktrace output ====\n\n");
120 * Handle signals here
122 extern "C" void signal_handler(int sig)
124 static int already_dead = 0;
128 /* If we come back more than once, get out fast! */
132 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
133 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
134 if (sig == SIGCHLD || sig == SIGUSR2) {
137 /* FreeBSD seems to generate a signal of 0, which is of course undefined */
142 /* Don't use Emsg here as it may lock and thus block us */
143 if (sig == SIGTERM) {
144 syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name);
146 fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
147 syslog(LOG_DAEMON|LOG_ERR,
148 _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
149 /* Edit current time for showing in the dump */
151 bstrftimes(fail_time, 30, now);
155 if (sig != SIGTERM) {
156 struct sigaction sigdefault;
157 static char *argv[5];
158 static char pid_buf[20];
159 static char btpath[400];
162 int exelen = strlen(exepath);
164 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s at %s. Attempting traceback.\n"),
165 exename, my_name, sig, get_signal_name(sig), fail_time);
166 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
168 if (exelen + 12 > (int)sizeof(btpath)) {
169 bstrncpy(btpath, "btraceback", sizeof(btpath));
171 bstrncpy(btpath, exepath, sizeof(btpath));
172 if (IsPathSeparator(btpath[exelen-1])) {
173 btpath[exelen-1] = 0;
175 bstrncat(btpath, "/btraceback", sizeof(btpath));
177 if (!IsPathSeparator(exepath[exelen - 1])) {
178 strcat(exepath, "/");
180 strcat(exepath, exename);
181 if (!working_directory) {
182 working_directory = buf;
185 if (*working_directory == 0) {
186 strcpy((char *)working_directory, "/tmp/");
188 if (chdir(working_directory) != 0) { /* dump in working directory */
190 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
191 strcpy((char *)working_directory, "/tmp/");
193 unlink("./core"); /* get rid of any old core file */
195 #ifdef DEVELOPER /* When DEVELOPER not set, this is done below */
196 /* print information about the current state into working/<file>.lockdump */
201 sprintf(pid_buf, "%d", (int)main_pid);
202 Dmsg1(300, "Working=%s\n", working_directory);
203 Dmsg1(300, "btpath=%s\n", btpath);
204 Dmsg1(300, "exepath=%s\n", exepath);
205 switch (pid = fork()) {
207 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
210 argv[0] = btpath; /* path to btraceback */
211 argv[1] = exepath; /* path to exe */
213 argv[3] = (char *)working_directory;
214 argv[4] = (char *)NULL;
215 fprintf(stderr, _("Calling: %s %s %s %s\n"), btpath, exepath, pid_buf,
217 if (execv(btpath, argv) != 0) {
219 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
222 default: /* parent */
226 /* Parent continue here, waiting for child */
227 sigdefault.sa_flags = 0;
228 sigdefault.sa_handler = SIG_DFL;
229 sigfillset(&sigdefault.sa_mask);
231 sigaction(sig, &sigdefault, NULL);
233 Dmsg0(500, "Doing waitpid\n");
234 waitpid(pid, &chld_status, 0); /* wait for child to produce dump */
235 Dmsg0(500, "Done waitpid\n");
237 Dmsg0(500, "Doing sleep\n");
240 if (WEXITSTATUS(chld_status) == 0) {
241 fprintf(stderr, _("It looks like the traceback worked...\n"));
243 fprintf(stderr, _("The btraceback call returned %d\n"),
244 WEXITSTATUS(chld_status));
246 /* If we want it printed, do so */
250 snprintf(buf, sizeof(buf), "%s/bacula.%s.traceback", working_directory, pid_buf);
251 fd = fopen(buf, "r");
253 printf("\n\n ==== Traceback output ====\n\n");
254 while (fgets(buf, (int)sizeof(buf), fd) != NULL) {
258 printf(" ==== End traceback output ====\n\n");
263 snprintf(buf, sizeof(buf), "/bin/cat %s/bacula.%s.traceback", working_directory, pid_buf);
264 fprintf(stderr, "\n\n ==== Traceback output ====\n\n");
266 fprintf(stderr, " ==== End traceback output ====\n\n");
270 #ifndef DEVELOPER /* When DEVELOPER set, this is done above */
271 /* print information about the current state into working/<file>.lockdump */
278 Dmsg0(500, "Done exit_handler\n");
282 * Init stack dump by saving main process id --
283 * needed by debugger to attach to this program.
285 void init_stack_dump(void)
287 main_pid = getpid(); /* save main thread's pid */
293 void init_signals(void terminate(int sig))
295 struct sigaction sighandle;
296 struct sigaction sigignore;
297 struct sigaction sigdefault;
301 exit_handler = terminate;
302 if (BA_NSIG < _sys_nsig)
303 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
305 for (i=0; i<_sys_nsig; i++)
306 sig_names[i] = _sys_siglist[i];
308 exit_handler = terminate;
309 sig_names[0] = _("UNKNOWN SIGNAL");
310 sig_names[SIGHUP] = _("Hangup");
311 sig_names[SIGINT] = _("Interrupt");
312 sig_names[SIGQUIT] = _("Quit");
313 sig_names[SIGILL] = _("Illegal instruction");;
314 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
315 sig_names[SIGABRT] = _("Abort");
317 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
320 sig_names[SIGIOT] = _("IOT trap");
322 sig_names[SIGBUS] = _("BUS error");
323 sig_names[SIGFPE] = _("Floating-point exception");
324 sig_names[SIGKILL] = _("Kill, unblockable");
325 sig_names[SIGUSR1] = _("User-defined signal 1");
326 sig_names[SIGSEGV] = _("Segmentation violation");
327 sig_names[SIGUSR2] = _("User-defined signal 2");
328 sig_names[SIGPIPE] = _("Broken pipe");
329 sig_names[SIGALRM] = _("Alarm clock");
330 sig_names[SIGTERM] = _("Termination");
332 sig_names[SIGSTKFLT] = _("Stack fault");
334 sig_names[SIGCHLD] = _("Child status has changed");
335 sig_names[SIGCONT] = _("Continue");
336 sig_names[SIGSTOP] = _("Stop, unblockable");
337 sig_names[SIGTSTP] = _("Keyboard stop");
338 sig_names[SIGTTIN] = _("Background read from tty");
339 sig_names[SIGTTOU] = _("Background write to tty");
340 sig_names[SIGURG] = _("Urgent condition on socket");
341 sig_names[SIGXCPU] = _("CPU limit exceeded");
342 sig_names[SIGXFSZ] = _("File size limit exceeded");
343 sig_names[SIGVTALRM] = _("Virtual alarm clock");
344 sig_names[SIGPROF] = _("Profiling alarm clock");
345 sig_names[SIGWINCH] = _("Window size change");
346 sig_names[SIGIO] = _("I/O now possible");
348 sig_names[SIGPWR] = _("Power failure restart");
351 sig_names[SIGWAITING] = _("No runnable lwp");
354 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
357 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
360 sig_names[SIGTHAW] = _("Checkpoint Thaw");
363 sig_names[SIGCANCEL] = _("Thread Cancellation");
366 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
371 /* Now setup signal handlers */
372 sighandle.sa_flags = 0;
373 sighandle.sa_handler = signal_handler;
374 sigfillset(&sighandle.sa_mask);
375 sigignore.sa_flags = 0;
376 sigignore.sa_handler = SIG_IGN;
377 sigfillset(&sigignore.sa_mask);
378 sigdefault.sa_flags = 0;
379 sigdefault.sa_handler = SIG_DFL;
380 sigfillset(&sigdefault.sa_mask);
383 sigaction(SIGPIPE, &sigignore, NULL);
384 sigaction(SIGCHLD, &sighandle, NULL);
385 sigaction(SIGCONT, &sigignore, NULL);
386 sigaction(SIGPROF, &sigignore, NULL);
387 sigaction(SIGWINCH, &sigignore, NULL);
388 sigaction(SIGIO, &sighandle, NULL);
390 sigaction(SIGINT, &sigdefault, NULL);
391 sigaction(SIGXCPU, &sigdefault, NULL);
392 sigaction(SIGXFSZ, &sigdefault, NULL);
394 sigaction(SIGHUP, &sigignore, NULL);
395 sigaction(SIGQUIT, &sighandle, NULL);
396 sigaction(SIGILL, &sighandle, NULL);
397 sigaction(SIGTRAP, &sighandle, NULL);
398 sigaction(SIGABRT, &sighandle, NULL);
400 sigaction(SIGEMT, &sighandle, NULL);
403 sigaction(SIGIOT, &sighandle, NULL);
405 sigaction(SIGBUS, &sighandle, NULL);
406 sigaction(SIGFPE, &sighandle, NULL);
407 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
408 sigaction(SIGUSR1, &sighandle, NULL);
409 sigaction(SIGSEGV, &sighandle, NULL);
410 sigaction(SIGUSR2, &sighandle, NULL);
411 sigaction(SIGALRM, &sighandle, NULL);
412 sigaction(SIGTERM, &sighandle, NULL);
414 sigaction(SIGSTKFLT, &sighandle, NULL);
416 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
417 sigaction(SIGTSTP, &sighandle, NULL);
418 sigaction(SIGTTIN, &sighandle, NULL);
419 sigaction(SIGTTOU, &sighandle, NULL);
420 sigaction(SIGURG, &sighandle, NULL);
421 sigaction(SIGVTALRM, &sighandle, NULL);
423 sigaction(SIGPWR, &sighandle, NULL);
426 sigaction(SIGWAITING,&sighandle, NULL);
429 sigaction(SIGLWP, &sighandle, NULL);
432 sigaction(SIGFREEZE, &sighandle, NULL);
435 sigaction(SIGTHAW, &sighandle, NULL);
438 sigaction(SIGCANCEL, &sighandle, NULL);
441 sigaction(SIGLOST, &sighandle, NULL);