2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 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 two of the GNU 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 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
35 * Note, we probably should do a core dump for the serious
36 * signals such as SIGBUS, SIGPFE, ...
37 * Also, for SIGHUP and SIGUSR1, we should re-read the
38 * configuration file. However, since this is a "general"
39 * routine, we leave it to the individual daemons to
40 * tweek their signals after calling this routine.
53 extern char my_name[];
56 extern void print_jcr_dbg();
58 static const char *sig_names[BA_NSIG+1];
60 typedef void (SIG_HANDLER)(int sig);
61 static SIG_HANDLER *exit_handler;
64 static pid_t main_pid = 0;
66 const char *get_signal_name(int sig)
68 if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
69 return _("Invalid signal number");
71 return sig_names[sig];
75 /* defined in jcr.c */
76 extern void _dbg_print_jcr(FILE *fp);
77 /* defined in plugin.c */
78 extern void _dbg_print_plugin(FILE *fp);
83 * This function should be used ONLY after a violent signal. We walk through the
84 * JCR chain without doing any lock, 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, getpid());
92 FILE *fp = fopen(buf, "ab") ;
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);
112 * Handle signals here
114 extern "C" void signal_handler(int sig)
116 static int already_dead = 0;
118 /* If we come back more than once, get out fast! */
122 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
123 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
124 if (sig == SIGCHLD || sig == SIGUSR2) {
128 if (sig == SIGTERM) {
129 // Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
131 Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
135 if (sig != SIGTERM) {
136 struct sigaction sigdefault;
137 static char *argv[4];
138 static char pid_buf[20];
139 static char btpath[400];
142 int exelen = strlen(exepath);
144 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
145 exename, my_name, sig, get_signal_name(sig));
146 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
148 if (exelen + 12 > (int)sizeof(btpath)) {
149 bstrncpy(btpath, "btraceback", sizeof(btpath));
151 bstrncpy(btpath, exepath, sizeof(btpath));
152 if (IsPathSeparator(btpath[exelen-1])) {
153 btpath[exelen-1] = 0;
155 bstrncat(btpath, "/btraceback", sizeof(btpath));
157 if (!IsPathSeparator(exepath[exelen - 1])) {
158 strcat(exepath, "/");
160 strcat(exepath, exename);
161 if (!working_directory) {
162 working_directory = buf;
165 if (*working_directory == 0) {
166 strcpy((char *)working_directory, "/tmp/");
168 if (chdir(working_directory) != 0) { /* dump in working directory */
170 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
171 strcpy((char *)working_directory, "/tmp/");
173 unlink("./core"); /* get rid of any old core file */
174 sprintf(pid_buf, "%d", (int)main_pid);
175 Dmsg1(300, "Working=%s\n", working_directory);
176 Dmsg1(300, "btpath=%s\n", btpath);
177 Dmsg1(300, "exepath=%s\n", exepath);
178 switch (pid = fork()) {
180 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
183 argv[0] = btpath; /* path to btraceback */
184 argv[1] = exepath; /* path to exe */
186 argv[3] = (char *)NULL;
187 fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
188 if (execv(btpath, argv) != 0) {
190 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
193 default: /* parent */
197 /* Parent continue here, waiting for child */
198 sigdefault.sa_flags = 0;
199 sigdefault.sa_handler = SIG_DFL;
200 sigfillset(&sigdefault.sa_mask);
202 sigaction(sig, &sigdefault, NULL);
204 Dmsg0(500, "Doing waitpid\n");
205 waitpid(pid, NULL, 0); /* wait for child to produce dump */
206 Dmsg0(500, "Done waitpid\n");
207 fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
208 /* print information about the current state into working/<file>.bactrace */
210 exit_handler(sig); /* clean up if possible */
211 Dmsg0(500, "Done exit_handler\n");
213 Dmsg0(500, "Doing sleep\n");
216 fprintf(stderr, _("It looks like the traceback worked ...\n"));
224 * Init stack dump by saving main process id --
225 * needed by debugger to attach to this program.
227 void init_stack_dump(void)
229 main_pid = getpid(); /* save main thread's pid */
235 void init_signals(void terminate(int sig))
237 struct sigaction sighandle;
238 struct sigaction sigignore;
239 struct sigaction sigdefault;
243 exit_handler = terminate;
244 if (BA_NSIG < _sys_nsig)
245 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
247 for (i=0; i<_sys_nsig; i++)
248 sig_names[i] = _sys_siglist[i];
250 exit_handler = terminate;
251 sig_names[0] = _("UNKNOWN SIGNAL");
252 sig_names[SIGHUP] = _("Hangup");
253 sig_names[SIGINT] = _("Interrupt");
254 sig_names[SIGQUIT] = _("Quit");
255 sig_names[SIGILL] = _("Illegal instruction");;
256 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
257 sig_names[SIGABRT] = _("Abort");
259 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
262 sig_names[SIGIOT] = _("IOT trap");
264 sig_names[SIGBUS] = _("BUS error");
265 sig_names[SIGFPE] = _("Floating-point exception");
266 sig_names[SIGKILL] = _("Kill, unblockable");
267 sig_names[SIGUSR1] = _("User-defined signal 1");
268 sig_names[SIGSEGV] = _("Segmentation violation");
269 sig_names[SIGUSR2] = _("User-defined signal 2");
270 sig_names[SIGPIPE] = _("Broken pipe");
271 sig_names[SIGALRM] = _("Alarm clock");
272 sig_names[SIGTERM] = _("Termination");
274 sig_names[SIGSTKFLT] = _("Stack fault");
276 sig_names[SIGCHLD] = _("Child status has changed");
277 sig_names[SIGCONT] = _("Continue");
278 sig_names[SIGSTOP] = _("Stop, unblockable");
279 sig_names[SIGTSTP] = _("Keyboard stop");
280 sig_names[SIGTTIN] = _("Background read from tty");
281 sig_names[SIGTTOU] = _("Background write to tty");
282 sig_names[SIGURG] = _("Urgent condition on socket");
283 sig_names[SIGXCPU] = _("CPU limit exceeded");
284 sig_names[SIGXFSZ] = _("File size limit exceeded");
285 sig_names[SIGVTALRM] = _("Virtual alarm clock");
286 sig_names[SIGPROF] = _("Profiling alarm clock");
287 sig_names[SIGWINCH] = _("Window size change");
288 sig_names[SIGIO] = _("I/O now possible");
290 sig_names[SIGPWR] = _("Power failure restart");
293 sig_names[SIGWAITING] = _("No runnable lwp");
296 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
299 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
302 sig_names[SIGTHAW] = _("Checkpoint Thaw");
305 sig_names[SIGCANCEL] = _("Thread Cancellation");
308 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
313 /* Now setup signal handlers */
314 sighandle.sa_flags = 0;
315 sighandle.sa_handler = signal_handler;
316 sigfillset(&sighandle.sa_mask);
317 sigignore.sa_flags = 0;
318 sigignore.sa_handler = SIG_IGN;
319 sigfillset(&sigignore.sa_mask);
320 sigdefault.sa_flags = 0;
321 sigdefault.sa_handler = SIG_DFL;
322 sigfillset(&sigdefault.sa_mask);
325 sigaction(SIGPIPE, &sigignore, NULL);
326 sigaction(SIGCHLD, &sighandle, NULL);
327 sigaction(SIGCONT, &sigignore, NULL);
328 sigaction(SIGPROF, &sigignore, NULL);
329 sigaction(SIGWINCH, &sigignore, NULL);
330 sigaction(SIGIO, &sighandle, NULL);
332 sigaction(SIGINT, &sigdefault, NULL);
333 sigaction(SIGXCPU, &sigdefault, NULL);
334 sigaction(SIGXFSZ, &sigdefault, NULL);
336 sigaction(SIGHUP, &sigignore, NULL);
337 sigaction(SIGQUIT, &sighandle, NULL);
338 sigaction(SIGILL, &sighandle, NULL);
339 sigaction(SIGTRAP, &sighandle, NULL);
340 sigaction(SIGABRT, &sighandle, NULL);
342 sigaction(SIGEMT, &sighandle, NULL);
345 sigaction(SIGIOT, &sighandle, NULL);
347 sigaction(SIGBUS, &sighandle, NULL);
348 sigaction(SIGFPE, &sighandle, NULL);
349 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
350 sigaction(SIGUSR1, &sighandle, NULL);
351 sigaction(SIGSEGV, &sighandle, NULL);
352 sigaction(SIGUSR2, &sighandle, NULL);
353 sigaction(SIGALRM, &sighandle, NULL);
354 sigaction(SIGTERM, &sighandle, NULL);
356 sigaction(SIGSTKFLT, &sighandle, NULL);
358 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
359 sigaction(SIGTSTP, &sighandle, NULL);
360 sigaction(SIGTTIN, &sighandle, NULL);
361 sigaction(SIGTTOU, &sighandle, NULL);
362 sigaction(SIGURG, &sighandle, NULL);
363 sigaction(SIGVTALRM, &sighandle, NULL);
365 sigaction(SIGPWR, &sighandle, NULL);
368 sigaction(SIGWAITING,&sighandle, NULL);
371 sigaction(SIGLWP, &sighandle, NULL);
374 sigaction(SIGFREEZE, &sighandle, NULL);
377 sigaction(SIGTHAW, &sighandle, NULL);
380 sigaction(SIGCANCEL, &sighandle, NULL);
383 sigaction(SIGLOST, &sighandle, NULL);