]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/signal.c
ebl Remove extra db lock debug
[bacula/bacula] / bacula / src / lib / signal.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
5
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
11    in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  *  Signal handlers for Bacula daemons
30  *
31  *   Kern Sibbald, April 2000
32  *
33  *   Version $Id$
34  *
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.
41  *
42  */
43
44 #ifndef HAVE_WIN32
45 #include "bacula.h"
46
47 #ifndef _NSIG
48 #define BA_NSIG 100
49 #else
50 #define BA_NSIG _NSIG
51 #endif
52
53 extern char my_name[];
54 extern char *exepath;
55 extern char *exename;
56 extern void print_jcr_dbg();
57
58 static const char *sig_names[BA_NSIG+1];
59
60 typedef void (SIG_HANDLER)(int sig);
61 static SIG_HANDLER *exit_handler;
62
63 /* main process id */
64 static pid_t main_pid = 0;
65
66 const char *get_signal_name(int sig)
67 {
68    if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
69       return _("Invalid signal number");
70    } else {
71       return sig_names[sig];
72    }
73 }
74
75 /* defined in jcr.c */
76 extern void _print_jcr_dbg(FILE *fp);
77
78 /*
79  * !!! WARNING !!! 
80  *
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.
83  */
84 static void print_bacula_dbg()
85 {
86    char buf[512];
87
88    snprintf(buf, sizeof(buf), "%s/bacula.%d.bactrace", 
89             working_directory, getpid());
90    FILE *fp = fopen(buf, "ab") ;
91    if (!fp) {
92       fp = stderr;
93    }
94
95    _print_jcr_dbg(fp);
96    print_lock_dbg(fp);
97
98    if (fp != stderr) {
99       fclose(fp);
100    }
101 }
102
103 /*
104  * Handle signals here
105  */
106 extern "C" void signal_handler(int sig)
107 {
108    static int already_dead = 0;
109
110    /* If we come back more than once, get out fast! */
111    if (already_dead) {
112       exit(1);
113    }
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) {
117       return;
118    }
119    already_dead++;
120    if (sig == SIGTERM) {
121 //    Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
122    } else {
123       Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
124    }
125
126 #ifdef TRACEBACK
127    if (sig != SIGTERM) {
128       struct sigaction sigdefault;
129       static char *argv[4];
130       static char pid_buf[20];
131       static char btpath[400];
132       char buf[100];
133       pid_t pid;
134       int exelen = strlen(exepath);
135
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);
139
140       if (exelen + 12 > (int)sizeof(btpath)) {
141          bstrncpy(btpath, "btraceback", sizeof(btpath));
142       } else {
143          bstrncpy(btpath, exepath, sizeof(btpath));
144          if (IsPathSeparator(btpath[exelen-1])) {
145             btpath[exelen-1] = 0;
146          }
147          bstrncat(btpath, "/btraceback", sizeof(btpath));
148       }
149       if (!IsPathSeparator(exepath[exelen - 1])) {
150          strcat(exepath, "/");
151       }
152       strcat(exepath, exename);
153       if (!working_directory) {
154          working_directory = buf;
155          *buf = 0;
156       }
157       if (*working_directory == 0) {
158          strcpy((char *)working_directory, "/tmp/");
159       }
160       if (chdir(working_directory) != 0) {  /* dump in working directory */
161          berrno be;
162          Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory,  be.bstrerror());
163          strcpy((char *)working_directory, "/tmp/");
164       }
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()) {
171       case -1:                        /* error */
172          fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
173          break;
174       case 0:                         /* child */
175          argv[0] = btpath;            /* path to btraceback */
176          argv[1] = exepath;           /* path to exe */
177          argv[2] = pid_buf;
178          argv[3] = (char *)NULL;
179          fprintf(stderr, _("Calling: %s %s %s\n"), btpath, exepath, pid_buf);
180          if (execv(btpath, argv) != 0) {
181             berrno be;
182             printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
183          }
184          exit(-1);
185       default:                        /* parent */
186          break;
187       }
188
189       /* Parent continue here, waiting for child */
190       sigdefault.sa_flags = 0;
191       sigdefault.sa_handler = SIG_DFL;
192       sigfillset(&sigdefault.sa_mask);
193
194       sigaction(sig,  &sigdefault, NULL);
195       if (pid > 0) {
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 */
201          print_bacula_dbg();
202          exit_handler(sig);           /* clean up if possible */
203          Dmsg0(500, "Done exit_handler\n");
204       } else {
205          Dmsg0(500, "Doing sleep\n");
206          bmicrosleep(30, 0);
207       }
208       fprintf(stderr, _("It looks like the traceback worked ...\n"));
209    }
210 #endif
211
212    exit_handler(sig);
213 }
214
215 /*
216  * Init stack dump by saving main process id --
217  *   needed by debugger to attach to this program.
218  */
219 void init_stack_dump(void)
220 {
221    main_pid = getpid();               /* save main thread's pid */
222 }
223
224 /*
225  * Initialize signals
226  */
227 void init_signals(void terminate(int sig))
228 {
229    struct sigaction sighandle;
230    struct sigaction sigignore;
231    struct sigaction sigdefault;
232 #ifdef _sys_nsig
233    int i;
234
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);
238
239    for (i=0; i<_sys_nsig; i++)
240       sig_names[i] = _sys_siglist[i];
241 #else
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");
250 #ifdef SIGEMT
251    sig_names[SIGEMT]    = _("EMT instruction (Emulation Trap)");
252 #endif
253 #ifdef SIGIOT
254    sig_names[SIGIOT]    = _("IOT trap");
255 #endif
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");
265 #ifdef SIGSTKFLT
266    sig_names[SIGSTKFLT] = _("Stack fault");
267 #endif
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");
281 #ifdef SIGPWR
282    sig_names[SIGPWR]    = _("Power failure restart");
283 #endif
284 #ifdef SIGWAITING
285    sig_names[SIGWAITING] = _("No runnable lwp");
286 #endif
287 #ifdef SIGLWP
288    sig_names[SIGLWP]     = _("SIGLWP special signal used by thread library");
289 #endif
290 #ifdef SIGFREEZE
291    sig_names[SIGFREEZE] = _("Checkpoint Freeze");
292 #endif
293 #ifdef SIGTHAW
294    sig_names[SIGTHAW]   = _("Checkpoint Thaw");
295 #endif
296 #ifdef SIGCANCEL
297    sig_names[SIGCANCEL] = _("Thread Cancellation");
298 #endif
299 #ifdef SIGLOST
300    sig_names[SIGLOST]   = _("Resource Lost (e.g. record-lock lost)");
301 #endif
302 #endif
303
304
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);
315
316
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);
323
324    sigaction(SIGINT,    &sigdefault, NULL);
325    sigaction(SIGXCPU,   &sigdefault, NULL);
326    sigaction(SIGXFSZ,   &sigdefault, NULL);
327
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);
333 #ifdef SIGEMT
334    sigaction(SIGEMT,    &sighandle, NULL);
335 #endif
336 #ifdef SIGIOT
337    sigaction(SIGIOT,    &sighandle, NULL);                     
338 #endif
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);
347 #ifdef SIGSTKFLT
348    sigaction(SIGSTKFLT, &sighandle, NULL);
349 #endif
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);
356 #ifdef SIGPWR
357    sigaction(SIGPWR,    &sighandle, NULL);
358 #endif
359 #ifdef SIGWAITING
360    sigaction(SIGWAITING,&sighandle, NULL);
361 #endif
362 #ifdef SIGLWP
363    sigaction(SIGLWP,    &sighandle, NULL);
364 #endif
365 #ifdef SIGFREEZE
366    sigaction(SIGFREEZE, &sighandle, NULL);
367 #endif
368 #ifdef SIGTHAW
369    sigaction(SIGTHAW,   &sighandle, NULL);
370 #endif
371 #ifdef SIGCANCEL
372    sigaction(SIGCANCEL, &sighandle, NULL);
373 #endif
374 #ifdef SIGLOST
375    sigaction(SIGLOST,   &sighandle, NULL);
376 #endif
377 }
378 #endif