From bb4e768eaf8025d3ccf369cbad9a9b8be721e7ac Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Wed, 25 Aug 2010 14:12:48 +0200 Subject: [PATCH] Use external tool for creating backtraces on crashes if available. This calls /usr/bin/xorg-backtrace to create reasonable commented backtraces with gdb. On errors it falls back to the generic method. Signed-off-by: Matthias Hopf --- os/backtrace.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 82 insertions(+), 0 deletions(-) diff --git a/os/backtrace.c b/os/backtrace.c index 7ca6dab..1e3201a 100644 --- a/os/backtrace.c +++ b/os/backtrace.c @@ -28,6 +28,81 @@ #include "os.h" #include "misc.h" +#include +#include +#include +#include +#include +#include + +#define XORG_BACKTRACE "/usr/bin/xorg-backtrace" + +/* Call gdb to create reasonable(!) backtrace. Returns 0 if successfull. */ +static int xorg_backtrace_gdb(void) +{ + static const char *xorg_backtrace = XORG_BACKTRACE; + char pidstr[12]; + char fdname[] = "/tmp/xorg.XXXXXX"; + char buf[256]; + pid_t pid; + int fd, status = -1, ret; + FILE *f; + + if (access (xorg_backtrace, R_OK | X_OK) != 0) { + ErrorF ("%s not found, using internal backtrace system\n", xorg_backtrace); + return 1; + } + if ( (fd = mkstemp (fdname)) == -1) { + ErrorF ("xorg_backtrace_gdb internal error 1\n"); + return 1; + } + unlink (fdname); + snprintf (pidstr, 12, "%d", getpid()); + + switch ( (pid = fork()) ) { + case 0: + close (0); + close (1); + close (2); + dup2 (fd, 1); + dup2 (fd, 2); + close (fd); + execl (xorg_backtrace, xorg_backtrace, pidstr, NULL); + exit (-1); + case -1: + close (fd); + return 1; + } + + while (waitpid (pid, &status, 0) == -1 && errno == EINTR) + ; + if (WIFEXITED (status) && WEXITSTATUS (status) == 0) + ret = 0; + else { + ErrorF ("%s failed with returncode %d\n", xorg_backtrace, WEXITSTATUS (status)); + ret = 1; + } + + lseek (fd, 0, SEEK_SET); + if (! (f = fdopen (fd, "r"))) { + ErrorF ("xorg_backtrace_gdb internal error 2\n"); + close (fd); + return 1; + } + status = 0; + while (fgets (buf, 256, f)) { + status++; + ErrorF("%s", buf); + } + fclose (f); + if (status < 10 && ret == 0) { + ErrorF ("%s only produced %d lines of output\n", xorg_backtrace, status); + return 1; + } + + return ret; +} + #ifdef HAVE_BACKTRACE #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -41,6 +116,10 @@ void xorg_backtrace(void) const char *mod; int size, i; Dl_info info; + + if (xorg_backtrace_gdb () == 0) + return; + ErrorF("\nBacktrace:\n"); size = backtrace(array, 64); for (i = 0; i < size; i++) { @@ -182,6 +261,9 @@ static int xorg_backtrace_pstack(void) { void xorg_backtrace(void) { + if (xorg_backtrace_gdb () == 0) + return; + ErrorF("\nBacktrace:\n"); # ifdef HAVE_PSTACK -- 1.6.0.2