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);
79 /* defined in lockmgr.c */
80 extern void dbg_print_lock(FILE *fp);
85 * This function should be used ONLY after a violent signal. We walk through the
86 * JCR chain without doing any lock, bacula should not be running.
88 static void dbg_print_bacula()
92 snprintf(buf, sizeof(buf), "%s/%s.%d.bactrace",
93 working_directory, my_name, getpid());
94 FILE *fp = fopen(buf, "ab") ;
99 fprintf(stderr, "Dumping: %s\n", buf);
101 /* Print also B_DB and RWLOCK structure
102 * Can add more info about JCR with dbg_jcr_add_hook()
106 _dbg_print_plugin(fp);
115 * Handle signals here
117 extern "C" void signal_handler(int sig)
119 static int already_dead = 0;
121 /* If we come back more than once, get out fast! */
125 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
126 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
127 if (sig == SIGCHLD || sig == SIGUSR2) {
131 if (sig == SIGTERM) {
132 // Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
134 /* ***FIXME*** Display a message without taking any lock in the system
135 * Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
137 fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
141 if (sig != SIGTERM) {
142 struct sigaction sigdefault;
143 static char *argv[4];
144 static char pid_buf[20];
145 static char btpath[400];
148 int exelen = strlen(exepath);
150 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
151 exename, my_name, sig, get_signal_name(sig));
152 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
154 if (exelen + 12 > (int)sizeof(btpath)) {
155 bstrncpy(btpath, "btraceback", sizeof(btpath));
157 bstrncpy(btpath, exepath, sizeof(btpath));
158 if (IsPathSeparator(btpath[exelen-1])) {
159 btpath[exelen-1] = 0;
161 bstrncat(btpath, "/btraceback", sizeof(btpath));
163 if (!IsPathSeparator(exepath[exelen - 1])) {
164 strcat(exepath, "/");
166 strcat(exepath, exename);
167 if (!working_directory) {
168 working_directory = buf;
171 if (*working_directory == 0) {
172 strcpy((char *)working_directory, "/tmp/");
174 if (chdir(working_directory) != 0) { /* dump in working directory */
176 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
177 strcpy((char *)working_directory, "/tmp/");
179 unlink("./core"); /* get rid of any old core file */
180 sprintf(pid_buf, "%d", (int)main_pid);
181 Dmsg1(300, "Working=%s\n", working_directory);
182 Dmsg1(300, "btpath=%s\n", btpath);
183 Dmsg1(300, "exepath=%s\n", exepath);
184 switch (pid = fork()) {
186 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
189 argv[0] = btpath; /* path to btraceback */
190 argv[1] = exepath; /* path to exe */
192 argv[3] = (char *)NULL;
193 fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
194 if (execv(btpath, argv) != 0) {
196 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
199 default: /* parent */
203 /* Parent continue here, waiting for child */
204 sigdefault.sa_flags = 0;
205 sigdefault.sa_handler = SIG_DFL;
206 sigfillset(&sigdefault.sa_mask);
208 sigaction(sig, &sigdefault, NULL);
210 Dmsg0(500, "Doing waitpid\n");
211 waitpid(pid, NULL, 0); /* wait for child to produce dump */
212 Dmsg0(500, "Done waitpid\n");
213 fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
214 /* print information about the current state into working/<file>.bactrace */
216 exit_handler(sig); /* clean up if possible */
217 Dmsg0(500, "Done exit_handler\n");
219 Dmsg0(500, "Doing sleep\n");
222 fprintf(stderr, _("It looks like the traceback worked ...\n"));
230 * Init stack dump by saving main process id --
231 * needed by debugger to attach to this program.
233 void init_stack_dump(void)
235 main_pid = getpid(); /* save main thread's pid */
236 lmgr_init_thread(); /* initialize the lockmanager stack */
242 void init_signals(void terminate(int sig))
244 struct sigaction sighandle;
245 struct sigaction sigignore;
246 struct sigaction sigdefault;
250 exit_handler = terminate;
251 if (BA_NSIG < _sys_nsig)
252 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
254 for (i=0; i<_sys_nsig; i++)
255 sig_names[i] = _sys_siglist[i];
257 exit_handler = terminate;
258 sig_names[0] = _("UNKNOWN SIGNAL");
259 sig_names[SIGHUP] = _("Hangup");
260 sig_names[SIGINT] = _("Interrupt");
261 sig_names[SIGQUIT] = _("Quit");
262 sig_names[SIGILL] = _("Illegal instruction");;
263 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
264 sig_names[SIGABRT] = _("Abort");
266 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
269 sig_names[SIGIOT] = _("IOT trap");
271 sig_names[SIGBUS] = _("BUS error");
272 sig_names[SIGFPE] = _("Floating-point exception");
273 sig_names[SIGKILL] = _("Kill, unblockable");
274 sig_names[SIGUSR1] = _("User-defined signal 1");
275 sig_names[SIGSEGV] = _("Segmentation violation");
276 sig_names[SIGUSR2] = _("User-defined signal 2");
277 sig_names[SIGPIPE] = _("Broken pipe");
278 sig_names[SIGALRM] = _("Alarm clock");
279 sig_names[SIGTERM] = _("Termination");
281 sig_names[SIGSTKFLT] = _("Stack fault");
283 sig_names[SIGCHLD] = _("Child status has changed");
284 sig_names[SIGCONT] = _("Continue");
285 sig_names[SIGSTOP] = _("Stop, unblockable");
286 sig_names[SIGTSTP] = _("Keyboard stop");
287 sig_names[SIGTTIN] = _("Background read from tty");
288 sig_names[SIGTTOU] = _("Background write to tty");
289 sig_names[SIGURG] = _("Urgent condition on socket");
290 sig_names[SIGXCPU] = _("CPU limit exceeded");
291 sig_names[SIGXFSZ] = _("File size limit exceeded");
292 sig_names[SIGVTALRM] = _("Virtual alarm clock");
293 sig_names[SIGPROF] = _("Profiling alarm clock");
294 sig_names[SIGWINCH] = _("Window size change");
295 sig_names[SIGIO] = _("I/O now possible");
297 sig_names[SIGPWR] = _("Power failure restart");
300 sig_names[SIGWAITING] = _("No runnable lwp");
303 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
306 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
309 sig_names[SIGTHAW] = _("Checkpoint Thaw");
312 sig_names[SIGCANCEL] = _("Thread Cancellation");
315 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
320 /* Now setup signal handlers */
321 sighandle.sa_flags = 0;
322 sighandle.sa_handler = signal_handler;
323 sigfillset(&sighandle.sa_mask);
324 sigignore.sa_flags = 0;
325 sigignore.sa_handler = SIG_IGN;
326 sigfillset(&sigignore.sa_mask);
327 sigdefault.sa_flags = 0;
328 sigdefault.sa_handler = SIG_DFL;
329 sigfillset(&sigdefault.sa_mask);
332 sigaction(SIGPIPE, &sigignore, NULL);
333 sigaction(SIGCHLD, &sighandle, NULL);
334 sigaction(SIGCONT, &sigignore, NULL);
335 sigaction(SIGPROF, &sigignore, NULL);
336 sigaction(SIGWINCH, &sigignore, NULL);
337 sigaction(SIGIO, &sighandle, NULL);
339 sigaction(SIGINT, &sigdefault, NULL);
340 sigaction(SIGXCPU, &sigdefault, NULL);
341 sigaction(SIGXFSZ, &sigdefault, NULL);
343 sigaction(SIGHUP, &sigignore, NULL);
344 sigaction(SIGQUIT, &sighandle, NULL);
345 sigaction(SIGILL, &sighandle, NULL);
346 sigaction(SIGTRAP, &sighandle, NULL);
347 sigaction(SIGABRT, &sighandle, NULL);
349 sigaction(SIGEMT, &sighandle, NULL);
352 sigaction(SIGIOT, &sighandle, NULL);
354 sigaction(SIGBUS, &sighandle, NULL);
355 sigaction(SIGFPE, &sighandle, NULL);
356 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
357 sigaction(SIGUSR1, &sighandle, NULL);
358 sigaction(SIGSEGV, &sighandle, NULL);
359 sigaction(SIGUSR2, &sighandle, NULL);
360 sigaction(SIGALRM, &sighandle, NULL);
361 sigaction(SIGTERM, &sighandle, NULL);
363 sigaction(SIGSTKFLT, &sighandle, NULL);
365 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
366 sigaction(SIGTSTP, &sighandle, NULL);
367 sigaction(SIGTTIN, &sighandle, NULL);
368 sigaction(SIGTTOU, &sighandle, NULL);
369 sigaction(SIGURG, &sighandle, NULL);
370 sigaction(SIGVTALRM, &sighandle, NULL);
372 sigaction(SIGPWR, &sighandle, NULL);
375 sigaction(SIGWAITING,&sighandle, NULL);
378 sigaction(SIGLWP, &sighandle, NULL);
381 sigaction(SIGFREEZE, &sighandle, NULL);
384 sigaction(SIGTHAW, &sighandle, NULL);
387 sigaction(SIGCANCEL, &sighandle, NULL);
390 sigaction(SIGLOST, &sighandle, NULL);