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];
76 * Global variables to get information about lock/unlock db access
78 utime_t _db_lock_time = 0;
79 int _db_lock_recurse_count = 0;
80 pthread_t _db_lock_threadid;
82 static void print_lock_dbg(FILE *fp)
85 bstrutime(buf, sizeof(buf), _db_lock_time);
87 fprintf(fp, "lock info: recurse_count=%i threadid=0x%x time=%s\n",
88 _db_lock_recurse_count, (int)_db_lock_threadid, buf);
91 /* defined in jcr.c */
92 extern void _print_jcr_dbg(FILE *fp);
97 * This function should be used ONLY after a violent signal. We walk through the
98 * JCR chain without doing any lock, bacula should not be running.
100 static void print_bacula_dbg()
104 snprintf(buf, sizeof(buf), "%s/bacula.%d.bactrace",
105 working_directory, getpid());
106 FILE *fp = fopen(buf, "ab") ;
120 * Handle signals here
122 extern "C" void signal_handler(int sig)
124 static int already_dead = 0;
126 /* If we come back more than once, get out fast! */
130 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
131 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
132 if (sig == SIGCHLD || sig == SIGUSR2) {
136 if (sig == SIGTERM) {
137 // Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
139 Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
143 if (sig != SIGTERM) {
144 struct sigaction sigdefault;
145 static char *argv[4];
146 static char pid_buf[20];
147 static char btpath[400];
150 int exelen = strlen(exepath);
152 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
153 exename, my_name, sig, get_signal_name(sig));
154 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
156 if (exelen + 12 > (int)sizeof(btpath)) {
157 bstrncpy(btpath, "btraceback", sizeof(btpath));
159 bstrncpy(btpath, exepath, sizeof(btpath));
160 if (IsPathSeparator(btpath[exelen-1])) {
161 btpath[exelen-1] = 0;
163 bstrncat(btpath, "/btraceback", sizeof(btpath));
165 if (!IsPathSeparator(exepath[exelen - 1])) {
166 strcat(exepath, "/");
168 strcat(exepath, exename);
169 if (!working_directory) {
170 working_directory = buf;
173 if (*working_directory == 0) {
174 strcpy((char *)working_directory, "/tmp/");
176 if (chdir(working_directory) != 0) { /* dump in working directory */
178 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
179 strcpy((char *)working_directory, "/tmp/");
181 unlink("./core"); /* get rid of any old core file */
182 sprintf(pid_buf, "%d", (int)main_pid);
183 Dmsg1(300, "Working=%s\n", working_directory);
184 Dmsg1(300, "btpath=%s\n", btpath);
185 Dmsg1(300, "exepath=%s\n", exepath);
186 switch (pid = fork()) {
188 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
191 argv[0] = btpath; /* path to btraceback */
192 argv[1] = exepath; /* path to exe */
194 argv[3] = (char *)NULL;
195 fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
196 if (execv(btpath, argv) != 0) {
198 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
201 default: /* parent */
205 /* Parent continue here, waiting for child */
206 sigdefault.sa_flags = 0;
207 sigdefault.sa_handler = SIG_DFL;
208 sigfillset(&sigdefault.sa_mask);
210 sigaction(sig, &sigdefault, NULL);
212 Dmsg0(500, "Doing waitpid\n");
213 waitpid(pid, NULL, 0); /* wait for child to produce dump */
214 Dmsg0(500, "Done waitpid\n");
215 fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
216 /* print information about the current state into working/<file>.bactrace */
218 exit_handler(sig); /* clean up if possible */
219 Dmsg0(500, "Done exit_handler\n");
221 Dmsg0(500, "Doing sleep\n");
224 fprintf(stderr, _("It looks like the traceback worked ...\n"));
232 * Init stack dump by saving main process id --
233 * needed by debugger to attach to this program.
235 void init_stack_dump(void)
237 main_pid = getpid(); /* save main thread's pid */
243 void init_signals(void terminate(int sig))
245 struct sigaction sighandle;
246 struct sigaction sigignore;
247 struct sigaction sigdefault;
251 exit_handler = terminate;
252 if (BA_NSIG < _sys_nsig)
253 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
255 for (i=0; i<_sys_nsig; i++)
256 sig_names[i] = _sys_siglist[i];
258 exit_handler = terminate;
259 sig_names[0] = _("UNKNOWN SIGNAL");
260 sig_names[SIGHUP] = _("Hangup");
261 sig_names[SIGINT] = _("Interrupt");
262 sig_names[SIGQUIT] = _("Quit");
263 sig_names[SIGILL] = _("Illegal instruction");;
264 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
265 sig_names[SIGABRT] = _("Abort");
267 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
270 sig_names[SIGIOT] = _("IOT trap");
272 sig_names[SIGBUS] = _("BUS error");
273 sig_names[SIGFPE] = _("Floating-point exception");
274 sig_names[SIGKILL] = _("Kill, unblockable");
275 sig_names[SIGUSR1] = _("User-defined signal 1");
276 sig_names[SIGSEGV] = _("Segmentation violation");
277 sig_names[SIGUSR2] = _("User-defined signal 2");
278 sig_names[SIGPIPE] = _("Broken pipe");
279 sig_names[SIGALRM] = _("Alarm clock");
280 sig_names[SIGTERM] = _("Termination");
282 sig_names[SIGSTKFLT] = _("Stack fault");
284 sig_names[SIGCHLD] = _("Child status has changed");
285 sig_names[SIGCONT] = _("Continue");
286 sig_names[SIGSTOP] = _("Stop, unblockable");
287 sig_names[SIGTSTP] = _("Keyboard stop");
288 sig_names[SIGTTIN] = _("Background read from tty");
289 sig_names[SIGTTOU] = _("Background write to tty");
290 sig_names[SIGURG] = _("Urgent condition on socket");
291 sig_names[SIGXCPU] = _("CPU limit exceeded");
292 sig_names[SIGXFSZ] = _("File size limit exceeded");
293 sig_names[SIGVTALRM] = _("Virtual alarm clock");
294 sig_names[SIGPROF] = _("Profiling alarm clock");
295 sig_names[SIGWINCH] = _("Window size change");
296 sig_names[SIGIO] = _("I/O now possible");
298 sig_names[SIGPWR] = _("Power failure restart");
301 sig_names[SIGWAITING] = _("No runnable lwp");
304 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
307 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
310 sig_names[SIGTHAW] = _("Checkpoint Thaw");
313 sig_names[SIGCANCEL] = _("Thread Cancellation");
316 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
321 /* Now setup signal handlers */
322 sighandle.sa_flags = 0;
323 sighandle.sa_handler = signal_handler;
324 sigfillset(&sighandle.sa_mask);
325 sigignore.sa_flags = 0;
326 sigignore.sa_handler = SIG_IGN;
327 sigfillset(&sigignore.sa_mask);
328 sigdefault.sa_flags = 0;
329 sigdefault.sa_handler = SIG_DFL;
330 sigfillset(&sigdefault.sa_mask);
333 sigaction(SIGPIPE, &sigignore, NULL);
334 sigaction(SIGCHLD, &sighandle, NULL);
335 sigaction(SIGCONT, &sigignore, NULL);
336 sigaction(SIGPROF, &sigignore, NULL);
337 sigaction(SIGWINCH, &sigignore, NULL);
338 sigaction(SIGIO, &sighandle, NULL);
340 sigaction(SIGINT, &sigdefault, NULL);
341 sigaction(SIGXCPU, &sigdefault, NULL);
342 sigaction(SIGXFSZ, &sigdefault, NULL);
344 sigaction(SIGHUP, &sigignore, NULL);
345 sigaction(SIGQUIT, &sighandle, NULL);
346 sigaction(SIGILL, &sighandle, NULL);
347 sigaction(SIGTRAP, &sighandle, NULL);
348 sigaction(SIGABRT, &sighandle, NULL);
350 sigaction(SIGEMT, &sighandle, NULL);
353 sigaction(SIGIOT, &sighandle, NULL);
355 sigaction(SIGBUS, &sighandle, NULL);
356 sigaction(SIGFPE, &sighandle, NULL);
357 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
358 sigaction(SIGUSR1, &sighandle, NULL);
359 sigaction(SIGSEGV, &sighandle, NULL);
360 sigaction(SIGUSR2, &sighandle, NULL);
361 sigaction(SIGALRM, &sighandle, NULL);
362 sigaction(SIGTERM, &sighandle, NULL);
364 sigaction(SIGSTKFLT, &sighandle, NULL);
366 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
367 sigaction(SIGTSTP, &sighandle, NULL);
368 sigaction(SIGTTIN, &sighandle, NULL);
369 sigaction(SIGTTOU, &sighandle, NULL);
370 sigaction(SIGURG, &sighandle, NULL);
371 sigaction(SIGVTALRM, &sighandle, NULL);
373 sigaction(SIGPWR, &sighandle, NULL);
376 sigaction(SIGWAITING,&sighandle, NULL);
379 sigaction(SIGLWP, &sighandle, NULL);
382 sigaction(SIGFREEZE, &sighandle, NULL);
385 sigaction(SIGTHAW, &sighandle, NULL);
388 sigaction(SIGCANCEL, &sighandle, NULL);
391 sigaction(SIGLOST, &sighandle, NULL);