diff options
Diffstat (limited to 'src/common/core.c')
-rw-r--r-- | src/common/core.c | 132 |
1 files changed, 94 insertions, 38 deletions
diff --git a/src/common/core.c b/src/common/core.c index a8c922fc3..d5251e352 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -8,6 +8,9 @@ #endif #include <signal.h> #include <string.h> +#ifdef DUMPSTACK +#include <execinfo.h> +#endif #include "../common/mmo.h" #include "core.h" @@ -31,6 +34,37 @@ void set_termfunc(void (*termfunc)(void)) term_func = termfunc; } +// Added by Gabuzomeu +// +// This is an implementation of signal() using sigaction() for portability. +// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced +// Programming in the UNIX Environment_. +// +#ifndef SIGPIPE +#define SIGPIPE SIGINT +#endif + +#ifndef POSIX +#define compat_signal(signo, func) signal(signo, func) +#else +sigfunc *compat_signal(int signo, sigfunc *func) +{ + struct sigaction sact, oact; + + sact.sa_handler = func; + sigemptyset(&sact.sa_mask); + sact.sa_flags = 0; +#ifdef SA_INTERRUPT + sact.sa_flags |= SA_INTERRUPT; /* SunOS */ +#endif + + if (sigaction(signo, &sact, &oact) < 0) + return (SIG_ERR); + + return (oact.sa_handler); +} +#endif + /*====================================== * CORE : Signal Sub Function *-------------------------------------- @@ -54,6 +88,49 @@ static void sig_proc(int sn) } } +/*========================================= + * Dumps the stack using glibc's backtrace + *----------------------------------------- + */ +#ifdef DUMPSTACK +static void sig_dump(int sn) +{ + FILE *fp; + void* array[20]; + + char **stack; + size_t size; + int no = 0; + char tmp[256]; + + // search for a usable filename + do { + sprintf(tmp,"save/stackdump_%04d.txt", ++no); + } while((fp = fopen(tmp,"r")) && (fclose(fp), no < 9999)); + // dump the trace into the file + if ((fp = fopen (tmp,"w")) != NULL) { + + fprintf(fp,"Exception: %s\n", strsignal(sn)); + fprintf(fp,"Stack trace:\n"); + size = backtrace (array, 20); + stack = backtrace_symbols (array, size); + + for (no = 0; no < size; no++) { + + fprintf(fp, "%s\n", stack[no]); + + } + fprintf(fp,"End of stack trace\n"); + + fclose(fp); + free(stack); + } + // When pass the signal to the system's default handler + compat_signal(sn, SIG_DFL); + raise(sn); +} +#endif + int get_svn_revision(char *svnentry) { // Warning: minor syntax checking char line[1024]; int rev = 0; @@ -110,38 +187,6 @@ static void display_title(void) } } -// Added by Gabuzomeu -// -// This is an implementation of signal() using sigaction() for portability. -// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced -// Programming in the UNIX Environment_. -// -#ifndef SIGPIPE -#define SIGPIPE SIGINT -#endif - -#ifndef POSIX -#define compat_signal(signo, func) signal(signo, func) -#else -sigfunc *compat_signal(int signo, sigfunc *func) -{ - struct sigaction sact, oact; - - sact.sa_handler = func; - sigemptyset(&sact.sa_mask); - sact.sa_flags = 0; -#ifdef SA_INTERRUPT - sact.sa_flags |= SA_INTERRUPT; /* SunOS */ -#endif - - if (sigaction(signo, &sact, &oact) < 0) - return (SIG_ERR); - - return (oact.sa_handler); -} -#endif - - /*====================================== * CORE : MAINROUTINE *-------------------------------------- @@ -160,13 +205,24 @@ int main(int argc,char **argv) compat_signal(SIGTERM,sig_proc); compat_signal(SIGINT,sig_proc); - // Signal to create coredumps by system when necessary (crash) - compat_signal(SIGSEGV, SIG_DFL); -#ifndef _WIN32 - compat_signal(SIGBUS, SIG_DFL); - compat_signal(SIGTRAP, SIG_DFL); -#endif +#ifndef DUMPSTACK + // Signal to create coredumps by system when necessary (crash) + compat_signal(SIGSEGV, SIG_DFL); + compat_signal(SIGFPE, SIG_DFL); compat_signal(SIGILL, SIG_DFL); + #ifndef _WIN32 + compat_signal(SIGBUS, SIG_DFL); + compat_signal(SIGTRAP, SIG_DFL); + #endif +#else + compat_signal(SIGSEGV, sig_dump); + compat_signal(SIGFPE, sig_dump); + compat_signal(SIGILL, sig_dump); + #ifndef _WIN32 + compat_signal(SIGBUS, sig_dump); + compat_signal(SIGTRAP, SIG_DFL); + #endif +#endif display_title(); |