diff options
Diffstat (limited to 'src/common/core.c')
-rw-r--r-- | src/common/core.c | 250 |
1 files changed, 199 insertions, 51 deletions
diff --git a/src/common/core.c b/src/common/core.c index 167b38efb..0a9e76120 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -8,17 +8,29 @@ #endif #include <signal.h> #include <string.h> +#ifdef DUMPSTACK + #ifndef CYGWIN // HAVE_EXECINFO_H + #include <execinfo.h> + #endif +#endif #include "core.h" -#include "socket.h" -#include "timer.h" -#include "version.h" -#include "showmsg.h" +#include "../common/mmo.h" +#include "../common/malloc.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/version.h" +#include "../common/showmsg.h" #ifdef MEMWATCH #include "memwatch.h" #endif +char *argp; +int runflag = 1; +char SERVER_TYPE = SERVER_NONE; +unsigned long ticks = 0; // by MC Cameri +char pid_file[256]; static void (*term_func)(void)=NULL; /*====================================== @@ -30,14 +42,54 @@ 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 *-------------------------------------- */ - +// for handling certain signals ourselves, like SIGPIPE +static void sig_ignore(int sn) { + printf ("Broken pipe found... closing socket\n"); // set to eof in socket.c + return; // does nothing here +} static void sig_proc(int sn) { int i; + static int is_called = 0; + + if(is_called++) + return; + switch(sn){ case SIGINT: case SIGTERM: @@ -53,6 +105,66 @@ static void sig_proc(int sn) } } +/*========================================= + * Dumps the stack using glibc's backtrace + *----------------------------------------- + */ +#ifndef DUMPSTACK + #define sig_dump SIG_DFL +#else + #ifdef CYGWIN + #define FOPEN_ freopen + extern void cygwin_stackdump(); + #else + #define FOPEN_(fn,m,s) fopen(fn,m) + #endif +extern const char *strsignal(int); +void sig_dump(int sn) +{ + FILE *fp; + char file[256]; + int no = 0; + + #ifndef CYGWIN + void* array[20]; + char **stack; + size_t size; + #endif + + // search for a usable filename + do { + sprintf (file, "log/%s%04d.stackdump", argp, ++no); + } while((fp = fopen(file,"r")) && (fclose(fp), no < 9999)); + // dump the trace into the file + + if ((fp = FOPEN_(file, "w", stderr)) != NULL) { + printf ("Dumping stack... "); + fprintf(fp, "Exception: %s \n", strsignal(sn)); + fflush (fp); + + #ifdef CYGWIN + cygwin_stackdump (); + #else + 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"); + aFree(stack); + #endif + + printf ("Done.\n"); + fflush(stdout); + fclose(fp); + } + // 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; @@ -60,12 +172,13 @@ int get_svn_revision(char *svnentry) { // Warning: minor syntax checking if ((fp = fopen(svnentry, "r")) == NULL) { return 0; } else { - while (fgets(line,1023,fp)) if (strstr(line,"revision=")) break; + while (fgets(line,1023,fp)) + if (strstr(line,"revision=")) break; fclose(fp); - if (sscanf(line," %*[^\"]\"%d%*[^\n]",&rev)==1) - return rev; + if (sscanf(line," %*[^\"]\"%d%*[^\n]",&rev) == 1) + return rev; else - return 0; + return 0; } // return 0; } @@ -87,7 +200,7 @@ static void display_title(void) // \033[1m : use bold for font printf("\033[2J"); // clear screen and go up/left (0, 0 position in text) printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n"); // white writing (37) on blue background (44), \033[K clean until end of file - printf("\033[0;44m (\033[1;33m (c)2004 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) + printf("\033[0;44m (\033[1;33m (c)2005 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) printf("\033[0;44m (\033[1m ______ __ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m /\\ _ \\/\\ \\__/\\ \\ v%2d.%02d.%02d \033[0;44m)\033[K\033[0m\n", ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m __\\ \\ \\_\\ \\ \\ ,_\\ \\ \\___ __ ___ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char @@ -100,80 +213,115 @@ static void display_title(void) printf("\033[0;44m (\033[1m ( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) - printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2004 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) + printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2005 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n\n"); // reset color if ((revision = get_svn_revision(".svn\\entries"))>0) { - snprintf(tmp_output,sizeof(tmp_output),"SVN Revision: %d.\n",revision); + snprintf(tmp_output,sizeof(tmp_output),"SVN Revision: '"CL_WHITE"%d"CL_RESET"'.\n",revision); ShowInfo(tmp_output); } } -// 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 +/*====================================== + * CORE : MAINROUTINE + *-------------------------------------- + */ -#ifndef POSIX -#define compat_signal(signo, func) signal(signo, func) -#else -sigfunc *compat_signal(int signo, sigfunc *func) -{ - struct sigaction sact, oact; +void pid_delete(void) { + unlink(pid_file); +} - sact.sa_handler = func; - sigemptyset(&sact.sa_mask); - sact.sa_flags = 0; -#ifdef SA_INTERRUPT - sact.sa_flags |= SA_INTERRUPT; /* SunOS */ +void pid_create(const char* file) { + FILE *fp; + int len = strlen(file); + strcpy(pid_file,file); + if(len > 4 && pid_file[len - 4] == '.') { + pid_file[len - 4] = 0; + } + strcat(pid_file,".pid"); + fp = fopen(pid_file,"w"); + if(fp) { +#ifdef _WIN32 + fprintf(fp,"%d",GetCurrentProcessId()); +#else + fprintf(fp,"%d",getpid()); #endif + fclose(fp); + atexit(pid_delete); + } +} - if (sigaction(signo, &sact, &oact) < 0) - return (SIG_ERR); +#define LOG_UPTIME 0 +void log_uptime(void) +{ +#if LOG_UPTIME + time_t curtime; + char curtime2[24]; + FILE *fp; + long seconds = 0, day = 24*60*60, hour = 60*60, + minute = 60, days = 0, hours = 0, minutes = 0; - return (oact.sa_handler); -} -#endif + fp = fopen("log/uptime.log","a"); + if (fp) { + time(&curtime); + strftime(curtime2, 24, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + seconds = (gettick()-ticks)/CLOCKS_PER_SEC; + days = seconds/day; + seconds -= (seconds/day>0)?(seconds/day)*day:0; + hours = seconds/hour; + seconds -= (seconds/hour>0)?(seconds/hour)*hour:0; + minutes = seconds/minute; + seconds -= (seconds/minute>0)?(seconds/minute)*minute:0; -/*====================================== - * CORE : MAINROUTINE - *-------------------------------------- - */ + fprintf(fp, "%s: %s uptime - %ld days, %ld hours, %ld minutes, %ld seconds.\n", + curtime2, argp, days, hours, minutes, seconds); + fclose(fp); + } -int runflag = 1; + return; +#endif +} int main(int argc,char **argv) { int next; + if ((argp = strstr(argv[0], "./")) != NULL) + argp+=2; + else argp = argv[0]; + + display_title(); + + do_init_memmgr(argp); // 一番最初に実行する必要がある + atexit(log_uptime); + pid_create(argp); Net_Init(); do_socket(); - compat_signal(SIGPIPE,SIG_IGN); + compat_signal(SIGPIPE, sig_ignore); 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 - compat_signal(SIGILL, SIG_DFL); + 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 - display_title(); + tick_ = time(0); + ticks = gettick(); do_init(argc,argv); + while(runflag){ next=do_timer(gettick_nocache()); do_sendrecv(next); do_parsepacket(); } + return 0; } |