[PATCH] Use external tool for creating backtraces on crashes if available.
Matthias Hopf
mhopf at suse.de
Fri Oct 8 09:25:12 PDT 2010
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 at 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
More information about the xorg-devel
mailing list