ソースを参照

* Added experimental code to generate a stack dump when it segfaults

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1026 54d463be-8e91-2dee-dedb-b68131a5f0ec
(no author) 20 年 前
コミット
f14900f7dc
1 ファイル変更94 行追加38 行削除
  1. 94 38
      src/common/core.c

+ 94 - 38
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();