Commit bd33badc authored by Kevin Modzelewski's avatar Kevin Modzelewski Committed by Kevin Modzelewski

Add experimental attach-gdb-on-segfault handler

It's a little bit complicated due to the fact that
gdb has to be the parent so that it can have the permissions
to ptrace the process that segfaults.
parent 959f5a40
...@@ -23,6 +23,7 @@ addons: ...@@ -23,6 +23,7 @@ addons:
- clang-3.5 - clang-3.5
- cmake - cmake
- g++-4.8 - g++-4.8
- gdb
- libgmp3-dev - libgmp3-dev
- liblzma-dev - liblzma-dev
- libncurses5-dev - libncurses5-dev
...@@ -51,7 +52,7 @@ script: ...@@ -51,7 +52,7 @@ script:
- ccache -z - ccache -z
- ninja -j4 pyston - ninja -j4 pyston
- ccache -s - ccache -s
- ninja check-pyston - PYSTON_RUN_ARGS=G ninja check-pyston
os: os:
- linux - linux
......
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
#include <csignal> #include <csignal>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <fcntl.h>
#include <readline/history.h> #include <readline/history.h>
#include <readline/readline.h> #include <readline/readline.h>
#include <stdint.h> #include <stdint.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
...@@ -90,6 +92,86 @@ static bool handle_toplevel_exn(const ExcInfo& e, int* retcode) { ...@@ -90,6 +92,86 @@ static bool handle_toplevel_exn(const ExcInfo& e, int* retcode) {
static bool force_repl = false; static bool force_repl = false;
static bool unbuffered = false; static bool unbuffered = false;
static const char* argv0;
static int pipefds[2];
static void handle_sigsegv(int signum) {
assert(signum == SIGSEGV);
// TODO: this should set a flag saying a KeyboardInterrupt is pending.
// For now, just call abort(), so that we get a traceback at least.
fprintf(stderr, "child encountered segfault! signalling parent watcher to backtrace.\n");
char buf[1];
int r = write(pipefds[1], buf, 1);
RELEASE_ASSERT(r == 1, "");
while (true) {
sleep(1);
}
}
static int gdb_child_pid;
static void propagate_sig(int signum) {
// fprintf(stderr, "parent received signal %d, passing to child and then ignoring\n", signum);
assert(gdb_child_pid);
int r = kill(gdb_child_pid, signum);
assert(!r);
}
static void enableGdbSegfaultWatcher() {
int r = pipe2(pipefds, 0);
RELEASE_ASSERT(r == 0, "");
gdb_child_pid = fork();
if (gdb_child_pid) {
// parent watcher process
close(pipefds[1]);
for (int i = 0; i < _NSIG; i++) {
if (i == SIGCHLD)
continue;
signal(i, &propagate_sig);
}
while (true) {
char buf[1];
int r = read(pipefds[0], buf, 1);
if (r == 1) {
fprintf(stderr, "Parent process woken up by child; collecting backtrace and killing child\n");
char pidbuf[20];
snprintf(pidbuf, sizeof(pidbuf), "%d", gdb_child_pid);
close(STDOUT_FILENO);
dup2(STDERR_FILENO, STDOUT_FILENO);
r = execlp("gdb", "gdb", "-p", pidbuf, argv0, "-batch", "-ex", "set pagination 0", "-ex",
"thread apply all bt", "-ex", "kill", "-ex", "quit -11", NULL);
RELEASE_ASSERT(0, "%d %d %s", r, errno, strerror(errno));
}
if (r == 0) {
int status;
r = waitpid(gdb_child_pid, &status, 0);
RELEASE_ASSERT(r == gdb_child_pid, "%d %d %s", r, errno, strerror(errno));
int rtncode = 0;
if (WIFEXITED(status))
rtncode = WEXITSTATUS(status);
else
rtncode = 128 + WTERMSIG(status);
exit(rtncode);
}
RELEASE_ASSERT(0, "%d %d %s", r, errno, strerror(errno));
}
RELEASE_ASSERT(0, "");
}
close(pipefds[0]);
signal(SIGSEGV, &handle_sigsegv);
}
int handleArg(char code) { int handleArg(char code) {
if (code == 'O') if (code == 'O')
FORCE_OPTIMIZE = true; FORCE_OPTIMIZE = true;
...@@ -131,6 +213,8 @@ int handleArg(char code) { ...@@ -131,6 +213,8 @@ int handleArg(char code) {
CONTINUE_AFTER_FATAL = true; CONTINUE_AFTER_FATAL = true;
} else if (code == 'T') { } else if (code == 'T') {
ENABLE_TRACEBACKS = false; ENABLE_TRACEBACKS = false;
} else if (code == 'G') {
enableGdbSegfaultWatcher();
} else { } else {
fprintf(stderr, "Unknown option: -%c\n", code); fprintf(stderr, "Unknown option: -%c\n", code);
return 2; return 2;
...@@ -139,6 +223,7 @@ int handleArg(char code) { ...@@ -139,6 +223,7 @@ int handleArg(char code) {
} }
static int main(int argc, char** argv) { static int main(int argc, char** argv) {
argv0 = argv[0];
Timer _t("for jit startup"); Timer _t("for jit startup");
// llvm::sys::PrintStackTraceOnErrorSignal(); // llvm::sys::PrintStackTraceOnErrorSignal();
...@@ -168,7 +253,7 @@ static int main(int argc, char** argv) { ...@@ -168,7 +253,7 @@ static int main(int argc, char** argv) {
// Suppress getopt errors so we can throw them ourselves // Suppress getopt errors so we can throw them ourselves
opterr = 0; opterr = 0;
while ((code = getopt(argc, argv, "+:OqdIibpjtrsSvnxEc:FuPT")) != -1) { while ((code = getopt(argc, argv, "+:OqdIibpjtrsSvnxEc:FuPTG")) != -1) {
if (code == 'c') { if (code == 'c') {
assert(optarg); assert(optarg);
command = optarg; command = optarg;
......
...@@ -198,6 +198,7 @@ extern "C" void abort() { ...@@ -198,6 +198,7 @@ extern "C" void abort() {
__builtin_unreachable(); __builtin_unreachable();
} }
#if 0
extern "C" void exit(int code) { extern "C" void exit(int code) {
static void (*libc_exit)(int) = (void (*)(int))dlsym(RTLD_NEXT, "exit"); static void (*libc_exit)(int) = (void (*)(int))dlsym(RTLD_NEXT, "exit");
...@@ -219,6 +220,7 @@ extern "C" void exit(int code) { ...@@ -219,6 +220,7 @@ extern "C" void exit(int code) {
libc_exit(code); libc_exit(code);
__builtin_unreachable(); __builtin_unreachable();
} }
#endif
extern "C" void raise0() { extern "C" void raise0() {
ExcInfo* exc_info = getFrameExcInfo(); ExcInfo* exc_info = getFrameExcInfo();
......
...@@ -157,6 +157,9 @@ def run_test(fn, check_stats, run_memcheck): ...@@ -157,6 +157,9 @@ def run_test(fn, check_stats, run_memcheck):
code = p.wait() code = p.wait()
elapsed = time.time() - start elapsed = time.time() - start
if code >= 128:
code -= 256
return determine_test_result(fn, opts, code, out, stderr, elapsed) return determine_test_result(fn, opts, code, out, stderr, elapsed)
def get_test_options(fn, check_stats, run_memcheck): def get_test_options(fn, check_stats, run_memcheck):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment