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