File Use-external-tool-for-creating-backtraces-on-crashes.patch of Package xorg-x11-server

From bb4e768eaf8025d3ccf369cbad9a9b8be721e7ac Mon Sep 17 00:00:00 2001
From: Matthias Hopf <mhopf@suse.de>
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 <mhopf@suse.de>
---
 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 <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#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