summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/crash.cc
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2013-11-02 21:24:31 +0100
committerAdam Borowski <kilobyte@angband.pl>2013-11-02 21:24:31 +0100
commit92b54d82f0e3b5f2b4a9e59d1a5c353c3e9a842b (patch)
tree24ab938f15b6183498c7f383ab53712a7473e696 /crawl-ref/source/crash.cc
parentab40554ef1c94aada324bed1a4d6c36215a459c7 (diff)
downloadcrawl-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.cc53
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