X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fbacktrace.c;h=1ad0d7ee781d7e7bfc845ad8b7efec172d36476d;hp=567e55f5d9129869518fcd47f75507b42166ca26;hb=HEAD;hpb=51e1ca7946289042c3c09e92afc1c1c465f5d870 diff --git a/src/backtrace.c b/src/backtrace.c index 567e55f..1ad0d7e 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -39,26 +39,24 @@ #define BACKTRACE_SZ 100 static char static_progname[256]; +#if HAVE_EXECINFO_H +static int yaz_panic_fd = -1; -static void yaz_invoke_backtrace(char *buf, int buf_sz) +static void yaz_invoke_gdb(void) { - FILE *file = yaz_log_file(); - int fd = fileno(file); -#if HAVE_EXECINFO_H + int fd = yaz_panic_fd; pid_t pid; int fds[2]; - void *backtrace_info[BACKTRACE_SZ]; - int sz = BACKTRACE_SZ; - - write(fd, buf, strlen(buf)); - sz = backtrace(backtrace_info, sz); - backtrace_symbols_fd(backtrace_info, sz, fd); - - pipe(fds); + if (pipe(fds) == -1) + { + const char *cp = "backtrace: pipe failed\n"; + write(fd, cp, strlen(cp)); + return; + } pid = fork(); if (pid == (pid_t) (-1)) { /* error */ - const char *cp = "backtrace: fork failure"; + const char *cp = "backtrace: fork failure\n"; write(fd, cp, strlen(cp)); } else if (pid == 0) @@ -66,7 +64,7 @@ static void yaz_invoke_backtrace(char *buf, int buf_sz) char *arg[20]; int arg_no = 0; char pidstr[40]; - const char *cp = "backtrace: could not exec gdb"; + const char *cp = "backtrace: could not exec gdb\n"; close(fds[1]); close(0); @@ -121,17 +119,38 @@ static void yaz_invoke_backtrace(char *buf, int buf_sz) } close(fds[1]); } -#else - strcat(buf, "no backtrace support (execinfo.h not found)\n"); - write(fd, buf, strlen(buf)); -#endif +} + +static void yaz_panic_alarm(int sig) +{ + const char *cp = "backtrace: backtrace hangs\n"; + + write(yaz_panic_fd, cp, strlen(cp)); + yaz_invoke_gdb(); + abort(); +} + +static void yaz_invoke_backtrace(void) +{ + int fd = yaz_panic_fd; + void *backtrace_info[BACKTRACE_SZ]; + int sz = BACKTRACE_SZ; + + signal(SIGALRM, yaz_panic_alarm); + alarm(1); + sz = backtrace(backtrace_info, sz); + backtrace_symbols_fd(backtrace_info, sz, fd); } static void yaz_panic_sig_handler(int sig) { char buf[512]; + FILE *file; signal(SIGABRT, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGBUS, SIG_DFL); strcpy(buf, "\nYAZ panic received "); switch (sig) { @@ -153,9 +172,17 @@ static void yaz_panic_sig_handler(int sig) } yaz_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf) - 1, " PID=" NMEM_INT_PRINTF "\n", (nmem_int_t) getpid()); - yaz_invoke_backtrace(buf, sizeof buf); + + file = yaz_log_file(); + /* static variable to be used in the following + handlers */ + yaz_panic_fd = fileno(file); + + write(yaz_panic_fd, buf, strlen(buf)); + yaz_invoke_backtrace(); + yaz_invoke_gdb(); abort(); } +#endif void yaz_enable_panic_backtrace(const char *progname) {