2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Signal handlers for Bacula daemons
31 * Kern Sibbald, April 2000
33 * Note, we probably should do a core dump for the serious
34 * signals such as SIGBUS, SIGPFE, ...
35 * Also, for SIGHUP and SIGUSR1, we should re-read the
36 * configuration file. However, since this is a "general"
37 * routine, we leave it to the individual daemons to
38 * tweek their signals after calling this routine.
51 extern char my_name[];
54 extern bool prt_kaboom;
56 static const char *sig_names[BA_NSIG+1];
58 typedef void (SIG_HANDLER)(int sig);
59 static SIG_HANDLER *exit_handler;
62 static pid_t main_pid = 0;
64 const char *get_signal_name(int sig)
66 if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
67 return _("Invalid signal number");
69 return sig_names[sig];
73 /* defined in jcr.c */
74 extern void dbg_print_jcr(FILE *fp);
75 /* defined in plugins.c */
76 extern void dbg_print_plugin(FILE *fp);
77 /* defined in lockmgr.c */
78 extern void dbg_print_lock(FILE *fp);
83 * This function should be used ONLY after a violent signal. We walk through the
84 * JCR chain without locking, Bacula should not be running.
86 static void dbg_print_bacula()
90 snprintf(buf, sizeof(buf), "%s/%s.%d.bactrace",
91 working_directory, my_name, (int)getpid());
92 FILE *fp = fopen(buf, "a+") ;
97 fprintf(stderr, "Dumping: %s\n", buf);
99 /* Print also B_DB and RWLOCK structure
100 * Can add more info about JCR with dbg_jcr_add_hook()
104 dbg_print_plugin(fp);
111 printf("\n\n ==== bactrace output ====\n\n");
112 while (fgets(buf, (int)sizeof(buf), fp) != NULL) {
115 printf(" ==== End baktrace output ====\n\n");
120 printf("\n\n ==== bactrace output ====\n\n");
121 snprintf(buf1, sizeof(buf1), "/bin/cat %s", buf);
123 printf(" ==== End baktrace output ====\n\n");
131 * Handle signals here
133 extern "C" void signal_handler(int sig)
135 static int already_dead = 0;
138 /* If we come back more than once, get out fast! */
142 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
143 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
144 if (sig == SIGCHLD || sig == SIGUSR2) {
148 /* Don't use Emsg here as it may lock and thus block us */
149 if (sig == SIGTERM) {
150 syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name);
152 fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
153 syslog(LOG_DAEMON|LOG_ERR,
154 _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
158 if (sig != SIGTERM) {
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. Attempting traceback.\n"),
168 exename, my_name, sig, get_signal_name(sig));
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>.bactrace */
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/bacula.%s.traceback", working_directory, 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/bacula.%s.traceback", working_directory, 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>.bactrace */
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, &sigdefault, 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);