-/*
- * 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"
- * routine, we leave it to the individual daemons to
- * tweek their signals after calling this routine.
- *
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
This program is Free Software; you can redistribute it and/or
modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation plus additions
- that are listed in the file LICENSE.
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ Bacula® is a registered trademark of Kern Sibbald.
The licensor of Bacula is the Free Software Foundation Europe
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ * 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"
+ * routine, we leave it to the individual daemons to
+ * tweek their signals after calling this routine.
+ *
+ */
#ifndef HAVE_WIN32
#include "bacula.h"
extern char my_name[];
extern char *exepath;
extern char *exename;
+extern void print_jcr_dbg();
static const char *sig_names[BA_NSIG+1];
}
}
+/* defined in jcr.c */
+extern void _dbg_print_jcr(FILE *fp);
+/* defined in plugin.c */
+extern void _dbg_print_plugin(FILE *fp);
+
+/*
+ * !!! WARNING !!!
+ *
+ * This function should be used ONLY after a violent signal. We walk through the
+ * JCR chain without doing any lock, bacula should not be running.
+ */
+static void dbg_print_bacula()
+{
+ char buf[512];
+
+ snprintf(buf, sizeof(buf), "%s/%s.%d.bactrace",
+ working_directory, my_name, getpid());
+ FILE *fp = fopen(buf, "ab") ;
+ if (!fp) {
+ fp = stderr;
+ }
+
+ fprintf(stderr, "Dumping: %s\n", buf);
+
+ /* Print also B_DB and RWLOCK structure
+ * Can add more info about JCR with dbg_jcr_add_hook()
+ */
+ _dbg_print_jcr(fp);
+
+ _dbg_print_plugin(fp);
+
+ if (fp != stderr) {
+ fclose(fp);
+ }
+}
+
/*
* Handle signals here
*/
if (sig == SIGTERM) {
// Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
} else {
- Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, sig_names[sig]);
+/* ***FIXME*** Display a message without taking any lock in the system
+ * Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
+ */
+ fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig));
}
#ifdef TRACEBACK
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! %s, %s got signal %d - %s. Attempting traceback.\n"),
+ exename, my_name, sig, get_signal_name(sig));
fprintf(stderr, _("Kaboom! exepath=%s\n"), exepath);
if (exelen + 12 > (int)sizeof(btpath)) {
bstrncpy(btpath, "btraceback", sizeof(btpath));
} else {
bstrncpy(btpath, exepath, sizeof(btpath));
- if (btpath[exelen-1] == '/') {
+ if (IsPathSeparator(btpath[exelen-1])) {
btpath[exelen-1] = 0;
}
bstrncat(btpath, "/btraceback", sizeof(btpath));
}
- if (exepath[exelen-1] != '/') {
+ if (!IsPathSeparator(exepath[exelen - 1])) {
strcat(exepath, "/");
}
strcat(exepath, exename);
}
if (chdir(working_directory) != 0) { /* dump in working directory */
berrno be;
- Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.strerror());
+ Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, be.bstrerror());
strcpy((char *)working_directory, "/tmp/");
}
unlink("./core"); /* get rid of any old core file */
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));
+ berrno be;
+ printf(_("execv: %s failed: ERR=%s\n"), btpath, be.bstrerror());
}
exit(-1);
default: /* parent */
break;
}
+
/* Parent continue here, waiting for child */
sigdefault.sa_flags = 0;
sigdefault.sa_handler = SIG_DFL;
if (pid > 0) {
Dmsg0(500, "Doing waitpid\n");
waitpid(pid, NULL, 0); /* wait for child to produce dump */
- fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
Dmsg0(500, "Done waitpid\n");
+ fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
+ /* print information about the current state into working/<file>.bactrace */
+ dbg_print_bacula();
exit_handler(sig); /* clean up if possible */
Dmsg0(500, "Done exit_handler\n");
} else {
bmicrosleep(30, 0);
}
fprintf(stderr, _("It looks like the traceback worked ...\n"));
+ dbg_print_bacula();
}
#endif
-
exit_handler(sig);
}
sigaction(SIGQUIT, &sighandle, NULL);
sigaction(SIGILL, &sighandle, NULL);
sigaction(SIGTRAP, &sighandle, NULL);
-/* sigaction(SIGABRT, &sighandle, NULL); */
+ sigaction(SIGABRT, &sighandle, NULL);
#ifdef SIGEMT
sigaction(SIGEMT, &sighandle, NULL);
#endif
#ifdef SIGIOT
-/* sigaction(SIGIOT, &sighandle, NULL); used by debugger */
+ sigaction(SIGIOT, &sighandle, NULL);
#endif
sigaction(SIGBUS, &sighandle, NULL);
sigaction(SIGFPE, &sighandle, NULL);
- sigaction(SIGKILL, &sighandle, NULL);
+/* sigaction(SIGKILL, &sighandle, NULL); cannot be trapped */
sigaction(SIGUSR1, &sighandle, NULL);
sigaction(SIGSEGV, &sighandle, NULL);
sigaction(SIGUSR2, &sighandle, NULL);
#ifdef SIGSTKFLT
sigaction(SIGSTKFLT, &sighandle, NULL);
#endif
- sigaction(SIGSTOP, &sighandle, NULL);
+/* sigaction(SIGSTOP, &sighandle, NULL); cannot be trapped */
sigaction(SIGTSTP, &sighandle, NULL);
sigaction(SIGTTIN, &sighandle, NULL);
sigaction(SIGTTOU, &sighandle, NULL);