From: Adam Dickmeiss Date: Tue, 15 Sep 2015 08:05:10 +0000 (+0200) Subject: Fix possible deadlock in backtrace (2nd attempt) YAZ-856 X-Git-Tag: v5.14.9~2 X-Git-Url: http://sru.miketaylor.org.uk/cgi-bin?a=commitdiff_plain;h=7c6b3363478950a3a5c7f448e5bfa6f4ea19fbab;p=yaz-moved-to-github.git Fix possible deadlock in backtrace (2nd attempt) YAZ-856 An alarm is set up so that backtrace is terminated if it hangs. Even if backtrace the handler also attempts to spawn gdb. --- diff --git a/src/backtrace.c b/src/backtrace.c index 2ed7385..1ad0d7e 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -40,20 +40,13 @@ 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); + 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); - if (pipe(fds) == -1) { const char *cp = "backtrace: pipe failed\n"; @@ -128,11 +121,36 @@ static void yaz_invoke_backtrace(char *buf, int buf_sz) } } +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) { @@ -154,7 +172,14 @@ 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 @@ -164,9 +189,6 @@ void yaz_enable_panic_backtrace(const char *progname) strncpy(static_progname, progname, sizeof(static_progname) - 1); static_progname[sizeof(static_progname) - 1] = '\0'; #if HAVE_EXECINFO_H - void *bt[1]; - backtrace(bt, 1); - signal(SIGABRT, yaz_panic_sig_handler); signal(SIGSEGV, yaz_panic_sig_handler); signal(SIGFPE, yaz_panic_sig_handler);