forked from pool/xorg-x11-server
124 lines
2.9 KiB
Diff
124 lines
2.9 KiB
Diff
|
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
|
||
|
|