No more manifest files
[yaz-moved-to-github.git] / src / backtrace.c
index 76e890f..1ad0d7e 100644 (file)
 
 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);
-
-    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);
@@ -123,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)
     {
@@ -149,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