/** Print stack traces for relevant threads. */ void HangHandler(bool simhang) { PRINT("Hang detection triggered %sfor Spring %s.", simhang ? "(in sim thread) " : "", SpringVersion::GetFull().c_str()); #ifdef USE_GML PRINT("MT with %d threads.", gmlThreadCount); #endif initImageHlpDll(); // Record list of loaded DLLs. PRINT("DLL information:"); SymEnumerateModules(GetCurrentProcess(), EnumModules, NULL); if (drawthread != INVALID_HANDLE_VALUE) { // Record stacktrace. PRINT("Stacktrace:"); Stacktrace(NULL, drawthread); } #if defined(USE_GML) && GML_ENABLE_SIM if (gmlMultiThreadSim && simthread != INVALID_HANDLE_VALUE) { PRINT("Stacktrace (sim):"); Stacktrace(NULL, simthread); } #endif // Unintialize IMAGEHLP.DLL SymCleanup(GetCurrentProcess()); logOutput.Flush(); }
void Stacktrace(Threading::NativeThreadHandle thread, const std::string& threadName) { if (!Threading::IsMainThread(thread)) { LOG_L(L_ERROR, "Stacktrace (%s):", threadName.c_str()); LOG_L(L_ERROR, " No Stacktraces for non-MainThread."); return; } Stacktrace(NULL, &thread, threadName.c_str()); }
void Stacktrace(Threading::NativeThreadHandle thread, const std::string& threadName, const int logLevel) { //TODO Our custom thread_backtrace() only works on the mainthread. // Use to gdb's libthread_db to get the stacktraces of all threads. if (!Threading::IsMainThread(thread) && Threading::GetCurrentThread() != thread) { LOG_I(logLevel, "Stacktrace (%s):", threadName.c_str()); LOG_I(logLevel, " No Stacktraces for non-MainThread."); return; } Stacktrace(NULL, &thread, threadName.c_str(), logLevel); }
/** Called by windows if an exception happens. */ static LONG CALLBACK ExceptionHandler(LPEXCEPTION_POINTERS e) { // Prologue. logOutput.SetSubscribersEnabled(false); PRINT("Spring %s has crashed.", SpringVersion::GetFull().c_str()); #ifdef USE_GML PRINT("MT with %d threads.", gmlThreadCount); #endif initImageHlpDll(); // Record exception info. PRINT("Exception: %s (0x%08lx)", ExceptionName(e->ExceptionRecord->ExceptionCode), e->ExceptionRecord->ExceptionCode); PRINT("Exception Address: 0x%08lx", (unsigned long int) (PVOID) e->ExceptionRecord->ExceptionAddress); // Record list of loaded DLLs. PRINT("DLL information:"); SymEnumerateModules(GetCurrentProcess(), EnumModules, NULL); // Record stacktrace. PRINT("Stacktrace:"); Stacktrace(e); // Unintialize IMAGEHLP.DLL SymCleanup(GetCurrentProcess()); // Cleanup. SDL_Quit(); logOutput.End(); // Stop writing to log. // FIXME: update closing of demo to new netcode // Inform user. char dir[MAX_PATH], msg[MAX_PATH+200]; GetCurrentDirectory(sizeof(dir) - 1, dir); SNPRINTF(msg, sizeof(msg), "Spring has crashed.\n\n" "A stacktrace has been written to:\n" "%s\\infolog.txt", dir); MessageBox(NULL, msg, "Spring: Unhandled exception", 0); // this seems to silently close the application return EXCEPTION_EXECUTE_HANDLER; // this triggers the microsoft "application has crashed" error dialog //return EXCEPTION_CONTINUE_SEARCH; // in practice, 100% CPU usage but no continuation of execution // (tested segmentation fault and division by zero) //return EXCEPTION_CONTINUE_EXECUTION; }
LONG CALLBACK ExceptionHandler(LPEXCEPTION_POINTERS e) { // generate crash report SymInitialize(GetCurrentProcess(), 0, TRUE); std::stringstream ss; ss << "== application crashed\n"; ss << stdext::format("app name: %s\n", g_app.getName()); ss << stdext::format("app version: %s\n", g_app.getVersion()); ss << stdext::format("build compiler: %s\n", BUILD_COMPILER); ss << stdext::format("build date: %s\n", __DATE__); ss << stdext::format("build type: %s\n", BUILD_TYPE); ss << stdext::format("build revision: %s (%s)\n", BUILD_REVISION, BUILD_COMMIT); ss << stdext::format("crash date: %s\n", stdext::date_time_string()); ss << stdext::format("exception: %s (0x%08lx)\n", getExceptionName(e->ExceptionRecord->ExceptionCode), e->ExceptionRecord->ExceptionCode); ss << stdext::format("exception address: 0x%08lx\n", (size_t)e->ExceptionRecord->ExceptionAddress); ss << stdext::format(" backtrace:\n"); Stacktrace(e, ss); ss << "\n"; SymCleanup(GetCurrentProcess()); // print in stdout g_logger.info(ss.str()); // write stacktrace to crashreport.log char dir[MAX_PATH]; GetCurrentDirectory(sizeof(dir) - 1, dir); std::string fileName = stdext::format("%s\\crashreport.log", dir); std::ofstream fout(fileName.c_str(), std::ios::out | std::ios::app); if(fout.is_open() && fout.good()) { fout << ss.str(); fout.close(); g_logger.info(stdext::format("Crash report saved to file %s", fileName)); } else g_logger.error("Failed to save crash report!"); // inform the user std::string msg = stdext::format( "The application has crashed.\n\n" "A crash report has been written to:\n" "%s", fileName.c_str()); MessageBox(NULL, msg.c_str(), "Application crashed", 0); // this seems to silently close the application //return EXCEPTION_EXECUTE_HANDLER; // this triggers the microsoft "application has crashed" error dialog return EXCEPTION_CONTINUE_SEARCH; }
/** Called by windows if an exception happens. */ static LONG CALLBACK ExceptionHandler(LPEXCEPTION_POINTERS e) { // Prologue. Logger::warning("CaesarIA %d has crashed.", CAESARIA_BUILD_NUMBER ); // Initialize IMAGEHLP.DLL. SymInitialize(GetCurrentProcess(), ".", TRUE); // Record exception info. Logger::warning("Exception: %s (0x%08x)\n", ExceptionName(e->ExceptionRecord->ExceptionCode), e->ExceptionRecord->ExceptionCode); Logger::warning("Exception Address: 0x%08x\n", e->ExceptionRecord->ExceptionAddress); // Record list of loaded DLLs. //Logger::warning("DLL information:\n"); //SymEnumerateModules(GetCurrentProcess(), EnumModules, NULL); // Record stacktrace. Logger::warning("Stacktrace:\n"); Stacktrace(e); // Unintialize IMAGEHLP.DLL SymCleanup(GetCurrentProcess()); // Cleanup. // FIXME: update closing of demo to new netcode // Inform user. char dir[MAX_PATH]; GetCurrentDirectory(sizeof(dir) - 1, dir); std::string msg = utils::format( 0xff, "CaesarIA has crashed.\n\n" "A stacktrace has been written to:\n" "%s\\stdout.txt", dir); OSystem::error( "CaesarIA: Unhandled exception", msg ); // this seems to silently close the application return EXCEPTION_EXECUTE_HANDLER; // this triggers the microsoft "application has crashed" error dialog //return EXCEPTION_CONTINUE_SEARCH; // in practice, 100% CPU usage but no continuation of execution // (tested segmentation fault and division by zero) //return EXCEPTION_CONTINUE_EXECUTION; }
/** Called by windows if an exception happens. */ LONG CALLBACK ExceptionHandler(LPEXCEPTION_POINTERS e) { // Prologue. logOutput.SetSubscribersEnabled(false); PRINT("Spring %s has crashed.", SpringVersion::GetFull().c_str()); #ifdef USE_GML PRINT("MT with %d threads.", gmlThreadCount); #endif PrepareStacktrace(); const std::string error(ExceptionName(e->ExceptionRecord->ExceptionCode)); // Print exception info. PRINT("Exception: %s (0x%08lx)", error.c_str(), e->ExceptionRecord->ExceptionCode); PRINT("Exception Address: 0x%08lx", (unsigned long int) (PVOID) e->ExceptionRecord->ExceptionAddress); // Print stacktrace. Stacktrace(NULL, e); CleanupStacktrace(); // Only the first crash is of any real interest CrashHandler::Remove(); // Inform user. std::ostringstream buf; buf << "Spring has crashed:\n" << " " << error << ".\n\n" << "A stacktrace has been written to:\n" << " " << logOutput.GetFilePath(); ErrorMessageBox(buf.str(), "Spring: Unhandled exception", MBF_OK | MBF_CRASH); //calls exit()! // this seems to silently close the application return EXCEPTION_EXECUTE_HANDLER; // this triggers the microsoft "application has crashed" error dialog //return EXCEPTION_CONTINUE_SEARCH; // in practice, 100% CPU usage but no continuation of execution // (tested segmentation fault and division by zero) //return EXCEPTION_CONTINUE_EXECUTION; }
void OutputStacktrace() { PrepareStacktrace(); Stacktrace(NULL); CleanupStacktrace(); }
void HandleSignal(int signal) { if (signal == SIGINT) { // ctrl+c = kill LOG("caught SIGINT, aborting"); // first try a clean exit SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); // abort after 5sec boost::thread(boost::bind(&ForcedExitAfterFiveSecs)); boost::thread(boost::bind(&ForcedExitAfterTenSecs)); return; } logSinkHandler.SetSinking(false); std::string error = strsignal(signal); // append the signal name (it seems there is no OS function to map signum to signame :<) if (signal == SIGSEGV) { error += " (SIGSEGV)"; } else if (signal == SIGILL) { error += " (SIGILL)"; } else if (signal == SIGPIPE) { error += " (SIGPIPE)"; } else if (signal == SIGIO) { error += " (SIGIO)"; } else if (signal == SIGABRT) { error += " (SIGABRT)"; } else if (signal == SIGFPE) { error += " (SIGFPE)"; } else if (signal == SIGBUS) { error += " (SIGBUS)"; } LOG_L(L_ERROR, "%s in spring %s", error.c_str(), (SpringVersion::GetFull()).c_str()); const bool nonFatalSignal = false; const bool fatalSignal = (signal == SIGSEGV) || (signal == SIGILL) || (signal == SIGPIPE) || (signal == SIGFPE) || // causes a endless loop, and process never gets far the causing cmd :< (signal == SIGABRT) || // same (signal == SIGBUS); bool keepRunning = false; bool aiCrash = false; if (fatalSignal) keepRunning = false; if (nonFatalSignal) keepRunning = true; // print stacktrace PrepareStacktrace(); Stacktrace(&aiCrash); CleanupStacktrace(); // try to clean up if (keepRunning) { bool cleanupOk = true; // try to cleanup AIs if (aiCrash) { cleanupOk = false; /*if (!containedAIInterfaceSo.empty()) { //LOG_L(L_ERROR, "Trying to kill AI Interface library only ...\n"); // TODO //cleanupOk = true; } else if (!containedSkirmishAISo.empty()) { //LOG_L(L_ERROR, "Trying to kill Skirmish AI library only ...\n"); // TODO //cleanupOk = true; }*/ } if (cleanupOk) { logSinkHandler.SetSinking(true); } else { keepRunning = false; } } // exit app if we catched a critical one if (!keepRunning) { // don't handle any further signals when exiting Remove(); std::ostringstream buf; buf << "Spring has crashed:\n" << error << ".\n\n" << "A stacktrace has been written to:\n" << " " << logOutput.GetFilePath(); ErrorMessageBox(buf.str(), "Spring crashed", MBF_OK | MBF_CRASH); // this also calls exit() } }
void Stacktrace(Threading::NativeThreadHandle thread, const std::string& threadName) { Stacktrace(threadName.c_str(), NULL, thread); }
void Stacktrace(Threading::NativeThreadHandle thread) { Stacktrace(NULL, thread); }
void OutputStacktrace() { bool keepRunning = true; Stacktrace(&keepRunning); }
void HandleSignal(int signal) { if (signal == SIGINT) { //! ctrl+c = kill LOG("caught SIGINT, aborting"); //! first try a clean exit SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); //! abort after 5sec boost::thread(boost::bind(&ForcedExitAfterFiveSecs)); return; } logSinkHandler.SetSinking(false); std::string error; if (signal == SIGSEGV) { error = "Segmentation fault (SIGSEGV)"; } else if (signal == SIGILL) { error = "Illegal instruction (SIGILL)"; } else if (signal == SIGPIPE) { error = "Broken pipe (SIGPIPE)"; } else if (signal == SIGIO) { error = "IO-Error (SIGIO)"; } else if (signal == SIGABRT) { error = "Aborted (SIGABRT)"; } else if (signal == SIGFPE) { error = "FloatingPointException (SIGFPE)"; } else { //! we should never get here error = "Unknown signal"; } LOG_L(L_ERROR, "%s in spring %s\n", error.c_str(), SpringVersion::GetFull().c_str()); //! print stacktrace bool keepRunning = false; Stacktrace(&keepRunning); //! don't try to keep on running after these signals if (keepRunning && (signal != SIGSEGV) && (signal != SIGILL) && (signal != SIGPIPE) && (signal != SIGABRT)) { keepRunning = false; } //! try to clean up if (keepRunning) { bool cleanupOk = false; { //! try to cleanup /*if (!containedAIInterfaceSo.empty()) { //LOG_L(L_ERROR, "Trying to kill AI Interface library only ...\n"); // TODO //cleanupOk = true; } else if (!containedSkirmishAISo.empty()) { //LOG_L(L_ERROR, "Trying to kill Skirmish AI library only ...\n"); // TODO //cleanupOk = true; }*/ } if (cleanupOk) { logSinkHandler.SetSinking(true); } else { keepRunning = false; } } //! exit app if we catched a critical one if (!keepRunning) { //! don't handle any further signals when exiting Remove(); std::ostringstream buf; buf << "Spring has crashed:\n" << error << ".\n\n" << "A stacktrace has been written to:\n" << " " << logOutput.GetFilePath(); ErrorMessageBox(buf.str(), "Spring crashed", MBF_CRASH); //! this also calls exit() } }