]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Better backtraces thanks to addr2link
authorAndreas Öman <andreas@lonelycoder.com>
Mon, 21 Feb 2011 21:40:10 +0000 (22:40 +0100)
committerAndreas Öman <andreas@lonelycoder.com>
Mon, 21 Feb 2011 21:40:10 +0000 (22:40 +0100)
src/trap.c

index 0184f1f832e5e06deab0bf6f1d8f31e38dd0aa6a..1e92497dd34f300a84cc33f094772445eca44b0e 100644 (file)
@@ -30,6 +30,7 @@ char tvh_binshasum[20];
 #include <string.h>
 #include <signal.h>
 #include <ucontext.h>
+#include <limits.h>
 #if ENABLE_EXECINFO
 #include <execinfo.h>
 #endif
@@ -49,6 +50,7 @@ char tvh_binshasum[20];
 static char line1[200];
 static char tmpbuf[1024];
 static char libs[1024];
+static char self[PATH_MAX];
 
 static void
 sappend(char *buf, size_t l, const char *fmt, ...)
@@ -62,10 +64,76 @@ sappend(char *buf, size_t l, const char *fmt, ...)
 
 
 
+/**
+ *
+ */
+static int
+add2lineresolve(const char *binary, void *addr, char *buf0, size_t buflen)
+{
+  char *buf = buf0;
+  int fd[2], r, f;
+  const char *argv[5];
+  pid_t p;
+  char addrstr[30], *cp;
+
+  argv[0] = "addr2line";
+  argv[1] = "-e";
+  argv[2] = binary;
+  argv[3] = addrstr;
+  argv[4] = NULL;
+
+  snprintf(addrstr, sizeof(addrstr), "%p", (void *)((intptr_t)addr-1));
+
+  if(pipe(fd) == -1)
+    return -1;
+
+  if((p = fork()) == -1)
+    return -1;
+
+  if(p == 0) {
+    close(0);
+    close(2);
+    close(fd[0]);
+    dup2(fd[1], 1);
+    close(fd[1]);
+    if((f = open("/dev/null", O_RDWR)) == -1)
+      exit(1);
+
+    dup2(f, 0);
+    dup2(f, 2);
+    close(f);
+
+    execve("/usr/bin/addr2line", (char *const *) argv, environ);
+    exit(2);
+  }
+
+  close(fd[1]);
+  *buf = 0;
+  while(buflen > 1) {
+    r = read(fd[0], buf, buflen);
+    if(r < 1)
+      break;
+
+    buf += r;
+    buflen -= r;
+    *buf = 0;
+    cp = strchr(buf0, '\n');
+    if(cp != NULL) {
+      *cp = 0;
+      break;
+    }
+  }
+  close(fd[0]);
+  return 0;
+}
+
+
+
 static void 
 traphandler(int sig, siginfo_t *si, void *UC)
 {
   ucontext_t *uc = UC;
+  char buf[200];
 #if ENABLE_EXECINFO
   static void *frames[MAXFRAMES];
   int nframes = backtrace(frames, MAXFRAMES);
@@ -122,6 +190,11 @@ traphandler(int sig, siginfo_t *si, void *UC)
        continue;
       }
 
+      if(self[0] && !add2lineresolve(self, frames[i], buf, sizeof(buf))) {
+       tvhlog_spawn(LOG_ALERT, "CRASH", "%s %p", buf, frames[i]);
+       continue;
+      }
+
       if(dli.dli_fname != NULL && dli.dli_fbase != NULL) {
        tvhlog_spawn(LOG_ALERT, "CRASH", "%s %p",
                     dli.dli_fname,
@@ -153,6 +226,7 @@ extern const char *htsversion_full;
 void
 trap_init(const char *ver)
 {
+  int r;
   uint8_t digest[20];
   struct sigaction sa, old;
   char path[256];
@@ -160,6 +234,11 @@ trap_init(const char *ver)
   SHA_CTX binsum;
   int fd;
 
+  r = readlink("/proc/self/exe", self, sizeof(self) - 1);
+  if(r == -1)
+    self[0] = 0;
+  else
+    self[r] = 0;
   
   if((fd = open("/proc/self/exe", O_RDONLY)) != -1) {
     struct stat st;