2 * Signal handlers for Bacula daemons
4 * Kern Sibbald, April 2000
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.
16 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
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.
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.
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,
44 extern char my_name[];
48 static const char *sig_names[BA_NSIG+1];
50 typedef void (SIG_HANDLER)(int sig);
51 static SIG_HANDLER *exit_handler;
54 static pid_t main_pid = 0;
59 static void signal_handler(int sig)
61 static int already_dead = FALSE;
62 struct sigaction sigdefault;
69 Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
71 Emsg2(M_FATAL, -1, "Interrupted by signal %d: %s\n", sig, sig_names[sig]);
77 static char pid_buf[20];
78 static char btpath[400];
81 Dmsg1(000, "Kaboom! Got signal %d. Attempting traceback\n", sig);
82 if (strlen(exepath) + 12 > (int)sizeof(btpath)) {
83 strcpy(btpath, "btraceback");
85 strcpy(btpath, exepath);
86 strcat(btpath, "/btraceback");
89 strcat(exepath, exename);
90 if (chdir(working_directory) !=0) { /* dump in working directory */
91 Dmsg1(000, "chdir failed. ERR=%s\n", strerror(errno));
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()) {
102 argv[0] = btpath; /* path to btraceback */
103 argv[1] = exepath; /* path to exe */
105 argv[3] = (char *)NULL;
106 if (execv(btpath, argv) != 0) {
107 printf("execv: %s failed: ERR=%s\n", btpath, strerror(errno));
110 default: /* parent */
113 sigdefault.sa_flags = 0;
114 sigdefault.sa_handler = SIG_DFL;
115 sigfillset(&sigdefault.sa_mask);
117 sigaction(sig, &sigdefault, NULL);
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");
125 Dmsg0(500, "Doing sleep\n");
135 * Init stack dump by saving main process id --
136 * needed by debugger to attach to this program.
138 void init_stack_dump(void)
140 main_pid = getpid(); /* save main thread's pid */
146 void init_signals(void terminate(int sig))
148 struct sigaction sighandle;
149 struct sigaction sigignore;
150 struct sigaction sigdefault;
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);
158 for (i=0; i<_sys_nsig; i++)
159 sig_names[i] = _sys_siglist[i];
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";
170 sig_names[SIGEMT] = "EMT instruction (Emulation Trap)";
173 sig_names[SIGIOT] = "IOT trap";
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";
185 sig_names[SIGSTKFLT] = "Stack fault";
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";
201 sig_names[SIGPWR] = "Power failure restart";
204 sig_names[SIGWAITING] = "No runnable lwp";
207 sig_name[SIGLWP] = "SIGLWP special signal used by thread library";
210 sig_names[SIGFREEZE] = "Checkpoint Freeze";
213 sig_names[SIGTHAW] = "Checkpoint Thaw";
216 sig_names[SIGCANCEL] = "Thread Cancellation";
219 sig_names[SIGLOST] = "Resource Lost (e.g. record-lock lost)";
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);
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);
243 sigaction(SIGINT, &sigdefault, NULL);
244 sigaction(SIGXCPU, &sigdefault, NULL);
245 sigaction(SIGXFSZ, &sigdefault, NULL);
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); */
253 sigaction(SIGEMT, &sighandle, NULL);
256 /* sigaction(SIGIOT, &sighandle, NULL); used by debugger */
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);
267 sigaction(SIGSTKFLT, &sighandle, NULL);
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);
276 sigaction(SIGPWR, &sighandle, NULL);
279 sigaction(SIGWAITING,&sighandle, NULL);
282 sigaction(SIGLWP, &sighandle, NULL);
285 sigaction(SIGFREEZE, &sighandle, NULL);
288 sigaction(SIGTHAW, &sighandle, NULL);
291 sigaction(SIGCANCEL, &sighandle, NULL);
294 sigaction(SIGLOST, &sighandle, NULL);