[PATCH] Use external tool for creating backtraces on crashes if available.
Matthias Hopf
mhopf-l3A5Bk7waGM at public.gmane.org
Fri Oct 8 09:25:12 PDT 2010
Make the code for fork/exec-ing a helper program to perform a backtrace
more generic, so it can be used to call /usr/bin/xorg-backtrace, a
script which invokes gdb to create reasonable backtraces.
On errors it falls back to the generic method.
Based on a patch by Matthias Hopf mhopf at suse.de
Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
---
os/Makefile.am | 2 +-
os/backtrace.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/os/Makefile.am b/os/Makefile.am
index 3e4f2c5..b40ee78 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -1,6 +1,6 @@
noinst_LTLIBRARIES = libos.la liblog.la
-AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS)
+AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS) -DBINDIR=\"$(bindir)\"
SECURERPC_SRCS = rpcauth.c
XDMCP_SRCS = xdmcp.c
diff --git a/os/backtrace.c b/os/backtrace.c
index 7ca6dab..b1ad535 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -28,6 +28,13 @@
#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>
+
#ifdef HAVE_BACKTRACE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -41,6 +48,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++) {
@@ -121,8 +132,12 @@ static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
}
# endif /* HAVE_WALKCONTEXT */
-# ifdef HAVE_PSTACK
-static int xorg_backtrace_pstack(void) {
+/*
+ fork/exec a program to create a backtrace
+ Returns 0 if successful.
+*/
+static int xorg_backtrace_exec_wrapper(const char* path)
+{
pid_t kidpid;
int pipefd[2];
@@ -130,7 +145,7 @@ static int xorg_backtrace_pstack(void) {
return -1;
}
- kidpid = fork1();
+ kidpid = fork();
if (kidpid == -1) {
/* ERROR */
@@ -142,11 +157,13 @@ static int xorg_backtrace_pstack(void) {
seteuid(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
+ close(STDERR_FILENO);
dup2(pipefd[1],STDOUT_FILENO);
- closefrom(STDERR_FILENO);
+ dup2(pipefd[1],STDERR_FILENO);
+ close(pipefd[1]);
snprintf(parent, sizeof(parent), "%d", getppid());
- execle("/usr/bin/pstack", "pstack", parent, NULL);
+ execle(path, path, parent, NULL, NULL);
exit(1);
} else {
/* PARENT */
@@ -154,13 +171,15 @@ static int xorg_backtrace_pstack(void) {
int kidstat;
int bytesread;
int done = 0;
-
+ int status = -1;
+
close(pipefd[1]);
while (!done) {
bytesread = read(pipefd[0], btline, sizeof(btline) - 1);
if (bytesread > 0) {
+ status++;
btline[bytesread] = 0;
ErrorF("%s", btline);
}
@@ -170,18 +189,38 @@ static int xorg_backtrace_pstack(void) {
}
close(pipefd[0]);
waitpid(kidpid, &kidstat, 0);
- if (kidstat != 0)
- return -1;
+ if (!(WIFEXITED (kidstat) && WEXITSTATUS (kidstat) == 0))
+ {
+ ErrorF ("%s failed with returncode %d\n", path, WEXITSTATUS (kidstat));
+ return -1;
+ }
+ if (status < 10) {
+ ErrorF ("%s only produced %d lines of output\n", path, status);
+ return -1;
+ }
}
return 0;
}
-# endif /* HAVE_PSTACK */
+# ifdef HAVE_PSTACK
+static int xorg_backtrace_pstack(void)
+{
+ return xorg_backtrace_exec_wrapper("/usr/bin/pstack");
+}
+#endif
+
+static int xorg_backtrace_gdb(void)
+{
+ return xorg_backtrace_exec_wrapper(BINDIR "/xorg-backtrace");
+}
# if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
void xorg_backtrace(void) {
+ if (xorg_backtrace_gdb () == 0)
+ return;
+
ErrorF("\nBacktrace:\n");
# ifdef HAVE_PSTACK
@@ -206,8 +245,11 @@ void xorg_backtrace(void) {
# else
-/* Default fallback if we can't find any way to get a backtrace */
-void xorg_backtrace(void) { return; }
+/* Default fallback if we can't find any better way to get a backtrace */
+void xorg_backtrace(void) {
+ if (xorg_backtrace_gdb () == 0)
+ return;
+}
# endif
#endif
--
1.7.2.3
--------------000401080505000000060809--
More information about the xorg-devel
mailing list