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];
78 extern "C" void signal_handler(int sig)
80 static int already_dead = 0;
82 /* If we come back more than once, get out fast! */
86 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
87 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
88 if (sig == SIGCHLD || sig == SIGUSR2) {
93 // Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
95 Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
100 struct sigaction sigdefault;
101 static char *argv[4];
102 static char pid_buf[20];
103 static char btpath[400];
106 int exelen = strlen(exepath);
108 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
109 exename, my_name, sig, get_signal_name(sig));
110 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
112 if (exelen + 12 > (int)sizeof(btpath)) {
113 bstrncpy(btpath, "btraceback", sizeof(btpath));
115 bstrncpy(btpath, exepath, sizeof(btpath));
116 if (IsPathSeparator(btpath[exelen-1])) {
117 btpath[exelen-1] = 0;
119 bstrncat(btpath, "/btraceback", sizeof(btpath));
121 if (!IsPathSeparator(exepath[exelen - 1])) {
122 strcat(exepath, "/");
124 strcat(exepath, exename);
125 if (!working_directory) {
126 working_directory = buf;
129 if (*working_directory == 0) {
130 strcpy((char *)working_directory, "/tmp/");
132 if (chdir(working_directory) != 0) { /* dump in working directory */
134 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
135 strcpy((char *)working_directory, "/tmp/");
137 unlink("./core"); /* get rid of any old core file */
138 sprintf(pid_buf, "%d", (int)main_pid);
139 Dmsg1(300, "Working=%s\n", working_directory);
140 Dmsg1(300, "btpath=%s\n", btpath);
141 Dmsg1(300, "exepath=%s\n", exepath);
142 switch (pid = fork()) {
144 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
147 argv[0] = btpath; /* path to btraceback */
148 argv[1] = exepath; /* path to exe */
150 argv[3] = (char *)NULL;
151 fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
152 if (execv(btpath, argv) != 0) {
154 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
157 default: /* parent */
161 /* Parent continue here, waiting for child */
162 sigdefault.sa_flags = 0;
163 sigdefault.sa_handler = SIG_DFL;
164 sigfillset(&sigdefault.sa_mask);
166 sigaction(sig, &sigdefault, NULL);
168 Dmsg0(500, "Doing waitpid\n");
169 waitpid(pid, NULL, 0); /* wait for child to produce dump */
170 Dmsg0(500, "Done waitpid\n");
171 fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
172 /* print information about the current state into stderr */
175 exit_handler(sig); /* clean up if possible */
176 Dmsg0(500, "Done exit_handler\n");
178 Dmsg0(500, "Doing sleep\n");
181 fprintf(stderr, _("It looks like the traceback worked ...\n"));
189 * Init stack dump by saving main process id --
190 * needed by debugger to attach to this program.
192 void init_stack_dump(void)
194 main_pid = getpid(); /* save main thread's pid */
200 void init_signals(void terminate(int sig))
202 struct sigaction sighandle;
203 struct sigaction sigignore;
204 struct sigaction sigdefault;
208 exit_handler = terminate;
209 if (BA_NSIG < _sys_nsig)
210 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
212 for (i=0; i<_sys_nsig; i++)
213 sig_names[i] = _sys_siglist[i];
215 exit_handler = terminate;
216 sig_names[0] = _("UNKNOWN SIGNAL");
217 sig_names[SIGHUP] = _("Hangup");
218 sig_names[SIGINT] = _("Interrupt");
219 sig_names[SIGQUIT] = _("Quit");
220 sig_names[SIGILL] = _("Illegal instruction");;
221 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
222 sig_names[SIGABRT] = _("Abort");
224 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
227 sig_names[SIGIOT] = _("IOT trap");
229 sig_names[SIGBUS] = _("BUS error");
230 sig_names[SIGFPE] = _("Floating-point exception");
231 sig_names[SIGKILL] = _("Kill, unblockable");
232 sig_names[SIGUSR1] = _("User-defined signal 1");
233 sig_names[SIGSEGV] = _("Segmentation violation");
234 sig_names[SIGUSR2] = _("User-defined signal 2");
235 sig_names[SIGPIPE] = _("Broken pipe");
236 sig_names[SIGALRM] = _("Alarm clock");
237 sig_names[SIGTERM] = _("Termination");
239 sig_names[SIGSTKFLT] = _("Stack fault");
241 sig_names[SIGCHLD] = _("Child status has changed");
242 sig_names[SIGCONT] = _("Continue");
243 sig_names[SIGSTOP] = _("Stop, unblockable");
244 sig_names[SIGTSTP] = _("Keyboard stop");
245 sig_names[SIGTTIN] = _("Background read from tty");
246 sig_names[SIGTTOU] = _("Background write to tty");
247 sig_names[SIGURG] = _("Urgent condition on socket");
248 sig_names[SIGXCPU] = _("CPU limit exceeded");
249 sig_names[SIGXFSZ] = _("File size limit exceeded");
250 sig_names[SIGVTALRM] = _("Virtual alarm clock");
251 sig_names[SIGPROF] = _("Profiling alarm clock");
252 sig_names[SIGWINCH] = _("Window size change");
253 sig_names[SIGIO] = _("I/O now possible");
255 sig_names[SIGPWR] = _("Power failure restart");
258 sig_names[SIGWAITING] = _("No runnable lwp");
261 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
264 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
267 sig_names[SIGTHAW] = _("Checkpoint Thaw");
270 sig_names[SIGCANCEL] = _("Thread Cancellation");
273 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
278 /* Now setup signal handlers */
279 sighandle.sa_flags = 0;
280 sighandle.sa_handler = signal_handler;
281 sigfillset(&sighandle.sa_mask);
282 sigignore.sa_flags = 0;
283 sigignore.sa_handler = SIG_IGN;
284 sigfillset(&sigignore.sa_mask);
285 sigdefault.sa_flags = 0;
286 sigdefault.sa_handler = SIG_DFL;
287 sigfillset(&sigdefault.sa_mask);
290 sigaction(SIGPIPE, &sigignore, NULL);
291 sigaction(SIGCHLD, &sighandle, NULL);
292 sigaction(SIGCONT, &sigignore, NULL);
293 sigaction(SIGPROF, &sigignore, NULL);
294 sigaction(SIGWINCH, &sigignore, NULL);
295 sigaction(SIGIO, &sighandle, NULL);
297 sigaction(SIGINT, &sigdefault, NULL);
298 sigaction(SIGXCPU, &sigdefault, NULL);
299 sigaction(SIGXFSZ, &sigdefault, NULL);
301 sigaction(SIGHUP, &sigignore, NULL);
302 sigaction(SIGQUIT, &sighandle, NULL);
303 sigaction(SIGILL, &sighandle, NULL);
304 sigaction(SIGTRAP, &sighandle, NULL);
305 sigaction(SIGABRT, &sighandle, NULL);
307 sigaction(SIGEMT, &sighandle, NULL);
310 sigaction(SIGIOT, &sighandle, NULL);
312 sigaction(SIGBUS, &sighandle, NULL);
313 sigaction(SIGFPE, &sighandle, NULL);
314 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
315 sigaction(SIGUSR1, &sighandle, NULL);
316 sigaction(SIGSEGV, &sighandle, NULL);
317 sigaction(SIGUSR2, &sighandle, NULL);
318 sigaction(SIGALRM, &sighandle, NULL);
319 sigaction(SIGTERM, &sighandle, NULL);
321 sigaction(SIGSTKFLT, &sighandle, NULL);
323 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
324 sigaction(SIGTSTP, &sighandle, NULL);
325 sigaction(SIGTTIN, &sighandle, NULL);
326 sigaction(SIGTTOU, &sighandle, NULL);
327 sigaction(SIGURG, &sighandle, NULL);
328 sigaction(SIGVTALRM, &sighandle, NULL);
330 sigaction(SIGPWR, &sighandle, NULL);
333 sigaction(SIGWAITING,&sighandle, NULL);
336 sigaction(SIGLWP, &sighandle, NULL);
339 sigaction(SIGFREEZE, &sighandle, NULL);
342 sigaction(SIGTHAW, &sighandle, NULL);
345 sigaction(SIGCANCEL, &sighandle, NULL);
348 sigaction(SIGLOST, &sighandle, NULL);