X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Fsignal.c;h=68ba78586b8915d5461b29e7cc1f2932898c9b19;hb=897707854a8240d026e933215009f931bb9c5762;hp=4e80e5241a4af70f1c98ad34310b090fe1cdc516;hpb=137bb193b84b61ecd75ea4d5093ced7c190809be;p=bacula%2Fbacula diff --git a/bacula/src/lib/signal.c b/bacula/src/lib/signal.c index 4e80e5241a..68ba78586b 100644 --- a/bacula/src/lib/signal.c +++ b/bacula/src/lib/signal.c @@ -1,45 +1,43 @@ -/* - * 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-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 two of the GNU General Public - License as published by the Free Software Foundation plus additions - that are listed in the file LICENSE. + 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 General Public License + 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 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 + * + * 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" @@ -53,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]; @@ -71,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 */ @@ -88,24 +144,27 @@ 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)) { @@ -130,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 */ @@ -146,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; @@ -164,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"); } /* @@ -296,12 +381,12 @@ 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);