long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) { // save config if( host.state != HOST_CRASHED ) { // check to avoid recursive call error_on_exit = true; host.crashed = true; if( host.type == HOST_NORMAL ) CL_Crashed(); // tell client about crash else host.state = HOST_CRASHED; Msg( "Sys_Crash: call %p at address %p\n", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode ); if( host.developer <= 0 ) { // no reason to call debugger in release build - just exit Sys_Quit(); return EXCEPTION_CONTINUE_EXECUTION; } // all other states keep unchanged to let debugger find bug Con_DestroyConsole(); } if( host.oldFilter ) return host.oldFilter( pInfo ); return EXCEPTION_CONTINUE_EXECUTION; }
/* ================= Host_Shutdown ================= */ void EXPORT Host_Shutdown( void ) { if( host.shutdown_issued ) return; host.shutdown_issued = true; switch( host.state ) { case HOST_INIT: case HOST_CRASHED: case HOST_ERR_FATAL: if( host.type == HOST_NORMAL ) MsgDev( D_WARN, "Not shutting down normally (%d), skipping config save!\n", host.state ); if( host.state != HOST_ERR_FATAL) host.state = HOST_SHUTDOWN; break; default: if( host.type == HOST_NORMAL ) { Host_WriteConfig(); IN_TouchWriteConfig(); } host.state = HOST_SHUTDOWN; // prepare host to normal shutdown } if( !host.change_game ) Q_strncpy( host.finalmsg, "Server shutdown", sizeof( host.finalmsg )); Log_Printf( "Server shutdown\n" ); Log_Close(); SV_Shutdown( false ); CL_Shutdown(); Mod_Shutdown(); NET_Shutdown(); HTTP_Shutdown(); Cmd_Shutdown(); Host_FreeCommon(); Con_DestroyConsole(); Sys_RestoreCrashHandler(); }
/* ================= Host_Shutdown ================= */ void EXPORT Host_Shutdown( void ) { if( host.shutdown_issued ) return; host.shutdown_issued = true; if( host.state != HOST_ERR_FATAL ) host.state = HOST_SHUTDOWN; // prepare host to normal shutdown if( !host.change_game ) Q_strncpy( host.finalmsg, "Server shutdown", sizeof( host.finalmsg )); if( host.type == HOST_NORMAL ) Host_WriteConfig(); SV_Shutdown( false ); CL_Shutdown(); Mod_Shutdown(); NET_Shutdown(); Host_FreeCommon(); Con_DestroyConsole(); #ifdef _WIN32 // restore filter if( host.oldFilter ) SetUnhandledExceptionFilter( host.oldFilter ); }
void Sys_Crash( int signal, siginfo_t *si, void *context) { void *trace[32]; char message[1024], stackframe[256]; int len, stacklen, logfd, i = 0; ucontext_t *ucontext = (ucontext_t*)context; #if __i386__ #ifdef __FreeBSD__ void *pc = (void*)ucontext->uc_mcontext.mc_eip, **bp = (void**)ucontext->uc_mcontext.mc_ebp, **sp = (void**)ucontext->uc_mcontext.mc_esp; #elif __NetBSD__ void *pc = (void*)ucontext->uc_mcontext.__gregs[REG_EIP], **bp = (void**)ucontext->uc_mcontext.__gregs[REG_EBP], **sp = (void**)ucontext->uc_mcontext.__gregs[REG_ESP]; #elif __OpenBSD__ void *pc = (void*)sc_eip, **bp = (void**)sc_ebp, **sp = (void**)sc_esp; #else void *pc = (void*)ucontext->uc_mcontext.gregs[REG_EIP], **bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP], **sp = (void**)ucontext->uc_mcontext.gregs[REG_ESP]; #endif #elif defined (__arm__) // arm not tested void *pc = (void*)ucontext->uc_mcontext.arm_pc, **bp = (void*)ucontext->uc_mcontext.arm_r10, **sp = (void*)ucontext->uc_mcontext.arm_sp; #endif // Safe actions first, stack and memory may be corrupted #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) len = snprintf(message, 1024, "Sys_Crash: signal %d, err %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr); #else len = snprintf(message, 1024, "Sys_Crash: signal %d, err %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr); #endif write(2, message, len); // Flush buffers before writing directly to descriptors fflush( stdout ); fflush( stderr ); // Now get log fd and write trace directly to log logfd = Sys_LogFileNo(); write( logfd, message, len ); write( 2, "Stack backtrace:\n", 17 ); write( logfd, "Stack backtrace:\n", 17 ); strncpy(message + len, "Stack backtrace:\n", 1024 - len); len += 17; long pagesize = sysconf(_SC_PAGESIZE); do { int line = printframe( message + len, 1024 - len, ++i, pc); write( 2, message + len, line ); write( logfd, message + len, line ); len += line; //if( !dladdr(bp,0) ) break; // Only when bp is in module if( mprotect((char *)(((int) bp + pagesize-1) & ~(pagesize-1)), pagesize, PROT_READ) == -1) break; if( mprotect((char *)(((int) bp[0] + pagesize-1) & ~(pagesize-1)), pagesize, PROT_READ) == -1) break; pc = bp[1]; bp = (void**)bp[0]; } while (bp); // Try to print stack write( 2, "Stack dump:\n", 12 ); write( logfd, "Stack dump:\n", 12 ); strncpy(message + len, "Stack dump:\n", 1024 - len); len += 12; if( mprotect((char *)(((int) sp + pagesize-1) & ~(pagesize-1)), pagesize, PROT_READ) != -1) for( i = 0; i < 32; i++ ) { int line = printframe( message + len, 1024 - len, i, sp[i] ); write( 2, message + len, line ); write( logfd, message + len, line ); len += line; } // Put MessageBox as Sys_Error Msg( message ); #ifdef XASH_SDL SDL_SetWindowGrab(host.hWnd, false); //SDL_MouseQuit(); MSGBOX( message ); #endif // Log saved, now we can try to save configs and close log correctly, it may crash if( host.type == HOST_NORMAL ) CL_Crashed(); host.state = HOST_CRASHED; error_on_exit = true; host.crashed = true; Con_DestroyConsole(); Sys_Quit(); }