diff --git a/source/src/command.cpp b/source/src/command.cpp index e99418fd..e657b3e1 100644 --- a/source/src/command.cpp +++ b/source/src/command.cpp @@ -7,6 +7,7 @@ bool allowidentaccess(ident *id); char *exchangestr(char *o, const char *n) { delete[] o; return newstring(n); } void scripterr(); +vector executionstack; // keep history of recursive command execution (to write to log in case of a crash) vector contextstack; bool contextsealed = false; bool contextisolated[IEXC_NUM] = { false }; @@ -550,6 +551,7 @@ vector seer_t2; // timestamp of last n3 (10) level-2 calls char *executeret(const char *p) // all evaluation happens here, recursively { if(!p || !p[0]) return NULL; + executionstack.add(p); bool noproblem = true; #if 0 if(execcontext>IEXC_CFG) // only PROMPT and MAP-CFG are checked for this, fooling with core/cfg at your own risk! @@ -760,6 +762,7 @@ char *executeret(const char *p) // all evaluation hap loopj(numargs) if(w[j]) delete[] w[j]; } } + executionstack.pop(); return retval; } @@ -1043,6 +1046,17 @@ void resetcontext() curcontext = curinfo = NULL; } +void dumpexecutionstack(stream *f) +{ + if(f && executionstack.length()) + { + f->printf("cubescript execution stack (%d levels)\n", executionstack.length()); + if(curcontext) f->printf(" cubescript context: %s %s\n", curcontext, curinfo ? curinfo : ""); + loopvrev(executionstack) f->printf("%4d: %s\n", i + 1, executionstack[i]); + f->fflush(); + } +} + bool execfile(const char *cfgfile) { string s; diff --git a/source/src/main.cpp b/source/src/main.cpp index de2f6d6f..4d81cf48 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -22,6 +22,11 @@ void cleanup(char *msg) // single program exit point; #else printf("%s", msg); #endif + if(clientlogfile) + { + clientlogfile->printf("%s\n", msg); + dumpexecutionstack(clientlogfile); + } } SDL_Quit(); } @@ -68,6 +73,7 @@ void fatal(const char *s, ...) // failure exit } else puts(msg); } + DELETEP(clientlogfile); exit(EXIT_FAILURE); } diff --git a/source/src/protos.h b/source/src/protos.h index 140745d0..dc3f2fb5 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -1031,6 +1031,7 @@ extern int execcontext; extern const char *currentserver(int i); extern void setcontext(const char *context, const char *info); extern void resetcontext(); +extern void dumpexecutionstack(stream *f); // server extern int modeacronyms; diff --git a/source/src/tools.cpp b/source/src/tools.cpp index 0a33b620..5a442b5e 100644 --- a/source/src/tools.cpp +++ b/source/src/tools.cpp @@ -517,6 +517,9 @@ void stackdumper(unsigned int type, EXCEPTION_POINTERS *ep) concatstring(out, t); } } +#if !defined(STANDALONE) + if(clientlogfile) clientlogfile->printf("%s\n", out); +#endif fatal("%s", out); } #elif defined(linux) || defined(__linux) || defined(__linux__) @@ -530,7 +533,9 @@ struct signalbinder static void stackdumper(int sig) { printf("stacktrace:\n"); - +#if !defined(STANDALONE) + if(clientlogfile) clientlogfile->printf("stacktrace\n"); +#endif const int BTSIZE = 25; void *array[BTSIZE]; int n = backtrace(array, BTSIZE); @@ -538,6 +543,9 @@ struct signalbinder for(int i = 0; i < n; i++) { printf("%s\n", symbols[i]); +#if !defined(STANDALONE) + if(clientlogfile) clientlogfile->printf("%s\n", symbols[i]); +#endif } free(symbols);