+/*
+ Bacula® - The Network Backup Solution
+
+ 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 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
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ 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
*
*
*/
-/*
- 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
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
-
- */
-
#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/bacula.%d.bactrace",
+ working_directory, getpid());
+ FILE *fp = fopen(buf, "ab") ;
+ if (!fp) {
+ fp = stderr;
+ }
+
+ /* 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]);
+ Emsg2(M_FATAL, -1, _("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 {
sig_names[SIGWAITING] = _("No runnable lwp");
#endif
#ifdef SIGLWP
- sig_name[SIGLWP] = _("SIGLWP special signal used by thread library");
+ sig_names[SIGLWP] = _("SIGLWP special signal used by thread library");
#endif
#ifdef SIGFREEZE
sig_names[SIGFREEZE] = _("Checkpoint Freeze");
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);