aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/packages/rpm/sle11/SOURCES/Use-external-tool-for-creating-backtraces-on-crashes.patch
blob: 4fc586ee9e45ab606c96bac43b98ff0b1181e400 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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