summaryrefslogtreecommitdiff
path: root/os/backtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/backtrace.c')
-rw-r--r--os/backtrace.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/os/backtrace.c b/os/backtrace.c
index 81348f417..9d525b545 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -30,6 +30,13 @@
#include <errno.h>
#include <string.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
@@ -138,9 +145,12 @@ xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
}
#endif /* HAVE_WALKCONTEXT */
-#ifdef HAVE_PSTACK
+/*
+ fork/exec a program to create a backtrace
+ Returns 0 if successful.
+*/
static int
-xorg_backtrace_pstack(void)
+xorg_backtrace_exec_wrapper(const char *path)
{
pid_t kidpid;
int pipefd[2];
@@ -149,7 +159,7 @@ xorg_backtrace_pstack(void)
return -1;
}
- kidpid = fork1();
+ kidpid = fork();
if (kidpid == -1) {
/* ERROR */
@@ -162,11 +172,13 @@ 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 {
@@ -185,17 +197,33 @@ xorg_backtrace_pstack(void)
btline[bytesread] = 0;
ErrorF("%s", btline);
}
- else if ((bytesread < 0) || ((errno != EINTR) && (errno != EAGAIN)))
+ else if ((bytesread == 0) || ((errno != EINTR) && (errno != EAGAIN)))
done = 1;
}
close(pipefd[0]);
waitpid(kidpid, &kidstat, 0);
- if (kidstat != 0)
+ if (!(WIFEXITED(kidstat) && WEXITSTATUS(kidstat) == 0)) {
+ ErrorF("%s failed with returncode %d\n", path,
+ WEXITSTATUS(kidstat));
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_script(void)
+{
+ return xorg_backtrace_exec_wrapper(BINDIR "/xorg-backtrace");
+}
#if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
@@ -232,7 +260,8 @@ xorg_backtrace(void)
void
xorg_backtrace(void)
{
- return;
+ if (xorg_backtrace_script() == 0)
+ return;
}
#endif