[Exception] Added better exception handling so that when the users are morons it explains exactly what happened to them.... cause they're morons

This commit is contained in:
TheApadayo 2017-02-09 16:16:49 -05:00
parent 16a2d93801
commit 23ff36d590
5 changed files with 55 additions and 22 deletions

View File

@ -20,6 +20,7 @@ namespace Components
Loader::Register(new Flags());
Loader::Register(new Singleton());
Loader::Register(new Exception()); // install our exception handler as early as posssible to get better debug dumps from startup crashes
Loader::Register(new Auth());
Loader::Register(new Bans());
@ -58,7 +59,6 @@ namespace Components
Loader::Register(new Changelog());
Loader::Register(new Dedicated());
Loader::Register(new Discovery());
Loader::Register(new Exception());
Loader::Register(new FastFiles());
Loader::Register(new FrameTime());
Loader::Register(new Gametypes());

View File

@ -24,27 +24,52 @@ namespace Components
return EXCEPTION_CONTINUE_EXECUTION;
}
const char* errorStr;
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
{
errorStr = "Termination because of a stack overflow.";
}
else
{
errorStr = Utils::String::VA("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
}
bool doFullDump = Flags::HasFlag("bigdumps") || Flags::HasFlag("reallybigdumps");
if (!doFullDump)
{
if (MessageBoxA(NULL,
Utils::String::VA("IW4x has encountered an exception and needs to close.\n"
"%s\n" // errorStr
"Would you like to create a full crash dump for the developers? (this can be almost 100mb)", errorStr),
"IW4x Error!", MB_YESNO | MB_ICONERROR) == IDYES)
{
doFullDump = true;
}
}
if (doFullDump)
{
Exception::SetMiniDumpType(true, false);
}
auto minidump = MinidumpUpload::CreateQueuedMinidump(ExceptionInfo, Exception::MiniDumpType);
if (!minidump)
{
MessageBoxA(NULL, "Minidump Error",
Utils::String::VA("There was an error creating the minidump (%s)! Hit OK to close the program.", Utils::GetLastWindowsError()), MB_OK | MB_ICONERROR);
OutputDebugStringA("Failed to create new minidump!");
Utils::OutputDebugLastError();
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
}
else
{
delete minidump;
}
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
if (ExceptionInfo->ExceptionRecord->ExceptionFlags == EXCEPTION_NONCONTINUABLE)
{
Logger::Error("Termination because of a stack overflow.\n");
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
}
else
{
Logger::Error("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
}
//TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
return EXCEPTION_CONTINUE_SEARCH;
}
@ -62,33 +87,29 @@ namespace Components
return SetUnhandledExceptionFilter(&Exception::ExceptionFilter);
}
void Exception::SetMiniDumpType()
void Exception::SetMiniDumpType(bool codeseg, bool dataseg)
{
Exception::MiniDumpType = MiniDumpIgnoreInaccessibleMemory;
Exception::MiniDumpType |= MiniDumpWithUnloadedModules;
Exception::MiniDumpType |= MiniDumpWithThreadInfo;
Exception::MiniDumpType |= MiniDumpWithFullMemoryInfo;
Exception::MiniDumpType |= MiniDumpWithHandleData;
Exception::MiniDumpType |= MiniDumpWithTokenInformation;
Exception::MiniDumpType |= MiniDumpScanMemory;
Exception::MiniDumpType |= MiniDumpWithProcessThreadData;
Exception::MiniDumpType |= MiniDumpWithFullAuxiliaryState;
Exception::MiniDumpType |= MiniDumpWithFullMemoryInfo;
Exception::MiniDumpType |= MiniDumpWithThreadInfo;
//Exception::MiniDumpType |= MiniDumpWithModuleHeaders;
if (Flags::HasFlag("bigminidumps"))
if (codeseg)
{
Exception::MiniDumpType |= MiniDumpWithModuleHeaders;
Exception::MiniDumpType |= MiniDumpWithCodeSegs;
}
else if (Flags::HasFlag("reallybigminidumps"))
if (dataseg)
{
Exception::MiniDumpType |= MiniDumpWithModuleHeaders;
Exception::MiniDumpType |= MiniDumpWithCodeSegs;
Exception::MiniDumpType |= MiniDumpWithDataSegs;
}
}
Exception::Exception()
{
Exception::SetMiniDumpType();
Exception::SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps"));
#ifdef DEBUG
// Display DEBUG branding, so we know we're on a debug build

View File

@ -14,7 +14,7 @@ namespace Components
static LPTOP_LEVEL_EXCEPTION_FILTER Hook();
static int MiniDumpType;
static void SetMiniDumpType();
static void SetMiniDumpType(bool codeseg, bool dataseg);
private:
static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo);

View File

@ -36,6 +36,17 @@ namespace Utils
LocalFree(messageBuffer);
}
std::string GetLastWindowsError()
{
DWORD errorMessageID = ::GetLastError();
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPSTR>(&messageBuffer), 0, nullptr);
std::string message(messageBuffer, size);
LocalFree(messageBuffer);
return message;
}
bool IsWineEnvironment()
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");

View File

@ -5,6 +5,7 @@ namespace Utils
std::string GetMimeType(std::string url);
std::string ParseChallenge(std::string data);
void OutputDebugLastError();
std::string GetLastWindowsError();
bool IsWineEnvironment();