void Remove() { const sigaction_t& sa = GetSigAction(SIG_DFL); sigaction(SIGSEGV, &sa, NULL); // segmentation fault sigaction(SIGILL, &sa, NULL); // illegal instruction sigaction(SIGPIPE, &sa, NULL); // maybe some network error sigaction(SIGIO, &sa, NULL); // who knows? sigaction(SIGFPE, &sa, NULL); // div0 and more sigaction(SIGABRT, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGBUS, &sa, NULL); // on macosx EXC_BAD_ACCESS (mach exception) is translated to SIGBUS std::set_new_handler(NULL); }
void Install() { struct rlimit limits; if ((getrlimit(RLIMIT_CORE, &limits) == 0) && (limits.rlim_cur > 0)) { LOG("Core dumps enabled, not installing signal handler"); LOG("see /proc/sys/kernel/core_pattern where it gets written"); return; } const sigaction_t& sa = GetSigAction(&HandleSignal); sigaction(SIGSEGV, &sa, NULL); // segmentation fault sigaction(SIGILL, &sa, NULL); // illegal instruction sigaction(SIGPIPE, &sa, NULL); // maybe some network error sigaction(SIGIO, &sa, NULL); // who knows? sigaction(SIGFPE, &sa, NULL); // div0 and more sigaction(SIGABRT, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGBUS, &sa, NULL); // on macosx EXC_BAD_ACCESS (mach exception) is translated to SIGBUS std::set_new_handler(NewHandler); }
void HandleSignal(int signal, siginfo_t* siginfo, void* pctx) { if (signal == SIGINT) { // ctrl+c = kill LOG("caught SIGINT, aborting"); #ifndef HEADLESS // first try a clean exit SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); #endif // abort after 5sec boost::thread(boost::bind(&ForcedExitAfterFiveSecs)); boost::thread(boost::bind(&ForcedExitAfterTenSecs)); return; } // Turn off signal handling for this signal temporarily in order to disable recursive events (e.g. SIGSEGV) reentrances++; if (reentrances >= 2) { sigaction_t& sa = GetSigAction(NULL); sigaction(signal, &sa, NULL); } ucontext_t* uctx = reinterpret_cast<ucontext_t*> (pctx); 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(); HaltedStacktrace(error, siginfo, uctx); 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() } // Re-enable signal handling for this signal // FIXME: reentrances should be implemented using boost::thread_specific_ptr if (reentrances >= 2) { sigaction_t& sa = GetSigAction(&HandleSignal); sigaction(signal, &sa, NULL); } reentrances--; }