diff options
author | Adam Borowski <kilobyte@angband.pl> | 2013-11-02 21:24:31 +0100 |
---|---|---|
committer | Adam Borowski <kilobyte@angband.pl> | 2013-11-02 21:24:31 +0100 |
commit | 92b54d82f0e3b5f2b4a9e59d1a5c353c3e9a842b (patch) | |
tree | 24ab938f15b6183498c7f383ab53712a7473e696 /crawl-ref/source/crash.cc | |
parent | ab40554ef1c94aada324bed1a4d6c36215a459c7 (diff) | |
download | crawl-ref-92b54d82f0e3b5f2b4a9e59d1a5c353c3e9a842b.tar.gz crawl-ref-92b54d82f0e3b5f2b4a9e59d1a5c353c3e9a842b.zip |
Attach and run gdb during crashes.
Its usefulness varies depending on existence of debug info, although in
every case I got at least one more symbol resolved than without it. Only
unstripped builds are fun, of course.
Diffstat (limited to 'crawl-ref/source/crash.cc')
-rw-r--r-- | crawl-ref/source/crash.cc | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/crawl-ref/source/crash.cc b/crawl-ref/source/crash.cc index 6c47073bb5..300de5a53b 100644 --- a/crawl-ref/source/crash.cc +++ b/crawl-ref/source/crash.cc @@ -10,6 +10,11 @@ #include <sys/time.h> #endif +#ifndef TARGET_OS_WINDOWS +# include <errno.h> +# include <sys/wait.h> +#endif + #if defined(UNIX) #include <unistd.h> #define BACKTRACE_SUPPORTED @@ -360,6 +365,54 @@ void write_stack_trace(FILE* file, int ignore_count) } #endif +void call_gdb(FILE *file) +{ +#ifndef TARGET_OS_WINDOWS + fprintf(file, "Trying to run gdb.\n"); + fflush(file); // so we can use fileno() + + char pid[12]; + snprintf(pid, sizeof(pid), "%d", getpid()); + + switch (int gdb = fork()) + { + case -1: + return (void)fprintf(file, "Couldn't fork: %s\n", strerror(errno)); + case 0: + { + int fd = fileno(file); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + + char exe[2048]; + ssize_t len = readlink("/proc/self/exe", exe, sizeof(exe) - 1); + if (len == -1) + strcpy(exe, "./crawl"); + else + exe[len] = 0; // readlink() doesn't null-terminate + + const char* argv[] = + { + "gdb", + "-p", + pid, + "-batch", + "-ex", + "bt full", + exe, + 0 + }; + execv("/usr/bin/gdb", (char* const*)argv); + fprintf(file, "%s\n", strerror(errno)); + } + return; + default: + waitpid(gdb, 0, 0); + } +#endif +} + void disable_other_crashes() { // If one thread calls end() without going through a crash (a handled |