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/bacula.%d.bactrace",
91 working_directory, getpid());
92 FILE *fp = fopen(buf, "ab") ;
97 /* Print also B_DB and RWLOCK structure
98 * Can add more info about JCR with dbg_jcr_add_hook()
102 _dbg_print_plugin(fp);
110 * Handle signals here
112 extern "C" void signal_handler(int sig)
114 static int already_dead = 0;
116 /* If we come back more than once, get out fast! */
120 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
121 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
122 if (sig == SIGCHLD || sig == SIGUSR2) {
126 if (sig == SIGTERM) {
127 // Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
129 Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
133 if (sig != SIGTERM) {
134 struct sigaction sigdefault;
135 static char *argv[4];
136 static char pid_buf[20];
137 static char btpath[400];
140 int exelen = strlen(exepath);
142 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
143 exename, my_name, sig, get_signal_name(sig));
144 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
146 if (exelen + 12 > (int)sizeof(btpath)) {
147 bstrncpy(btpath, "btraceback", sizeof(btpath));
149 bstrncpy(btpath, exepath, sizeof(btpath));
150 if (IsPathSeparator(btpath[exelen-1])) {
151 btpath[exelen-1] = 0;
153 bstrncat(btpath, "/btraceback", sizeof(btpath));
155 if (!IsPathSeparator(exepath[exelen - 1])) {
156 strcat(exepath, "/");
158 strcat(exepath, exename);
159 if (!working_directory) {
160 working_directory = buf;
163 if (*working_directory == 0) {
164 strcpy((char *)working_directory, "/tmp/");
166 if (chdir(working_directory) != 0) { /* dump in working directory */
168 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
169 strcpy((char *)working_directory, "/tmp/");
171 unlink("./core"); /* get rid of any old core file */
172 sprintf(pid_buf, "%d", (int)main_pid);
173 Dmsg1(300, "Working=%s\n", working_directory);
174 Dmsg1(300, "btpath=%s\n", btpath);
175 Dmsg1(300, "exepath=%s\n", exepath);
176 switch (pid = fork()) {
178 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
181 argv[0] = btpath; /* path to btraceback */
182 argv[1] = exepath; /* path to exe */
184 argv[3] = (char *)NULL;
185 fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
186 if (execv(btpath, argv) != 0) {
188 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
191 default: /* parent */
195 /* Parent continue here, waiting for child */
196 sigdefault.sa_flags = 0;
197 sigdefault.sa_handler = SIG_DFL;
198 sigfillset(&sigdefault.sa_mask);
200 sigaction(sig, &sigdefault, NULL);
202 Dmsg0(500, "Doing waitpid\n");
203 waitpid(pid, NULL, 0); /* wait for child to produce dump */
204 Dmsg0(500, "Done waitpid\n");
205 fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
206 /* print information about the current state into working/<file>.bactrace */
208 exit_handler(sig); /* clean up if possible */
209 Dmsg0(500, "Done exit_handler\n");
211 Dmsg0(500, "Doing sleep\n");
214 fprintf(stderr, _("It looks like the traceback worked ...\n"));
222 * Init stack dump by saving main process id --
223 * needed by debugger to attach to this program.
225 void init_stack_dump(void)
227 main_pid = getpid(); /* save main thread's pid */
233 void init_signals(void terminate(int sig))
235 struct sigaction sighandle;
236 struct sigaction sigignore;
237 struct sigaction sigdefault;
241 exit_handler = terminate;
242 if (BA_NSIG < _sys_nsig)
243 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
245 for (i=0; i<_sys_nsig; i++)
246 sig_names[i] = _sys_siglist[i];
248 exit_handler = terminate;
249 sig_names[0] = _("UNKNOWN SIGNAL");
250 sig_names[SIGHUP] = _("Hangup");
251 sig_names[SIGINT] = _("Interrupt");
252 sig_names[SIGQUIT] = _("Quit");
253 sig_names[SIGILL] = _("Illegal instruction");;
254 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
255 sig_names[SIGABRT] = _("Abort");
257 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
260 sig_names[SIGIOT] = _("IOT trap");
262 sig_names[SIGBUS] = _("BUS error");
263 sig_names[SIGFPE] = _("Floating-point exception");
264 sig_names[SIGKILL] = _("Kill, unblockable");
265 sig_names[SIGUSR1] = _("User-defined signal 1");
266 sig_names[SIGSEGV] = _("Segmentation violation");
267 sig_names[SIGUSR2] = _("User-defined signal 2");
268 sig_names[SIGPIPE] = _("Broken pipe");
269 sig_names[SIGALRM] = _("Alarm clock");
270 sig_names[SIGTERM] = _("Termination");
272 sig_names[SIGSTKFLT] = _("Stack fault");
274 sig_names[SIGCHLD] = _("Child status has changed");
275 sig_names[SIGCONT] = _("Continue");
276 sig_names[SIGSTOP] = _("Stop, unblockable");
277 sig_names[SIGTSTP] = _("Keyboard stop");
278 sig_names[SIGTTIN] = _("Background read from tty");
279 sig_names[SIGTTOU] = _("Background write to tty");
280 sig_names[SIGURG] = _("Urgent condition on socket");
281 sig_names[SIGXCPU] = _("CPU limit exceeded");
282 sig_names[SIGXFSZ] = _("File size limit exceeded");
283 sig_names[SIGVTALRM] = _("Virtual alarm clock");
284 sig_names[SIGPROF] = _("Profiling alarm clock");
285 sig_names[SIGWINCH] = _("Window size change");
286 sig_names[SIGIO] = _("I/O now possible");
288 sig_names[SIGPWR] = _("Power failure restart");
291 sig_names[SIGWAITING] = _("No runnable lwp");
294 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
297 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
300 sig_names[SIGTHAW] = _("Checkpoint Thaw");
303 sig_names[SIGCANCEL] = _("Thread Cancellation");
306 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
311 /* Now setup signal handlers */
312 sighandle.sa_flags = 0;
313 sighandle.sa_handler = signal_handler;
314 sigfillset(&sighandle.sa_mask);
315 sigignore.sa_flags = 0;
316 sigignore.sa_handler = SIG_IGN;
317 sigfillset(&sigignore.sa_mask);
318 sigdefault.sa_flags = 0;
319 sigdefault.sa_handler = SIG_DFL;
320 sigfillset(&sigdefault.sa_mask);
323 sigaction(SIGPIPE, &sigignore, NULL);
324 sigaction(SIGCHLD, &sighandle, NULL);
325 sigaction(SIGCONT, &sigignore, NULL);
326 sigaction(SIGPROF, &sigignore, NULL);
327 sigaction(SIGWINCH, &sigignore, NULL);
328 sigaction(SIGIO, &sighandle, NULL);
330 sigaction(SIGINT, &sigdefault, NULL);
331 sigaction(SIGXCPU, &sigdefault, NULL);
332 sigaction(SIGXFSZ, &sigdefault, NULL);
334 sigaction(SIGHUP, &sigignore, NULL);
335 sigaction(SIGQUIT, &sighandle, NULL);
336 sigaction(SIGILL, &sighandle, NULL);
337 sigaction(SIGTRAP, &sighandle, NULL);
338 sigaction(SIGABRT, &sighandle, NULL);
340 sigaction(SIGEMT, &sighandle, NULL);
343 sigaction(SIGIOT, &sighandle, NULL);
345 sigaction(SIGBUS, &sighandle, NULL);
346 sigaction(SIGFPE, &sighandle, NULL);
347 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
348 sigaction(SIGUSR1, &sighandle, NULL);
349 sigaction(SIGSEGV, &sighandle, NULL);
350 sigaction(SIGUSR2, &sighandle, NULL);
351 sigaction(SIGALRM, &sighandle, NULL);
352 sigaction(SIGTERM, &sighandle, NULL);
354 sigaction(SIGSTKFLT, &sighandle, NULL);
356 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
357 sigaction(SIGTSTP, &sighandle, NULL);
358 sigaction(SIGTTIN, &sighandle, NULL);
359 sigaction(SIGTTOU, &sighandle, NULL);
360 sigaction(SIGURG, &sighandle, NULL);
361 sigaction(SIGVTALRM, &sighandle, NULL);
363 sigaction(SIGPWR, &sighandle, NULL);
366 sigaction(SIGWAITING,&sighandle, NULL);
369 sigaction(SIGLWP, &sighandle, NULL);
372 sigaction(SIGFREEZE, &sighandle, NULL);
375 sigaction(SIGTHAW, &sighandle, NULL);
378 sigaction(SIGCANCEL, &sighandle, NULL);
381 sigaction(SIGLOST, &sighandle, NULL);