Backtrace using addr2line to get filename + lineno info
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 18 Nov 2014 13:50:57 +0000 (14:50 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 18 Nov 2014 13:50:57 +0000 (14:50 +0100)
src/backtrace.c

index ec1d9be..840d2c5 100644 (file)
@@ -35,7 +35,7 @@
 #include <execinfo.h>
 #endif
 
-#define BACKTRACE_SZ 1000
+#define BACKTRACE_SZ 100
 
 void yaz_invoke_backtrace(char *buf, int buf_sz)
 {
@@ -64,8 +64,70 @@ void yaz_invoke_backtrace(char *buf, int buf_sz)
                          backtrace_info[i], backtrace_str[i]);
         }
     }
-#endif
     write(fd, buf, strlen(buf));
+
+    if (backtrace_str)
+    {
+        pid_t pid;
+        const char *cp = "-----------\n";
+        write(fd, cp, strlen(cp));
+
+        pid = fork();
+        if (pid == (pid_t) (-1))
+        {   /* error */
+            const char *cp = "backtrace: fork failure";
+            write(fd, cp, strlen(cp));
+        }
+        else if (pid == 0)
+        {   /* child */
+            int i;
+            char *arg[BACKTRACE_SZ + 4];
+            int arg_no = 0;
+            char *cp;
+
+            close(0);
+            dup(fd);
+            close(1);
+            dup(fd);
+            if (fd != 2)
+            {
+                close(2);
+                dup(fd);
+            }
+            arg[arg_no++] = "addr2line";
+            arg[arg_no++] = "-paf";
+            arg[arg_no++] = "-e";
+            arg[arg_no++] = backtrace_str[0];
+            cp = strchr(backtrace_str[0], '(');
+            if (cp)
+                *cp = '\0';
+
+            for (i = 1; i < sz; i++)
+            {
+                cp = strchr(backtrace_str[i], '[');
+                if (cp)
+                    arg[arg_no++] = cp + 1;
+            }
+            arg[arg_no] = 0;
+            execv("/usr/bin/addr2line", arg);
+            _exit(1);
+        }
+        else
+        {  /* parent */
+            int status;
+            waitpid(pid, &status, 0);
+            if (status)
+            {
+                char msg[100];
+                sprintf(msg, "backtrace: exit status=%d\n", status);
+                write(fd, msg, strlen(msg));
+            }
+        }
+    }
+#else
+    strcat(buf, "no backtrace support (execinfo.h not found)\n");
+    write(fd, buf, strlen(buf));
+#endif
 }
 
 void yaz_panic_sig_handler(int sig)
@@ -98,10 +160,12 @@ void yaz_panic_sig_handler(int sig)
 
 void yaz_enable_panic_backtrace(void)
 {
+#if HAVE_EXECINFO_H
     signal(SIGABRT, yaz_panic_sig_handler);
     signal(SIGSEGV, yaz_panic_sig_handler);
     signal(SIGFPE, yaz_panic_sig_handler);
     signal(SIGBUS, yaz_panic_sig_handler);
+#endif
 }
 
 /*