예제 #1
0
/** 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();
}
예제 #2
0
	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());
	}
예제 #3
0
	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);
	}
예제 #4
0
/** 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;
}
예제 #5
0
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;
}
예제 #6
0
/** 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;
}
예제 #7
0
/** 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;
}
예제 #8
0
	void OutputStacktrace() {
		PrepareStacktrace();
		Stacktrace(NULL);
		CleanupStacktrace();
	}
예제 #9
0
	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()
		}
	}
예제 #10
0
void Stacktrace(Threading::NativeThreadHandle thread, const std::string& threadName)
{
	Stacktrace(threadName.c_str(), NULL, thread);
}
예제 #11
0
void Stacktrace(Threading::NativeThreadHandle thread)
{
	Stacktrace(NULL, thread);
}
예제 #12
0
	void OutputStacktrace() {
		bool keepRunning = true;
		Stacktrace(&keepRunning);
	}
예제 #13
0
	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()
		}
	}