]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/signal.c
Fix cancel problem and implement run gnome dialog
[bacula/bacula] / bacula / src / lib / signal.c
1 /*
2  *  Signal handlers for Bacula daemons
3  *
4  *   Kern Sibbald, April 2000
5  *
6  *   Version $Id$
7  * 
8  * Note, we probably should do a core dump for the serious
9  * signals such as SIGBUS, SIGPFE, ... 
10  * Also, for SIGHUP and SIGUSR1, we should re-read the 
11  * configuration file.  However, since this is a "general"  
12  * routine, we leave it to the individual daemons to
13  * tweek their signals after calling this routine.
14  *
15  */
16
17 /*
18    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
19
20    This program is free software; you can redistribute it and/or
21    modify it under the terms of the GNU General Public License as
22    published by the Free Software Foundation; either version 2 of
23    the License, or (at your option) any later version.
24
25    This program is distributed in the hope that it will be useful,
26    but WITHOUT ANY WARRANTY; without even the implied warranty of
27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28    General Public License for more details.
29
30    You should have received a copy of the GNU General Public
31    License along with this program; if not, write to the Free
32    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
33    MA 02111-1307, USA.
34
35  */
36
37
38 #include "bacula.h"
39
40 #ifndef _NSIG
41 #define BA_NSIG 100
42 #else
43 #define BA_NSIG _NSIG
44 #endif
45
46 extern char my_name[];
47 extern char *exepath;
48 extern char *exename;
49
50 static const char *sig_names[BA_NSIG+1];
51
52 typedef void (SIG_HANDLER)(int sig);
53 static SIG_HANDLER *exit_handler;
54
55 /* main process id */
56 static pid_t main_pid = 0;
57
58 /* 
59  * Handle signals here
60  */
61 static void signal_handler(int sig)
62 {
63    static int already_dead = FALSE;
64
65    if (already_dead) {
66       _exit(1);
67    }
68    /* Ignore certain signals */
69    if (sig == SIGCHLD || sig == SIGUSR2) {
70       return;
71    }
72    already_dead = sig;
73    if (sig == SIGTERM) {
74       Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
75    } else {
76       Emsg2(M_FATAL, -1, "Bacula interrupted by signal %d: %s\n", sig, sig_names[sig]);
77    }
78
79 #ifdef TRACEBACK
80    if (sig != SIGTERM) {
81       struct sigaction sigdefault;
82       static char *argv[4];
83       static char pid_buf[20];
84       static char btpath[400];
85       pid_t pid;
86
87       fprintf(stderr, "Kaboom! %s, %s got signal %d. Attempting traceback.\n", 
88               exename, my_name, sig);
89
90       if (strlen(exepath) + 12 > (int)sizeof(btpath)) {
91          strcpy(btpath, "btraceback");
92       } else {
93          strcpy(btpath, exepath);
94          strcat(btpath, "/btraceback");
95       }
96       strcat(exepath, "/");
97       strcat(exepath, exename);
98       if (chdir(working_directory) !=0) {  /* dump in working directory */
99          Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory,  strerror(errno));
100       }
101       unlink("./core");               /* get rid of any old core file */
102       sprintf(pid_buf, "%d", (int)main_pid);
103       Dmsg1(300, "Working=%s\n", working_directory);
104       Dmsg1(300, "btpath=%s\n", btpath);
105       Dmsg1(300, "exepath=%s\n", exepath);
106       switch (pid = fork()) {
107       case -1:                        /* error */
108          fprintf(stderr, "Fork error: ERR=%s\n", strerror(errno));
109          break;
110       case 0:                         /* child */
111          argv[0] = btpath;            /* path to btraceback */
112          argv[1] = exepath;           /* path to exe */
113          argv[2] = pid_buf;
114          argv[3] = (char *)NULL;
115          if (execv(btpath, argv) != 0) {
116             printf("execv: %s failed: ERR=%s\n", btpath, strerror(errno));
117          }
118          exit(-1);
119       default:                        /* parent */
120          break;
121       }
122       sigdefault.sa_flags = 0;
123       sigdefault.sa_handler = SIG_DFL;
124       sigfillset(&sigdefault.sa_mask);
125
126       sigaction(sig,  &sigdefault, NULL);
127       if (pid > 0) {
128          Dmsg0(500, "Doing waitpid\n");
129          waitpid(pid, NULL, 0);       /* wait for child to produce dump */
130          fprintf(stderr, "Traceback complete, attempting cleanup ...\n");
131          Dmsg0(500, "Done waitpid\n");
132          exit_handler(1);             /* clean up if possible */
133          Dmsg0(500, "Done exit_handler\n");
134       } else {
135          Dmsg0(500, "Doing sleep\n");
136          bmicrosleep(30, 0);
137       }
138       fprintf(stderr, "It looks like the traceback worked ...\n");
139    }
140 #endif
141
142    exit_handler(1);
143 }
144
145 /*
146  * Init stack dump by saving main process id --
147  *   needed by debugger to attach to this program.
148  */
149 void init_stack_dump(void)
150 {
151    main_pid = getpid();               /* save main thread's pid */
152 }
153
154 /*
155  * Initialize signals
156  */
157 void init_signals(void terminate(int sig))
158 {
159    struct sigaction sighandle;
160    struct sigaction sigignore;
161    struct sigaction sigdefault;
162 #ifdef _sys_nsig
163    int i;
164
165    exit_handler = terminate;
166    if (BA_NSIG < _sys_nsig)
167       Emsg2(M_ABORT, 0, "BA_NSIG too small (%d) should be (%d)\n", BA_NSIG, _sys_nsig);
168
169    for (i=0; i<_sys_nsig; i++)
170       sig_names[i] = _sys_siglist[i];
171 #else
172    exit_handler = terminate;
173    sig_names[0]         = "UNKNOWN SIGNAL";
174    sig_names[SIGHUP]    = "Hangup";
175    sig_names[SIGINT]    = "Interrupt";
176    sig_names[SIGQUIT]   = "Quit";
177    sig_names[SIGILL]    = "Illegal instruction";;
178    sig_names[SIGTRAP]   = "Trace/Breakpoint trap";
179    sig_names[SIGABRT]   = "Abort";
180 #ifdef SIGEMT
181    sig_names[SIGEMT]    = "EMT instruction (Emulation Trap)";
182 #endif
183 #ifdef SIGIOT
184    sig_names[SIGIOT]    = "IOT trap";
185 #endif
186    sig_names[SIGBUS]    = "BUS error";
187    sig_names[SIGFPE]    = "Floating-point exception";
188    sig_names[SIGKILL]   = "Kill, unblockable";
189    sig_names[SIGUSR1]   = "User-defined signal 1";
190    sig_names[SIGSEGV]   = "Segmentation violation";
191    sig_names[SIGUSR2]   = "User-defined signal 2";
192    sig_names[SIGPIPE]   = "Broken pipe";
193    sig_names[SIGALRM]   = "Alarm clock";
194    sig_names[SIGTERM]   = "Termination";
195 #ifdef SIGSTKFLT
196    sig_names[SIGSTKFLT] = "Stack fault";
197 #endif
198    sig_names[SIGCHLD]   = "Child status has changed";
199    sig_names[SIGCONT]   = "Continue";
200    sig_names[SIGSTOP]   = "Stop, unblockable";
201    sig_names[SIGTSTP]   = "Keyboard stop";
202    sig_names[SIGTTIN]   = "Background read from tty";
203    sig_names[SIGTTOU]   = "Background write to tty";
204    sig_names[SIGURG]    = "Urgent condition on socket";
205    sig_names[SIGXCPU]   = "CPU limit exceeded";
206    sig_names[SIGXFSZ]   = "File size limit exceeded";
207    sig_names[SIGVTALRM] = "Virtual alarm clock";
208    sig_names[SIGPROF]   = "Profiling alarm clock";
209    sig_names[SIGWINCH]  = "Window size change";
210    sig_names[SIGIO]     = "I/O now possible";
211 #ifdef SIGPWR
212    sig_names[SIGPWR]    = "Power failure restart";
213 #endif
214 #ifdef SIGWAITING
215    sig_names[SIGWAITING] = "No runnable lwp";
216 #endif
217 #ifdef SIGLWP
218    sig_name[SIGLWP]     = "SIGLWP special signal used by thread library";
219 #endif
220 #ifdef SIGFREEZE
221    sig_names[SIGFREEZE] = "Checkpoint Freeze";
222 #endif
223 #ifdef SIGTHAW
224    sig_names[SIGTHAW]   = "Checkpoint Thaw";
225 #endif
226 #ifdef SIGCANCEL
227    sig_names[SIGCANCEL] = "Thread Cancellation";
228 #endif
229 #ifdef SIGLOST
230    sig_names[SIGLOST]   = "Resource Lost (e.g. record-lock lost)";
231 #endif
232 #endif
233
234
235 /* Now setup signal handlers */
236    sighandle.sa_flags = 0;
237    sighandle.sa_handler = signal_handler;
238    sigfillset(&sighandle.sa_mask);
239    sigignore.sa_flags = 0;
240    sigignore.sa_handler = SIG_IGN;       
241    sigfillset(&sigignore.sa_mask);
242    sigdefault.sa_flags = 0;
243    sigdefault.sa_handler = SIG_DFL;
244    sigfillset(&sigdefault.sa_mask);
245
246
247    sigaction(SIGPIPE,   &sigignore, NULL);
248    sigaction(SIGCHLD,   &sighandle, NULL);
249    sigaction(SIGCONT,   &sigignore, NULL);
250    sigaction(SIGPROF,   &sigignore, NULL);
251    sigaction(SIGWINCH,  &sigignore, NULL);
252    sigaction(SIGIO,     &sighandle, NULL);     
253
254    sigaction(SIGINT,    &sigdefault, NULL);    
255    sigaction(SIGXCPU,   &sigdefault, NULL);
256    sigaction(SIGXFSZ,   &sigdefault, NULL);
257
258    sigaction(SIGHUP,    &sigignore, NULL);
259    sigaction(SIGQUIT,   &sighandle, NULL);   
260    sigaction(SIGILL,    &sighandle, NULL);    
261    sigaction(SIGTRAP,   &sighandle, NULL);   
262 /* sigaction(SIGABRT,   &sighandle, NULL);   */
263 #ifdef SIGEMT
264    sigaction(SIGEMT,    &sighandle, NULL);
265 #endif
266 #ifdef SIGIOT
267 /* sigaction(SIGIOT,    &sighandle, NULL);  used by debugger */
268 #endif
269    sigaction(SIGBUS,    &sighandle, NULL);    
270    sigaction(SIGFPE,    &sighandle, NULL);    
271    sigaction(SIGKILL,   &sighandle, NULL);   
272    sigaction(SIGUSR1,   &sighandle, NULL);   
273    sigaction(SIGSEGV,   &sighandle, NULL);   
274    sigaction(SIGUSR2,   &sighandle, NULL);
275    sigaction(SIGALRM,   &sighandle, NULL);   
276    sigaction(SIGTERM,   &sighandle, NULL);   
277 #ifdef SIGSTKFLT
278    sigaction(SIGSTKFLT, &sighandle, NULL); 
279 #endif
280    sigaction(SIGSTOP,   &sighandle, NULL);   
281    sigaction(SIGTSTP,   &sighandle, NULL);   
282    sigaction(SIGTTIN,   &sighandle, NULL);   
283    sigaction(SIGTTOU,   &sighandle, NULL);   
284    sigaction(SIGURG,    &sighandle, NULL);    
285    sigaction(SIGVTALRM, &sighandle, NULL); 
286 #ifdef SIGPWR
287    sigaction(SIGPWR,    &sighandle, NULL);    
288 #endif
289 #ifdef SIGWAITING
290    sigaction(SIGWAITING,&sighandle, NULL);
291 #endif
292 #ifdef SIGLWP
293    sigaction(SIGLWP,    &sighandle, NULL);
294 #endif
295 #ifdef SIGFREEZE
296    sigaction(SIGFREEZE, &sighandle, NULL);
297 #endif
298 #ifdef SIGTHAW
299    sigaction(SIGTHAW,   &sighandle, NULL);
300 #endif
301 #ifdef SIGCANCEL
302    sigaction(SIGCANCEL, &sighandle, NULL);
303 #endif
304 #ifdef SIGLOST
305    sigaction(SIGLOST,   &sighandle, NULL);
306 #endif
307 }