diff options
author | zelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573> | 2009-01-22 05:17:56 +0000 |
---|---|---|
committer | zelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573> | 2009-01-22 05:17:56 +0000 |
commit | d42a180a16bfde48d1b4b198db0d64c097ab93a7 (patch) | |
tree | 75e1cda9ad77f84596abe6ab49669cae35e6a563 /crawl-ref/source/crash-u.cc | |
parent | e547d7f8d9b7dc26589af1e1290fa5df850722f0 (diff) | |
download | crawl-ref-d42a180a16bfde48d1b4b198db0d64c097ab93a7.tar.gz crawl-ref-d42a180a16bfde48d1b4b198db0d64c097ab93a7.zip |
Put platform dependant crash handling code into crash-X.cc files, and link
against them in the make files like libunix/libgui/etc are.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8675 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/crash-u.cc')
-rw-r--r-- | crawl-ref/source/crash-u.cc | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/crawl-ref/source/crash-u.cc b/crawl-ref/source/crash-u.cc new file mode 100644 index 0000000000..fba87d64fb --- /dev/null +++ b/crawl-ref/source/crash-u.cc @@ -0,0 +1,176 @@ +/* + * File: crash-u.cc + * Summary: UNIX specific crash handling functions. + * Written by: Matthew Cline + * + * Modified for Crawl Reference by $Author$ on $Date$ + */ + +#include "AppHdr.h" +REVISION("$Rev$"); + +#ifdef USE_UNIX_SIGNALS +#include <signal.h> +#endif + +#ifdef __GLIBC__ +#include <execinfo.h> +#endif + +#include "crash.h" + +#include "externs.h" +#include "state.h" +#include "initfile.h" + +///////////////////////////////////////////////////////////////////////////// +// Code for printing out debugging info on a crash. +//////////////////////////////////////////////////////////////////////////// +static int _crash_signal = 0; +static int _recursion_depth = 0; + +static void _crash_signal_handler(int sig_num) +{ + if (crawl_state.game_crashed) + { + if (_recursion_depth > 0) + return; + _recursion_depth++; + + fprintf(stderr, "Recursive crash." EOL); + + std::string dir = (!Options.morgue_dir.empty() ? Options.morgue_dir : + !SysEnv.crawl_dir.empty() ? SysEnv.crawl_dir + : ""); + + if (!dir.empty() && dir[dir.length() - 1] != FILE_SEPARATOR) + dir += FILE_SEPARATOR; + + char name[180]; + + sprintf(name, "%scrash-recursive-%s-%d.txt", dir.c_str(), + you.your_name, (int) time(NULL)); + + FILE* file = fopen(name, "w"); + + if (file == NULL) + file = stderr; + + write_stack_trace(file, 0); + + if (file != stderr) + fclose(file); + return; + } + + _crash_signal = sig_num; + crawl_state.game_crashed = true; + + // In case the crash dumper is unable to open a file and has to dump + // to stderr. +#ifndef USE_TILE + unixcurses_shutdown(); +#endif + + do_crash_dump(); + + // Now crash for real. + signal(sig_num, SIG_DFL); + raise(sig_num); +} + +void init_crash_handler() +{ +#if defined(USE_UNIX_SIGNALS) + + for (int i = 1; i <= 64; i++) + { +#ifdef SIGHUP_SAVE + if (i == SIGHUP) + continue; +#endif +#ifdef SIGQUIT + if (i == SIGQUIT) + continue; +#endif +#ifdef SIGINT + if (i == SIGINT) + continue; +#endif +#ifdef SIGCHLD + if (i == SIGCHLD) + continue; +#endif +#ifdef SIGTSTP + if (i == SIGTSTP) + continue; +#endif +#ifdef SIGCONT + if (i == SIGCONT) + continue; +#endif +#ifdef SIGIO + if (i == SIGIO) + continue; +#endif +#ifdef SIGPROF + if (i == SIGPROF) + continue; +#endif + if (i == SIGWINCH) + continue; + + signal(i, _crash_signal_handler); + } + +#endif // if defined(USE_UNIX_SIGNALS) +} + +void dump_crash_info(FILE* file) +{ + const char *name = strsignal(_crash_signal); + if (name == NULL) + name = "INVALID"; + + fprintf(file, "Crash caused by signal #%d: %s" EOL, _crash_signal, + name); +} + +#ifdef __GLIBC__ +// NOTE: This should work on OS X, according to +// http://developer.apple.com/DOCUMENTATION/DARWIN/Reference/ManPages/man3/backtrace_symbols.3.html + +void write_stack_trace(FILE* file, int ignore_count) +{ + void* frames[50]; + + int num_frames = backtrace(frames, ARRAYSZ(frames)); + + char **symbols = backtrace_symbols(frames, num_frames); + + if (symbols == NULL) + { + fprintf(stderr, "Out of memroy." EOL); + fprintf(file, "Out of memory." EOL); + + // backtrace_symbols_fd() can print out the stack trace even if + // malloc() can't find any free memory. + backtrace_symbols_fd(frames, num_frames, fileno(file)); + return; + } + + for (int i = ignore_count; i < num_frames; i++) + { + fprintf(file, "%s" EOL, symbols[i]); + } + + free(symbols); +} +#else // ifdef __GLIBC__ +void write_stack_trace(FILE* file, int ignore_count) +{ + const char* msg = "Unable to get stack trace on this platform." EOL; + fprintf(stderr, msg); + fprintf(file, msg); +} +#endif |