2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 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[];
57 static const char *sig_names[BA_NSIG+1];
59 typedef void (SIG_HANDLER)(int sig);
60 static SIG_HANDLER *exit_handler;
63 static pid_t main_pid = 0;
65 const char *get_signal_name(int sig)
67 if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
68 return _("Invalid signal number");
70 return sig_names[sig];
77 extern "C" void signal_handler(int sig)
79 static int already_dead = 0;
81 /* If we come back more than once, get out fast! */
85 Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
86 /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
87 if (sig == SIGCHLD || sig == SIGUSR2) {
92 // Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
94 Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
99 struct sigaction sigdefault;
100 static char *argv[4];
101 static char pid_buf[20];
102 static char btpath[400];
105 int exelen = strlen(exepath);
107 fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
108 exename, my_name, sig, get_signal_name(sig));
109 fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
111 if (exelen + 12 > (int)sizeof(btpath)) {
112 bstrncpy(btpath, "btraceback", sizeof(btpath));
114 bstrncpy(btpath, exepath, sizeof(btpath));
115 if (IsPathSeparator(btpath[exelen-1])) {
116 btpath[exelen-1] = 0;
118 bstrncat(btpath, "/btraceback", sizeof(btpath));
120 if (!IsPathSeparator(exepath[exelen - 1])) {
121 strcat(exepath, "/");
123 strcat(exepath, exename);
124 if (!working_directory) {
125 working_directory = buf;
128 if (*working_directory == 0) {
129 strcpy((char *)working_directory, "/tmp/");
131 if (chdir(working_directory) != 0) { /* dump in working directory */
133 Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
134 strcpy((char *)working_directory, "/tmp/");
136 unlink("./core"); /* get rid of any old core file */
137 sprintf(pid_buf, "%d", (int)main_pid);
138 Dmsg1(300, "Working=%s\n", working_directory);
139 Dmsg1(300, "btpath=%s\n", btpath);
140 Dmsg1(300, "exepath=%s\n", exepath);
141 switch (pid = fork()) {
143 fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
146 argv[0] = btpath; /* path to btraceback */
147 argv[1] = exepath; /* path to exe */
149 argv[3] = (char *)NULL;
150 fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
151 if (execv(btpath, argv) != 0) {
153 printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
156 default: /* parent */
159 /* Parent continue here, waiting for child */
160 sigdefault.sa_flags = 0;
161 sigdefault.sa_handler = SIG_DFL;
162 sigfillset(&sigdefault.sa_mask);
164 sigaction(sig, &sigdefault, NULL);
166 Dmsg0(500, "Doing waitpid\n");
167 waitpid(pid, NULL, 0); /* wait for child to produce dump */
168 fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
169 Dmsg0(500, "Done waitpid\n");
170 exit_handler(sig); /* clean up if possible */
171 Dmsg0(500, "Done exit_handler\n");
173 Dmsg0(500, "Doing sleep\n");
176 fprintf(stderr, _("It looks like the traceback worked ...\n"));
184 * Init stack dump by saving main process id --
185 * needed by debugger to attach to this program.
187 void init_stack_dump(void)
189 main_pid = getpid(); /* save main thread's pid */
195 void init_signals(void terminate(int sig))
197 struct sigaction sighandle;
198 struct sigaction sigignore;
199 struct sigaction sigdefault;
203 exit_handler = terminate;
204 if (BA_NSIG < _sys_nsig)
205 Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
207 for (i=0; i<_sys_nsig; i++)
208 sig_names[i] = _sys_siglist[i];
210 exit_handler = terminate;
211 sig_names[0] = _("UNKNOWN SIGNAL");
212 sig_names[SIGHUP] = _("Hangup");
213 sig_names[SIGINT] = _("Interrupt");
214 sig_names[SIGQUIT] = _("Quit");
215 sig_names[SIGILL] = _("Illegal instruction");;
216 sig_names[SIGTRAP] = _("Trace/Breakpoint trap");
217 sig_names[SIGABRT] = _("Abort");
219 sig_names[SIGEMT] = _("EMT instruction (Emulation Trap)");
222 sig_names[SIGIOT] = _("IOT trap");
224 sig_names[SIGBUS] = _("BUS error");
225 sig_names[SIGFPE] = _("Floating-point exception");
226 sig_names[SIGKILL] = _("Kill, unblockable");
227 sig_names[SIGUSR1] = _("User-defined signal 1");
228 sig_names[SIGSEGV] = _("Segmentation violation");
229 sig_names[SIGUSR2] = _("User-defined signal 2");
230 sig_names[SIGPIPE] = _("Broken pipe");
231 sig_names[SIGALRM] = _("Alarm clock");
232 sig_names[SIGTERM] = _("Termination");
234 sig_names[SIGSTKFLT] = _("Stack fault");
236 sig_names[SIGCHLD] = _("Child status has changed");
237 sig_names[SIGCONT] = _("Continue");
238 sig_names[SIGSTOP] = _("Stop, unblockable");
239 sig_names[SIGTSTP] = _("Keyboard stop");
240 sig_names[SIGTTIN] = _("Background read from tty");
241 sig_names[SIGTTOU] = _("Background write to tty");
242 sig_names[SIGURG] = _("Urgent condition on socket");
243 sig_names[SIGXCPU] = _("CPU limit exceeded");
244 sig_names[SIGXFSZ] = _("File size limit exceeded");
245 sig_names[SIGVTALRM] = _("Virtual alarm clock");
246 sig_names[SIGPROF] = _("Profiling alarm clock");
247 sig_names[SIGWINCH] = _("Window size change");
248 sig_names[SIGIO] = _("I/O now possible");
250 sig_names[SIGPWR] = _("Power failure restart");
253 sig_names[SIGWAITING] = _("No runnable lwp");
256 sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
259 sig_names[SIGFREEZE] = _("Checkpoint Freeze");
262 sig_names[SIGTHAW] = _("Checkpoint Thaw");
265 sig_names[SIGCANCEL] = _("Thread Cancellation");
268 sig_names[SIGLOST] = _("Resource Lost (e.g. record-lock lost)");
273 /* Now setup signal handlers */
274 sighandle.sa_flags = 0;
275 sighandle.sa_handler = signal_handler;
276 sigfillset(&sighandle.sa_mask);
277 sigignore.sa_flags = 0;
278 sigignore.sa_handler = SIG_IGN;
279 sigfillset(&sigignore.sa_mask);
280 sigdefault.sa_flags = 0;
281 sigdefault.sa_handler = SIG_DFL;
282 sigfillset(&sigdefault.sa_mask);
285 sigaction(SIGPIPE, &sigignore, NULL);
286 sigaction(SIGCHLD, &sighandle, NULL);
287 sigaction(SIGCONT, &sigignore, NULL);
288 sigaction(SIGPROF, &sigignore, NULL);
289 sigaction(SIGWINCH, &sigignore, NULL);
290 sigaction(SIGIO, &sighandle, NULL);
292 sigaction(SIGINT, &sigdefault, NULL);
293 sigaction(SIGXCPU, &sigdefault, NULL);
294 sigaction(SIGXFSZ, &sigdefault, NULL);
296 sigaction(SIGHUP, &sigignore, NULL);
297 sigaction(SIGQUIT, &sighandle, NULL);
298 sigaction(SIGILL, &sighandle, NULL);
299 sigaction(SIGTRAP, &sighandle, NULL);
300 sigaction(SIGABRT, &sighandle, NULL);
302 sigaction(SIGEMT, &sighandle, NULL);
305 sigaction(SIGIOT, &sighandle, NULL);
307 sigaction(SIGBUS, &sighandle, NULL);
308 sigaction(SIGFPE, &sighandle, NULL);
309 /* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
310 sigaction(SIGUSR1, &sighandle, NULL);
311 sigaction(SIGSEGV, &sighandle, NULL);
312 sigaction(SIGUSR2, &sighandle, NULL);
313 sigaction(SIGALRM, &sighandle, NULL);
314 sigaction(SIGTERM, &sighandle, NULL);
316 sigaction(SIGSTKFLT, &sighandle, NULL);
318 /* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
319 sigaction(SIGTSTP, &sighandle, NULL);
320 sigaction(SIGTTIN, &sighandle, NULL);
321 sigaction(SIGTTOU, &sighandle, NULL);
322 sigaction(SIGURG, &sighandle, NULL);
323 sigaction(SIGVTALRM, &sighandle, NULL);
325 sigaction(SIGPWR, &sighandle, NULL);
328 sigaction(SIGWAITING,&sighandle, NULL);
331 sigaction(SIGLWP, &sighandle, NULL);
334 sigaction(SIGFREEZE, &sighandle, NULL);
337 sigaction(SIGTHAW, &sighandle, NULL);
340 sigaction(SIGCANCEL, &sighandle, NULL);
343 sigaction(SIGLOST, &sighandle, NULL);