X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Fsignal.c;h=68ba78586b8915d5461b29e7cc1f2932898c9b19;hb=897707854a8240d026e933215009f931bb9c5762;hp=f9be096f4ded48f00b25b897ab66a83b9c6e29c3;hpb=043dfdbe5bb4cec577c9000959f051b83c270b08;p=bacula%2Fbacula diff --git a/bacula/src/lib/signal.c b/bacula/src/lib/signal.c index f9be096f4d..68ba78586b 100644 --- a/bacula/src/lib/signal.c +++ b/bacula/src/lib/signal.c @@ -1,10 +1,35 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2000-2009 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 three of the GNU Affero 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 Affero 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 * * 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 @@ -14,26 +39,6 @@ * */ -/* - 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" @@ -46,6 +51,7 @@ extern char my_name[]; extern char *exepath; extern char *exename; +extern bool prt_kaboom; static const char *sig_names[BA_NSIG+1]; @@ -64,6 +70,63 @@ const char *get_signal_name(int sig) } } +/* defined in jcr.c */ +extern void dbg_print_jcr(FILE *fp); +/* defined in plugins.c */ +extern void dbg_print_plugin(FILE *fp); +/* defined in lockmgr.c */ +extern void dbg_print_lock(FILE *fp); + +/* + * !!! WARNING !!! + * + * This function should be used ONLY after a violent signal. We walk through the + * JCR chain without locking, 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, (int)getpid()); + FILE *fp = fopen(buf, "a+") ; + 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_lock(fp); + dbg_print_jcr(fp); + dbg_print_plugin(fp); + + if (fp != stderr) { +#define direct_print +#ifdef direct_print + if (prt_kaboom) { + rewind(fp); + printf("\n\n ==== bactrace output ====\n\n"); + while (fgets(buf, (int)sizeof(buf), fp) != NULL) { + printf("%s", buf); + } + printf(" ==== End baktrace output ====\n\n"); + } +#else + if (prt_kaboom) { + char buf1[512]; + printf("\n\n ==== bactrace output ====\n\n"); + snprintf(buf1, sizeof(buf1), "/bin/cat %s", buf); + system(buf1); + printf(" ==== End baktrace output ====\n\n"); + } +#endif + fclose(fp); + } +} + /* * Handle signals here */ @@ -81,36 +144,39 @@ extern "C" void signal_handler(int sig) return; } already_dead++; + /* Don't use Emsg here as it may lock and thus block us */ if (sig == SIGTERM) { -// Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name); + syslog(LOG_DAEMON|LOG_ERR, "Shutting down Bacula service: %s ...\n", my_name); } else { - Emsg2(M_FATAL, -1, _("Bacula interrupted by signal %d: %s\n"), sig, sig_names[sig]); + fprintf(stderr, _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig)); + syslog(LOG_DAEMON|LOG_ERR, + _("Bacula interrupted by signal %d: %s\n"), sig, get_signal_name(sig)); } #ifdef TRACEBACK if (sig != SIGTERM) { struct sigaction sigdefault; - static char *argv[4]; + static char *argv[5]; static char pid_buf[20]; static char btpath[400]; - char buf[100]; + char buf[400]; 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); @@ -123,7 +189,7 @@ extern "C" void signal_handler(int sig) } 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 */ @@ -139,15 +205,19 @@ extern "C" void signal_handler(int sig) 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); + argv[3] = (char *)working_directory; + argv[4] = (char *)NULL; + fprintf(stderr, _("Calling: %s %s %s %s\n"), btpath, exepath, pid_buf, + working_directory); 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; @@ -157,19 +227,41 @@ extern "C" void signal_handler(int sig) 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"); - exit_handler(sig); /* clean up if possible */ - Dmsg0(500, "Done exit_handler\n"); } else { Dmsg0(500, "Doing sleep\n"); bmicrosleep(30, 0); } fprintf(stderr, _("It looks like the traceback worked ...\n")); + /* If we want it printed, do so */ +#ifdef direct_print + if (prt_kaboom) { + FILE *fd; + snprintf(buf, sizeof(buf), "%s/bacula.%s.traceback", working_directory, pid_buf); + fd = fopen(buf, "r"); + if (fd != NULL) { + printf("\n\n ==== Traceback output ====\n\n"); + while (fgets(buf, (int)sizeof(buf), fd) != NULL) { + printf("%s", buf); + } + fclose(fd); + printf(" ==== End traceback output ====\n\n"); + } + } +#else + if (prt_kaboom) { + snprintf(buf, sizeof(buf), "/bin/cat %s/bacula.%s.traceback", working_directory, pid_buf); + fprintf(stderr, "\n\n ==== Traceback output ====\n\n"); + system(buf); + fprintf(stderr, " ==== End traceback output ====\n\n"); + } +#endif + /* print information about the current state into working/.bactrace */ + dbg_print_bacula(); } #endif - exit_handler(sig); + Dmsg0(500, "Done exit_handler\n"); } /* @@ -245,7 +337,7 @@ void init_signals(void terminate(int sig)) 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"); @@ -289,16 +381,16 @@ void init_signals(void terminate(int 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); @@ -307,7 +399,7 @@ void init_signals(void terminate(int sig)) #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);