summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/core.c132
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();