* Signal handlers for Bacula daemons
*
* Kern Sibbald, April 2000
- *
+ *
+ * Version $Id$
+ *
* Note, we probably should do a core dump for the serious
- * signals such as SIGBUS, SIGPFE, ...
- * Also, for SIGHUP and SIGUSR1, we should re-read the
- * configuration file. However, since this is a "general"
+ * signals such as SIGBUS, SIGPFE, ...
+ * Also, for SIGHUP and SIGUSR1, we should re-read the
+ * configuration file. However, since this is a "general"
* routine, we leave it to the individual daemons to
* tweek their signals after calling this routine.
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
*/
-
+#ifndef HAVE_WIN32
#include "bacula.h"
#ifndef _NSIG
/* main process id */
static pid_t main_pid = 0;
-/*
+const char *get_signal_name(int sig)
+{
+ if (sig < 0 || sig > BA_NSIG || !sig_names[sig]) {
+ return "Invalid signal number";
+ } else {
+ return sig_names[sig];
+ }
+}
+
+/*
* Handle signals here
*/
-static void signal_handler(int sig)
+extern "C" void signal_handler(int sig)
{
- static int already_dead = FALSE;
- struct sigaction sigdefault;
+ static int already_dead = 0;
+ /* If we come back more than once, get out fast! */
if (already_dead) {
- abort();
+ exit(1);
}
- already_dead = TRUE;
+ Dmsg2(900, "sig=%d %s\n", sig, sig_names[sig]);
+ /* Ignore certain signals -- SIGUSR2 used to interrupt threads */
+ if (sig == SIGCHLD || sig == SIGUSR2) {
+ return;
+ }
+ already_dead++;
if (sig == SIGTERM) {
- Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
+// Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
} else {
- Emsg2(M_FATAL, -1, "Interrupted by signal %d: %s\n", sig, sig_names[sig]);
+ Emsg2(M_FATAL, -1, "Bacula interrupted by signal %d: %s\n", sig, sig_names[sig]);
}
#ifdef TRACEBACK
if (sig != SIGTERM) {
+ struct sigaction sigdefault;
static char *argv[4];
static char pid_buf[20];
static char btpath[400];
+ char buf[100];
pid_t pid;
+ int exelen = strlen(exepath);
+
+ fprintf(stderr, "Kaboom! %s, %s got signal %d. Attempting traceback.\n",
+ exename, my_name, sig);
+ fprintf(stderr, "Kaboom! exepath=%s\n", exepath);
- Dmsg1(000, "Kaboom! Got signal %d. Attempting traceback\n", sig);
- if (strlen(exepath) + 12 > (int)sizeof(btpath)) {
- strcpy(btpath, "btraceback");
+ if (exelen + 12 > (int)sizeof(btpath)) {
+ bstrncpy(btpath, "btraceback", sizeof(btpath));
} else {
- strcpy(btpath, exepath);
- strcat(btpath, "/btraceback");
+ bstrncpy(btpath, exepath, sizeof(btpath));
+ if (btpath[exelen-1] == '/') {
+ btpath[exelen-1] = 0;
+ }
+ bstrncat(btpath, "/btraceback", sizeof(btpath));
+ }
+ if (exepath[exelen-1] != '/') {
+ strcat(exepath, "/");
}
- strcat(exepath, "/");
strcat(exepath, exename);
- if (chdir(working_directory) !=0) { /* dump in working directory */
- Dmsg1(000, "chdir failed. ERR=%s\n", strerror(errno));
+ if (!working_directory) {
+ working_directory = buf;
+ *buf = 0;
+ }
+ if (*working_directory == 0) {
+ strcpy((char *)working_directory, "/tmp/");
+ }
+ if (chdir(working_directory) != 0) { /* dump in working directory */
+ berrno be;
+ Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.strerror());
+ strcpy((char *)working_directory, "/tmp/");
}
unlink("./core"); /* get rid of any old core file */
- sprintf(pid_buf, "%d", main_pid);
+ sprintf(pid_buf, "%d", (int)main_pid);
Dmsg1(300, "Working=%s\n", working_directory);
Dmsg1(300, "btpath=%s\n", btpath);
Dmsg1(300, "exepath=%s\n", exepath);
switch (pid = fork()) {
- case -1: /* error */
- break;
- case 0: /* child */
- argv[0] = btpath; /* path to btraceback */
- argv[1] = exepath; /* path to exe */
- argv[2] = pid_buf;
- argv[3] = (char *)NULL;
- if (execv(btpath, argv) != 0) {
+ case -1: /* error */
+ fprintf(stderr, "Fork error: ERR=%s\n", strerror(errno));
+ break;
+ case 0: /* child */
+ argv[0] = btpath; /* path to btraceback */
+ argv[1] = exepath; /* path to exe */
+ argv[2] = pid_buf;
+ argv[3] = (char *)NULL;
+ fprintf(stderr, "Calling: %s %s %s\n", btpath, exepath, pid_buf);
+ if (execv(btpath, argv) != 0) {
printf("execv: %s failed: ERR=%s\n", btpath, strerror(errno));
- }
- exit(-1);
- default: /* parent */
- break;
+ }
+ exit(-1);
+ default: /* parent */
+ break;
}
+ /* Parent continue here, waiting for child */
sigdefault.sa_flags = 0;
sigdefault.sa_handler = SIG_DFL;
sigfillset(&sigdefault.sa_mask);
sigaction(sig, &sigdefault, NULL);
if (pid > 0) {
Dmsg0(500, "Doing waitpid\n");
- waitpid(pid, NULL, 0); /* wait for child to produce dump */
+ waitpid(pid, NULL, 0); /* wait for child to produce dump */
+ fprintf(stderr, "Traceback complete, attempting cleanup ...\n");
Dmsg0(500, "Done waitpid\n");
- exit_handler(1); /* clean up if possible */
+ exit_handler(sig); /* clean up if possible */
Dmsg0(500, "Done exit_handler\n");
} else {
Dmsg0(500, "Doing sleep\n");
- sleep(30);
+ bmicrosleep(30, 0);
}
- abort(); /* produce dump */
+ fprintf(stderr, "It looks like the traceback worked ...\n");
}
#endif
- exit_handler(1);
+ exit_handler(sig);
}
/*
sighandle.sa_handler = signal_handler;
sigfillset(&sighandle.sa_mask);
sigignore.sa_flags = 0;
- sigignore.sa_handler = SIG_IGN;
+ sigignore.sa_handler = SIG_IGN;
sigfillset(&sigignore.sa_mask);
sigdefault.sa_flags = 0;
sigdefault.sa_handler = SIG_DFL;
sigfillset(&sigdefault.sa_mask);
- sigaction(SIGPIPE, &sigignore, NULL);
- sigaction(SIGCHLD, &sigignore, NULL);
- sigaction(SIGCONT, &sigignore, NULL);
- sigaction(SIGPROF, &sigignore, NULL);
- sigaction(SIGWINCH, &sigignore, NULL);
- sigaction(SIGIO, &sighandle, NULL);
+ sigaction(SIGPIPE, &sigignore, NULL);
+ sigaction(SIGCHLD, &sighandle, NULL);
+ sigaction(SIGCONT, &sigignore, NULL);
+ sigaction(SIGPROF, &sigignore, NULL);
+ sigaction(SIGWINCH, &sigignore, NULL);
+ sigaction(SIGIO, &sighandle, NULL);
- sigaction(SIGINT, &sigdefault, NULL);
- sigaction(SIGXCPU, &sigdefault, NULL);
- sigaction(SIGXFSZ, &sigdefault, NULL);
+ sigaction(SIGINT, &sigdefault, NULL);
+ sigaction(SIGXCPU, &sigdefault, NULL);
+ sigaction(SIGXFSZ, &sigdefault, NULL);
- sigaction(SIGHUP, &sighandle, NULL);
- sigaction(SIGQUIT, &sighandle, NULL);
- sigaction(SIGILL, &sighandle, NULL);
- sigaction(SIGTRAP, &sighandle, NULL);
-/* sigaction(SIGABRT, &sighandle, NULL); */
+ sigaction(SIGHUP, &sigignore, NULL);
+ sigaction(SIGQUIT, &sighandle, NULL);
+ sigaction(SIGILL, &sighandle, NULL);
+ sigaction(SIGTRAP, &sighandle, NULL);
+/* sigaction(SIGABRT, &sighandle, NULL); */
#ifdef SIGEMT
- sigaction(SIGEMT, &sighandle, NULL);
+ sigaction(SIGEMT, &sighandle, NULL);
#endif
#ifdef SIGIOT
-/* sigaction(SIGIOT, &sighandle, NULL); used by debugger */
+/* sigaction(SIGIOT, &sighandle, NULL); used by debugger */
#endif
- sigaction(SIGBUS, &sighandle, NULL);
- sigaction(SIGFPE, &sighandle, NULL);
- sigaction(SIGKILL, &sighandle, NULL);
- sigaction(SIGUSR1, &sighandle, NULL);
- sigaction(SIGSEGV, &sighandle, NULL);
- sigaction(SIGUSR2, &sighandle, NULL);
- sigaction(SIGALRM, &sighandle, NULL);
- sigaction(SIGTERM, &sighandle, NULL);
+ sigaction(SIGBUS, &sighandle, NULL);
+ sigaction(SIGFPE, &sighandle, NULL);
+ sigaction(SIGKILL, &sighandle, NULL);
+ sigaction(SIGUSR1, &sighandle, NULL);
+ sigaction(SIGSEGV, &sighandle, NULL);
+ sigaction(SIGUSR2, &sighandle, NULL);
+ sigaction(SIGALRM, &sighandle, NULL);
+ sigaction(SIGTERM, &sighandle, NULL);
#ifdef SIGSTKFLT
- sigaction(SIGSTKFLT, &sighandle, NULL);
+ sigaction(SIGSTKFLT, &sighandle, NULL);
#endif
- sigaction(SIGSTOP, &sighandle, NULL);
- sigaction(SIGTSTP, &sighandle, NULL);
- sigaction(SIGTTIN, &sighandle, NULL);
- sigaction(SIGTTOU, &sighandle, NULL);
- sigaction(SIGURG, &sighandle, NULL);
- sigaction(SIGVTALRM, &sighandle, NULL);
+ sigaction(SIGSTOP, &sighandle, NULL);
+ sigaction(SIGTSTP, &sighandle, NULL);
+ sigaction(SIGTTIN, &sighandle, NULL);
+ sigaction(SIGTTOU, &sighandle, NULL);
+ sigaction(SIGURG, &sighandle, NULL);
+ sigaction(SIGVTALRM, &sighandle, NULL);
#ifdef SIGPWR
- sigaction(SIGPWR, &sighandle, NULL);
+ sigaction(SIGPWR, &sighandle, NULL);
#endif
#ifdef SIGWAITING
sigaction(SIGWAITING,&sighandle, NULL);
#endif
#ifdef SIGLWP
- sigaction(SIGLWP, &sighandle, NULL);
+ sigaction(SIGLWP, &sighandle, NULL);
#endif
#ifdef SIGFREEZE
sigaction(SIGFREEZE, &sighandle, NULL);
#endif
#ifdef SIGTHAW
- sigaction(SIGTHAW, &sighandle, NULL);
+ sigaction(SIGTHAW, &sighandle, NULL);
#endif
#ifdef SIGCANCEL
sigaction(SIGCANCEL, &sighandle, NULL);
#endif
#ifdef SIGLOST
- sigaction(SIGLOST, &sighandle, NULL);
+ sigaction(SIGLOST, &sighandle, NULL);
#endif
}
+#endif