]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/signal.c
Pull src/lib changes from master
[bacula/bacula] / bacula / src / lib / signal.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2012 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 three of the GNU Affero 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 Affero 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  * Note, we probably should do a core dump for the serious
34  * signals such as SIGBUS, SIGPFE, ...
35  * Also, for SIGHUP and SIGUSR1, we should re-read the
36  * configuration file.  However, since this is a "general"
37  * routine, we leave it to the individual daemons to
38  * tweek their signals after calling this routine.
39  *
40  */
41
42 #ifndef HAVE_WIN32
43 #include "bacula.h"
44
45 #ifndef _NSIG
46 #define BA_NSIG 100
47 #else
48 #define BA_NSIG _NSIG
49 #endif
50
51 extern char my_name[];
52 extern char *exepath;
53 extern char *exename;
54 extern bool prt_kaboom;
55
56 static const char *sig_names[BA_NSIG+1];
57
58 typedef void (SIG_HANDLER)(int sig);
59 static SIG_HANDLER *exit_handler;
60
61 /* main process id */
62 static pid_t main_pid = 0;
63
64 const char *get_signal_name(int sig)
65 {
66    if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
67       return _("Invalid signal number");
68    } else {
69       return sig_names[sig];
70    }
71 }
72
73 /* defined in jcr.c */
74 extern void dbg_print_jcr(FILE *fp);
75 /* defined in plugins.c */
76 extern void dbg_print_plugin(FILE *fp);
77 /* defined in lockmgr.c */
78 extern void dbg_print_lock(FILE *fp);
79
80 /*
81  * !!! WARNING !!! 
82  *
83  * This function should be used ONLY after a violent signal. We walk through the
84  * JCR chain without locking, Bacula should not be running.
85  */
86 static void dbg_print_bacula()
87 {
88    char buf[512];
89
90    snprintf(buf, sizeof(buf), "%s/%s.%d.bactrace", 
91             working_directory, my_name, (int)getpid());
92    FILE *fp = fopen(buf, "a+") ;
93    if (!fp) {
94       fp = stderr;
95    }
96    
97    fprintf(stderr, "Dumping: %s\n", buf);
98
99    /* Print also B_DB and RWLOCK structure 
100     * Can add more info about JCR with dbg_jcr_add_hook()
101     */
102    dbg_print_lock(fp);
103    dbg_print_jcr(fp);
104    dbg_print_plugin(fp);
105
106    if (fp != stderr) {
107 #define direct_print
108 #ifdef direct_print
109       if (prt_kaboom) {
110          rewind(fp);
111          printf("\n\n ==== bactrace output ====\n\n");
112          while (fgets(buf, (int)sizeof(buf), fp) != NULL) {
113             printf("%s", buf);
114          }
115          printf(" ==== End baktrace output ====\n\n");
116       }
117 #else
118       if (prt_kaboom) {
119          char buf1[512];
120          printf("\n\n ==== bactrace output ====\n\n");
121          snprintf(buf1, sizeof(buf1), "/bin/cat %s", buf);
122          system(buf1);
123          printf(" ==== End baktrace output ====\n\n");
124       }
125 #endif
126       fclose(fp);
127    }
128 }
129
130 /*
131  * Handle signals here
132  */
133 extern "C" void signal_handler(int sig)
134 {
135    static int already_dead = 0;
136    int chld_status=-1;
137
138    /* If we come back more than once, get out fast! */
139    if (already_dead) {
140       exit(1);
141    }
142    Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
143    /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
144    if (sig == SIGCHLD || sig == SIGUSR2) {
145       return;
146    }
147    already_dead++;
148    /* Don't use Emsg here as it may lock and thus block us */
149    if (sig == SIGTERM) {
150        syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name);
151    } else {
152       fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
153       syslog(LOG_DAEMON|LOG_ERR, 
154          _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
155    }
156
157 #ifdef TRACEBACK
158    if (sig != SIGTERM) {
159       struct sigaction sigdefault;
160       static char *argv[5];
161       static char pid_buf[20];
162       static char btpath[400];
163       char buf[400];
164       pid_t pid;
165       int exelen = strlen(exepath);
166
167       fprintf(stderr, _("Kaboom! %s, %s got signal %d - %s. Attempting traceback.\n"),
168               exename, my_name, sig, get_signal_name(sig));
169       fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
170
171       if (exelen + 12 > (int)sizeof(btpath)) {
172          bstrncpy(btpath, "btraceback", sizeof(btpath));
173       } else {
174          bstrncpy(btpath, exepath, sizeof(btpath));
175          if (IsPathSeparator(btpath[exelen-1])) {
176             btpath[exelen-1] = 0;
177          }
178          bstrncat(btpath, "/btraceback", sizeof(btpath));
179       }
180       if (!IsPathSeparator(exepath[exelen - 1])) {
181          strcat(exepath, "/");
182       }
183       strcat(exepath, exename);
184       if (!working_directory) {
185          working_directory = buf;
186          *buf = 0;
187       }
188       if (*working_directory == 0) {
189          strcpy((char *)working_directory, "/tmp/");
190       }
191       if (chdir(working_directory) != 0) {  /* dump in working directory */
192          berrno be;
193          Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory,  be.bstrerror());
194          strcpy((char *)working_directory, "/tmp/");
195       }
196       unlink("./core");               /* get rid of any old core file */
197
198 #ifdef DEVELOPER /* When DEVELOPER not set, this is done below */
199       /* print information about the current state into working/<file>.bactrace */
200       dbg_print_bacula();
201 #endif
202
203
204       sprintf(pid_buf, "%d", (int)main_pid);
205       Dmsg1(300, "Working=%s\n", working_directory);
206       Dmsg1(300, "btpath=%s\n", btpath);
207       Dmsg1(300, "exepath=%s\n", exepath);
208       switch (pid = fork()) {
209       case -1:                        /* error */
210          fprintf(stderr, _("Fork error: ERR=%s\n"), strerror(errno));
211          break;
212       case 0:                         /* child */
213          argv[0] = btpath;            /* path to btraceback */
214          argv[1] = exepath;           /* path to exe */
215          argv[2] = pid_buf;
216          argv[3] = (char *)working_directory;
217          argv[4] = (char *)NULL;
218          fprintf(stderr, _("Calling: %s %s %s %s\n"), btpath, exepath, pid_buf,
219             working_directory);
220          if (execv(btpath, argv) != 0) {
221             berrno be;
222             printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
223          }
224          exit(-1);
225       default:                        /* parent */
226          break;
227       }
228
229       /* Parent continue here, waiting for child */
230       sigdefault.sa_flags = 0;
231       sigdefault.sa_handler = SIG_DFL;
232       sigfillset(&sigdefault.sa_mask);
233
234       sigaction(sig,  &sigdefault, NULL);
235       if (pid > 0) {
236          Dmsg0(500, "Doing waitpid\n");
237          waitpid(pid, &chld_status, 0);   /* wait for child to produce dump */
238          Dmsg0(500, "Done waitpid\n");
239       } else {
240          Dmsg0(500, "Doing sleep\n");
241          bmicrosleep(30, 0);
242       }
243       if (WEXITSTATUS(chld_status) == 0) {
244          fprintf(stderr, _("It looks like the traceback worked...\n"));
245       } else {
246          fprintf(stderr, _("The btraceback call returned %d\n"), 
247                            WEXITSTATUS(chld_status));
248       }
249       /* If we want it printed, do so */
250 #ifdef direct_print
251       if (prt_kaboom) {
252          FILE *fd;
253          snprintf(buf, sizeof(buf), "%s/bacula.%s.traceback", working_directory, pid_buf); 
254          fd = fopen(buf, "r"); 
255          if (fd != NULL) {
256             printf("\n\n ==== Traceback output ====\n\n");
257             while (fgets(buf, (int)sizeof(buf), fd) != NULL) {
258                printf("%s", buf);
259             }
260             fclose(fd);
261             printf(" ==== End traceback output ====\n\n");
262          }
263       }
264 #else
265       if (prt_kaboom) {
266          snprintf(buf, sizeof(buf), "/bin/cat %s/bacula.%s.traceback", working_directory, pid_buf);
267          fprintf(stderr, "\n\n ==== Traceback output ====\n\n");
268          system(buf);
269          fprintf(stderr, " ==== End traceback output ====\n\n");
270       }
271 #endif
272
273 #ifndef DEVELOPER /* When DEVELOPER set, this is done above */
274       /* print information about the current state into working/<file>.bactrace */
275       dbg_print_bacula();
276 #endif
277
278    }
279 #endif
280    exit_handler(sig);
281    Dmsg0(500, "Done exit_handler\n");
282 }
283
284 /*
285  * Init stack dump by saving main process id --
286  *   needed by debugger to attach to this program.
287  */
288 void init_stack_dump(void)
289 {
290    main_pid = getpid();               /* save main thread's pid */
291 }
292
293 /*
294  * Initialize signals
295  */
296 void init_signals(void terminate(int sig))
297 {
298    struct sigaction sighandle;
299    struct sigaction sigignore;
300    struct sigaction sigdefault;
301 #ifdef _sys_nsig
302    int i;
303
304    exit_handler = terminate;
305    if (BA_NSIG < _sys_nsig)
306       Emsg2(M_ABORT, 0, _("BA_NSIG too small (%d) should be (%d)\n"), BA_NSIG, _sys_nsig);
307
308    for (i=0; i<_sys_nsig; i++)
309       sig_names[i] = _sys_siglist[i];
310 #else
311    exit_handler = terminate;
312    sig_names[0]         = _("UNKNOWN SIGNAL");
313    sig_names[SIGHUP]    = _("Hangup");
314    sig_names[SIGINT]    = _("Interrupt");
315    sig_names[SIGQUIT]   = _("Quit");
316    sig_names[SIGILL]    = _("Illegal instruction");;
317    sig_names[SIGTRAP]   = _("Trace/Breakpoint trap");
318    sig_names[SIGABRT]   = _("Abort");
319 #ifdef SIGEMT
320    sig_names[SIGEMT]    = _("EMT instruction (Emulation Trap)");
321 #endif
322 #ifdef SIGIOT
323    sig_names[SIGIOT]    = _("IOT trap");
324 #endif
325    sig_names[SIGBUS]    = _("BUS error");
326    sig_names[SIGFPE]    = _("Floating-point exception");
327    sig_names[SIGKILL]   = _("Kill, unblockable");
328    sig_names[SIGUSR1]   = _("User-defined signal 1");
329    sig_names[SIGSEGV]   = _("Segmentation violation");
330    sig_names[SIGUSR2]   = _("User-defined signal 2");
331    sig_names[SIGPIPE]   = _("Broken pipe");
332    sig_names[SIGALRM]   = _("Alarm clock");
333    sig_names[SIGTERM]   = _("Termination");
334 #ifdef SIGSTKFLT
335    sig_names[SIGSTKFLT] = _("Stack fault");
336 #endif
337    sig_names[SIGCHLD]   = _("Child status has changed");
338    sig_names[SIGCONT]   = _("Continue");
339    sig_names[SIGSTOP]   = _("Stop, unblockable");
340    sig_names[SIGTSTP]   = _("Keyboard stop");
341    sig_names[SIGTTIN]   = _("Background read from tty");
342    sig_names[SIGTTOU]   = _("Background write to tty");
343    sig_names[SIGURG]    = _("Urgent condition on socket");
344    sig_names[SIGXCPU]   = _("CPU limit exceeded");
345    sig_names[SIGXFSZ]   = _("File size limit exceeded");
346    sig_names[SIGVTALRM] = _("Virtual alarm clock");
347    sig_names[SIGPROF]   = _("Profiling alarm clock");
348    sig_names[SIGWINCH]  = _("Window size change");
349    sig_names[SIGIO]     = _("I/O now possible");
350 #ifdef SIGPWR
351    sig_names[SIGPWR]    = _("Power failure restart");
352 #endif
353 #ifdef SIGWAITING
354    sig_names[SIGWAITING] = _("No runnable lwp");
355 #endif
356 #ifdef SIGLWP
357    sig_names[SIGLWP]     = _("SIGLWP special signal used by thread library");
358 #endif
359 #ifdef SIGFREEZE
360    sig_names[SIGFREEZE] = _("Checkpoint Freeze");
361 #endif
362 #ifdef SIGTHAW
363    sig_names[SIGTHAW]   = _("Checkpoint Thaw");
364 #endif
365 #ifdef SIGCANCEL
366    sig_names[SIGCANCEL] = _("Thread Cancellation");
367 #endif
368 #ifdef SIGLOST
369    sig_names[SIGLOST]   = _("Resource Lost (e.g. record-lock lost)");
370 #endif
371 #endif
372
373
374 /* Now setup signal handlers */
375    sighandle.sa_flags = 0;
376    sighandle.sa_handler = signal_handler;
377    sigfillset(&sighandle.sa_mask);
378    sigignore.sa_flags = 0;
379    sigignore.sa_handler = SIG_IGN;
380    sigfillset(&sigignore.sa_mask);
381    sigdefault.sa_flags = 0;
382    sigdefault.sa_handler = SIG_DFL;
383    sigfillset(&sigdefault.sa_mask);
384
385
386    sigaction(SIGPIPE,   &sigignore, NULL);
387    sigaction(SIGCHLD,   &sighandle, NULL);
388    sigaction(SIGCONT,   &sigignore, NULL);
389    sigaction(SIGPROF,   &sigignore, NULL);
390    sigaction(SIGWINCH,  &sigignore, NULL);
391    sigaction(SIGIO,     &sighandle, NULL);
392
393    sigaction(SIGINT,    &sigdefault, NULL);
394    sigaction(SIGXCPU,   &sigdefault, NULL);
395    sigaction(SIGXFSZ,   &sigdefault, NULL);
396
397    sigaction(SIGHUP,    &sigignore, NULL);
398    sigaction(SIGQUIT,   &sighandle, NULL);
399    sigaction(SIGILL,    &sighandle, NULL);
400    sigaction(SIGTRAP,   &sighandle, NULL);
401    sigaction(SIGABRT,   &sighandle, NULL);
402 #ifdef SIGEMT
403    sigaction(SIGEMT,    &sighandle, NULL);
404 #endif
405 #ifdef SIGIOT
406    sigaction(SIGIOT,    &sighandle, NULL);                     
407 #endif
408    sigaction(SIGBUS,    &sighandle, NULL);
409    sigaction(SIGFPE,    &sighandle, NULL);
410 /* sigaction(SIGKILL,   &sighandle, NULL);  cannot be trapped */
411    sigaction(SIGUSR1,   &sighandle, NULL);
412    sigaction(SIGSEGV,   &sighandle, NULL);
413    sigaction(SIGUSR2,   &sighandle, NULL);
414    sigaction(SIGALRM,   &sighandle, NULL);
415    sigaction(SIGTERM,   &sighandle, NULL);
416 #ifdef SIGSTKFLT
417    sigaction(SIGSTKFLT, &sighandle, NULL);
418 #endif
419 /* sigaction(SIGSTOP,   &sighandle, NULL); cannot be trapped */
420    sigaction(SIGTSTP,   &sighandle, NULL);
421    sigaction(SIGTTIN,   &sighandle, NULL);
422    sigaction(SIGTTOU,   &sighandle, NULL);
423    sigaction(SIGURG,    &sighandle, NULL);
424    sigaction(SIGVTALRM, &sighandle, NULL);
425 #ifdef SIGPWR
426    sigaction(SIGPWR,    &sighandle, NULL);
427 #endif
428 #ifdef SIGWAITING
429    sigaction(SIGWAITING,&sighandle, NULL);
430 #endif
431 #ifdef SIGLWP
432    sigaction(SIGLWP,    &sighandle, NULL);
433 #endif
434 #ifdef SIGFREEZE
435    sigaction(SIGFREEZE, &sighandle, NULL);
436 #endif
437 #ifdef SIGTHAW
438    sigaction(SIGTHAW,   &sighandle, NULL);
439 #endif
440 #ifdef SIGCANCEL
441    sigaction(SIGCANCEL, &sighandle, NULL);
442 #endif
443 #ifdef SIGLOST
444    sigaction(SIGLOST,   &sighandle, NULL);
445 #endif
446 }
447 #endif