2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2009 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;
137 /* If we come back more than once, get out fast! */
141 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
142 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
143 if (sig == SIGCHLD || sig == SIGUSR2) {
147 /* Don't use Emsg here as it may lock and thus block us */
148 if (sig == SIGTERM) {
149 syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name);
151 fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
152 syslog(LOG_DAEMON|LOG_ERR,
153 _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
157 if (sig != SIGTERM) {
158 struct sigaction sigdefault;
159 static char *argv[5];
160 static char pid_buf[20];
161 static char btpath[400];
164 int exelen = strlen(exepath);
166 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
167 exename, my_name, sig, get_signal_name(sig));
168 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
170 if (exelen + 12 > (int)sizeof(btpath)) {
171 bstrncpy(btpath, "btraceback", sizeof(btpath));
173 bstrncpy(btpath, exepath, sizeof(btpath));
174 if (IsPathSeparator(btpath[exelen-1])) {
175 btpath[exelen-1] = 0;
177 bstrncat(btpath, "/btraceback", sizeof(btpath));
179 if (!IsPathSeparator(exepath[exelen - 1])) {
180 strcat(exepath, "/");
182 strcat(exepath, exename);
183 if (!working_directory) {
184 working_directory = buf;
187 if (*working_directory == 0) {
188 strcpy((char *)working_directory, "/tmp/");
190 if (chdir(working_directory) != 0) { /* dump in working directory */
192 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
193 strcpy((char *)working_directory, "/tmp/");
195 unlink("./core"); /* get rid of any old core file */
196 sprintf(pid_buf, "%d", (int)main_pid);
197 Dmsg1(300, "Working=%s\n", working_directory);
198 Dmsg1(300, "btpath=%s\n", btpath);
199 Dmsg1(300, "exepath=%s\n", exepath);
200 switch (pid = fork()) {
202 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
205 argv[0] = btpath; /* path to btraceback */
206 argv[1] = exepath; /* path to exe */
208 argv[3] = (char *)working_directory;
209 argv[4] = (char *)NULL;
210 fprintf(stderr, _("Calling: %s %s %s %s\n"), btpath, exepath, pid_buf,
212 if (execv(btpath, argv) != 0) {
214 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
217 default: /* parent */
221 /* Parent continue here, waiting for child */
222 sigdefault.sa_flags = 0;
223 sigdefault.sa_handler = SIG_DFL;
224 sigfillset(&sigdefault.sa_mask);
226 sigaction(sig, &sigdefault, NULL);
228 Dmsg0(500, "Doing waitpid\n");
229 waitpid(pid, NULL, 0); /* wait for child to produce dump */
230 Dmsg0(500, "Done waitpid\n");
232 Dmsg0(500, "Doing sleep\n");
235 fprintf(stderr, _("It looks like the traceback worked ...\n"));
236 /* If we want it printed, do so */
240 snprintf(buf, sizeof(buf), "%s/bacula.%s.traceback", working_directory, pid_buf);
241 fd = fopen(buf, "r");
243 printf("\n\n ==== Traceback output ====\n\n");
244 while (fgets(buf, (int)sizeof(buf), fd) != NULL) {
248 printf(" ==== End traceback output ====\n\n");
253 snprintf(buf, sizeof(buf), "/bin/cat %s/bacula.%s.traceback", working_directory, pid_buf);
254 fprintf(stderr, "\n\n ==== Traceback output ====\n\n");
256 fprintf(stderr, " ==== End traceback output ====\n\n");
259 /* print information about the current state into working/<file>.bactrace */
264 Dmsg0(500, "Done exit_handler\n");
268 * Init stack dump by saving main process id --
269 * needed by debugger to attach to this program.
271 void init_stack_dump(void)
273 main_pid = getpid(); /* save main thread's pid */
279 void init_signals(void terminate(int sig))
281 struct sigaction sighandle;
282 struct sigaction sigignore;
283 struct sigaction sigdefault;
287 exit_handler = terminate;
288 if (BA_NSIG < _sys_nsig)
289 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
291 for (i=0; i<_sys_nsig; i++)
292 sig_names[i] = _sys_siglist[i];
294 exit_handler = terminate;
295 sig_names[0] = _("UNKNOWN SIGNAL");
296 sig_names[SIGHUP] = _("Hangup");
297 sig_names[SIGINT] = _("Interrupt");
298 sig_names[SIGQUIT] = _("Quit");
299 sig_names[SIGILL] = _("Illegal instruction");;
300 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
301 sig_names[SIGABRT] = _("Abort");
303 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
306 sig_names[SIGIOT] = _("IOT trap");
308 sig_names[SIGBUS] = _("BUS error");
309 sig_names[SIGFPE] = _("Floating-point exception");
310 sig_names[SIGKILL] = _("Kill, unblockable");
311 sig_names[SIGUSR1] = _("User-defined signal 1");
312 sig_names[SIGSEGV] = _("Segmentation violation");
313 sig_names[SIGUSR2] = _("User-defined signal 2");
314 sig_names[SIGPIPE] = _("Broken pipe");
315 sig_names[SIGALRM] = _("Alarm clock");
316 sig_names[SIGTERM] = _("Termination");
318 sig_names[SIGSTKFLT] = _("Stack fault");
320 sig_names[SIGCHLD] = _("Child status has changed");
321 sig_names[SIGCONT] = _("Continue");
322 sig_names[SIGSTOP] = _("Stop, unblockable");
323 sig_names[SIGTSTP] = _("Keyboard stop");
324 sig_names[SIGTTIN] = _("Background read from tty");
325 sig_names[SIGTTOU] = _("Background write to tty");
326 sig_names[SIGURG] = _("Urgent condition on socket");
327 sig_names[SIGXCPU] = _("CPU limit exceeded");
328 sig_names[SIGXFSZ] = _("File size limit exceeded");
329 sig_names[SIGVTALRM] = _("Virtual alarm clock");
330 sig_names[SIGPROF] = _("Profiling alarm clock");
331 sig_names[SIGWINCH] = _("Window size change");
332 sig_names[SIGIO] = _("I/O now possible");
334 sig_names[SIGPWR] = _("Power failure restart");
337 sig_names[SIGWAITING] = _("No runnable lwp");
340 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
343 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
346 sig_names[SIGTHAW] = _("Checkpoint Thaw");
349 sig_names[SIGCANCEL] = _("Thread Cancellation");
352 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
357 /* Now setup signal handlers */
358 sighandle.sa_flags = 0;
359 sighandle.sa_handler = signal_handler;
360 sigfillset(&sighandle.sa_mask);
361 sigignore.sa_flags = 0;
362 sigignore.sa_handler = SIG_IGN;
363 sigfillset(&sigignore.sa_mask);
364 sigdefault.sa_flags = 0;
365 sigdefault.sa_handler = SIG_DFL;
366 sigfillset(&sigdefault.sa_mask);
369 sigaction(SIGPIPE, &sigignore, NULL);
370 sigaction(SIGCHLD, &sighandle, NULL);
371 sigaction(SIGCONT, &sigignore, NULL);
372 sigaction(SIGPROF, &sigignore, NULL);
373 sigaction(SIGWINCH, &sigignore, NULL);
374 sigaction(SIGIO, &sighandle, NULL);
376 sigaction(SIGINT, &sigdefault, NULL);
377 sigaction(SIGXCPU, &sigdefault, NULL);
378 sigaction(SIGXFSZ, &sigdefault, NULL);
380 sigaction(SIGHUP, &sigignore, NULL);
381 sigaction(SIGQUIT, &sighandle, NULL);
382 sigaction(SIGILL, &sighandle, NULL);
383 sigaction(SIGTRAP, &sighandle, NULL);
384 sigaction(SIGABRT, &sighandle, NULL);
386 sigaction(SIGEMT, &sighandle, NULL);
389 sigaction(SIGIOT, &sighandle, NULL);
391 sigaction(SIGBUS, &sighandle, NULL);
392 sigaction(SIGFPE, &sighandle, NULL);
393 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
394 sigaction(SIGUSR1, &sighandle, NULL);
395 sigaction(SIGSEGV, &sighandle, NULL);
396 sigaction(SIGUSR2, &sighandle, NULL);
397 sigaction(SIGALRM, &sighandle, NULL);
398 sigaction(SIGTERM, &sighandle, NULL);
400 sigaction(SIGSTKFLT, &sighandle, NULL);
402 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
403 sigaction(SIGTSTP, &sighandle, NULL);
404 sigaction(SIGTTIN, &sighandle, NULL);
405 sigaction(SIGTTOU, &sighandle, NULL);
406 sigaction(SIGURG, &sighandle, NULL);
407 sigaction(SIGVTALRM, &sighandle, NULL);
409 sigaction(SIGPWR, &sighandle, NULL);
412 sigaction(SIGWAITING,&sighandle, NULL);
415 sigaction(SIGLWP, &sighandle, NULL);
418 sigaction(SIGFREEZE, &sighandle, NULL);
421 sigaction(SIGTHAW, &sighandle, NULL);
424 sigaction(SIGCANCEL, &sighandle, NULL);
427 sigaction(SIGLOST, &sighandle, NULL);