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 _print_jcr_dbg(FILE *fp);
81 * This function should be used ONLY after a violent signal. We walk through the
82 * JCR chain without doing any lock, bacula should not be running.
84 static void print_bacula_dbg()
88 snprintf(buf, sizeof(buf), "%s/bacula.%d.bactrace",
89 working_directory, getpid());
90 FILE *fp = fopen(buf, "ab") ;
104 * Handle signals here
106 extern "C" void signal_handler(int sig)
108 static int already_dead = 0;
110 /* If we come back more than once, get out fast! */
114 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
115 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
116 if (sig == SIGCHLD || sig == SIGUSR2) {
120 if (sig == SIGTERM) {
121 // Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
123 Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
127 if (sig != SIGTERM) {
128 struct sigaction sigdefault;
129 static char *argv[4];
130 static char pid_buf[20];
131 static char btpath[400];
134 int exelen = strlen(exepath);
136 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
137 exename, my_name, sig, get_signal_name(sig));
138 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
140 if (exelen + 12 > (int)sizeof(btpath)) {
141 bstrncpy(btpath, "btraceback", sizeof(btpath));
143 bstrncpy(btpath, exepath, sizeof(btpath));
144 if (IsPathSeparator(btpath[exelen-1])) {
145 btpath[exelen-1] = 0;
147 bstrncat(btpath, "/btraceback", sizeof(btpath));
149 if (!IsPathSeparator(exepath[exelen - 1])) {
150 strcat(exepath, "/");
152 strcat(exepath, exename);
153 if (!working_directory) {
154 working_directory = buf;
157 if (*working_directory == 0) {
158 strcpy((char *)working_directory, "/tmp/");
160 if (chdir(working_directory) != 0) { /* dump in working directory */
162 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
163 strcpy((char *)working_directory, "/tmp/");
165 unlink("./core"); /* get rid of any old core file */
166 sprintf(pid_buf, "%d", (int)main_pid);
167 Dmsg1(300, "Working=%s\n", working_directory);
168 Dmsg1(300, "btpath=%s\n", btpath);
169 Dmsg1(300, "exepath=%s\n", exepath);
170 switch (pid = fork()) {
172 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
175 argv[0] = btpath; /* path to btraceback */
176 argv[1] = exepath; /* path to exe */
178 argv[3] = (char *)NULL;
179 fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
180 if (execv(btpath, argv) != 0) {
182 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
185 default: /* parent */
189 /* Parent continue here, waiting for child */
190 sigdefault.sa_flags = 0;
191 sigdefault.sa_handler = SIG_DFL;
192 sigfillset(&sigdefault.sa_mask);
194 sigaction(sig, &sigdefault, NULL);
196 Dmsg0(500, "Doing waitpid\n");
197 waitpid(pid, NULL, 0); /* wait for child to produce dump */
198 Dmsg0(500, "Done waitpid\n");
199 fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
200 /* print information about the current state into working/<file>.bactrace */
202 exit_handler(sig); /* clean up if possible */
203 Dmsg0(500, "Done exit_handler\n");
205 Dmsg0(500, "Doing sleep\n");
208 fprintf(stderr, _("It looks like the traceback worked ...\n"));
216 * Init stack dump by saving main process id --
217 * needed by debugger to attach to this program.
219 void init_stack_dump(void)
221 main_pid = getpid(); /* save main thread's pid */
227 void init_signals(void terminate(int sig))
229 struct sigaction sighandle;
230 struct sigaction sigignore;
231 struct sigaction sigdefault;
235 exit_handler = terminate;
236 if (BA_NSIG < _sys_nsig)
237 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
239 for (i=0; i<_sys_nsig; i++)
240 sig_names[i] = _sys_siglist[i];
242 exit_handler = terminate;
243 sig_names[0] = _("UNKNOWN SIGNAL");
244 sig_names[SIGHUP] = _("Hangup");
245 sig_names[SIGINT] = _("Interrupt");
246 sig_names[SIGQUIT] = _("Quit");
247 sig_names[SIGILL] = _("Illegal instruction");;
248 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
249 sig_names[SIGABRT] = _("Abort");
251 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
254 sig_names[SIGIOT] = _("IOT trap");
256 sig_names[SIGBUS] = _("BUS error");
257 sig_names[SIGFPE] = _("Floating-point exception");
258 sig_names[SIGKILL] = _("Kill, unblockable");
259 sig_names[SIGUSR1] = _("User-defined signal 1");
260 sig_names[SIGSEGV] = _("Segmentation violation");
261 sig_names[SIGUSR2] = _("User-defined signal 2");
262 sig_names[SIGPIPE] = _("Broken pipe");
263 sig_names[SIGALRM] = _("Alarm clock");
264 sig_names[SIGTERM] = _("Termination");
266 sig_names[SIGSTKFLT] = _("Stack fault");
268 sig_names[SIGCHLD] = _("Child status has changed");
269 sig_names[SIGCONT] = _("Continue");
270 sig_names[SIGSTOP] = _("Stop, unblockable");
271 sig_names[SIGTSTP] = _("Keyboard stop");
272 sig_names[SIGTTIN] = _("Background read from tty");
273 sig_names[SIGTTOU] = _("Background write to tty");
274 sig_names[SIGURG] = _("Urgent condition on socket");
275 sig_names[SIGXCPU] = _("CPU limit exceeded");
276 sig_names[SIGXFSZ] = _("File size limit exceeded");
277 sig_names[SIGVTALRM] = _("Virtual alarm clock");
278 sig_names[SIGPROF] = _("Profiling alarm clock");
279 sig_names[SIGWINCH] = _("Window size change");
280 sig_names[SIGIO] = _("I/O now possible");
282 sig_names[SIGPWR] = _("Power failure restart");
285 sig_names[SIGWAITING] = _("No runnable lwp");
288 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
291 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
294 sig_names[SIGTHAW] = _("Checkpoint Thaw");
297 sig_names[SIGCANCEL] = _("Thread Cancellation");
300 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
305 /* Now setup signal handlers */
306 sighandle.sa_flags = 0;
307 sighandle.sa_handler = signal_handler;
308 sigfillset(&sighandle.sa_mask);
309 sigignore.sa_flags = 0;
310 sigignore.sa_handler = SIG_IGN;
311 sigfillset(&sigignore.sa_mask);
312 sigdefault.sa_flags = 0;
313 sigdefault.sa_handler = SIG_DFL;
314 sigfillset(&sigdefault.sa_mask);
317 sigaction(SIGPIPE, &sigignore, NULL);
318 sigaction(SIGCHLD, &sighandle, NULL);
319 sigaction(SIGCONT, &sigignore, NULL);
320 sigaction(SIGPROF, &sigignore, NULL);
321 sigaction(SIGWINCH, &sigignore, NULL);
322 sigaction(SIGIO, &sighandle, NULL);
324 sigaction(SIGINT, &sigdefault, NULL);
325 sigaction(SIGXCPU, &sigdefault, NULL);
326 sigaction(SIGXFSZ, &sigdefault, NULL);
328 sigaction(SIGHUP, &sigignore, NULL);
329 sigaction(SIGQUIT, &sighandle, NULL);
330 sigaction(SIGILL, &sighandle, NULL);
331 sigaction(SIGTRAP, &sighandle, NULL);
332 sigaction(SIGABRT, &sighandle, NULL);
334 sigaction(SIGEMT, &sighandle, NULL);
337 sigaction(SIGIOT, &sighandle, NULL);
339 sigaction(SIGBUS, &sighandle, NULL);
340 sigaction(SIGFPE, &sighandle, NULL);
341 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
342 sigaction(SIGUSR1, &sighandle, NULL);
343 sigaction(SIGSEGV, &sighandle, NULL);
344 sigaction(SIGUSR2, &sighandle, NULL);
345 sigaction(SIGALRM, &sighandle, NULL);
346 sigaction(SIGTERM, &sighandle, NULL);
348 sigaction(SIGSTKFLT, &sighandle, NULL);
350 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
351 sigaction(SIGTSTP, &sighandle, NULL);
352 sigaction(SIGTTIN, &sighandle, NULL);
353 sigaction(SIGTTOU, &sighandle, NULL);
354 sigaction(SIGURG, &sighandle, NULL);
355 sigaction(SIGVTALRM, &sighandle, NULL);
357 sigaction(SIGPWR, &sighandle, NULL);
360 sigaction(SIGWAITING,&sighandle, NULL);
363 sigaction(SIGLWP, &sighandle, NULL);
366 sigaction(SIGFREEZE, &sighandle, NULL);
369 sigaction(SIGTHAW, &sighandle, NULL);
372 sigaction(SIGCANCEL, &sighandle, NULL);
375 sigaction(SIGLOST, &sighandle, NULL);