[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:
parent
16a2d93801
commit
23ff36d590
@ -20,6 +20,7 @@ namespace Components
|
|||||||
|
|
||||||
Loader::Register(new Flags());
|
Loader::Register(new Flags());
|
||||||
Loader::Register(new Singleton());
|
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 Auth());
|
||||||
Loader::Register(new Bans());
|
Loader::Register(new Bans());
|
||||||
@ -58,7 +59,6 @@ namespace Components
|
|||||||
Loader::Register(new Changelog());
|
Loader::Register(new Changelog());
|
||||||
Loader::Register(new Dedicated());
|
Loader::Register(new Dedicated());
|
||||||
Loader::Register(new Discovery());
|
Loader::Register(new Discovery());
|
||||||
Loader::Register(new Exception());
|
|
||||||
Loader::Register(new FastFiles());
|
Loader::Register(new FastFiles());
|
||||||
Loader::Register(new FrameTime());
|
Loader::Register(new FrameTime());
|
||||||
Loader::Register(new Gametypes());
|
Loader::Register(new Gametypes());
|
||||||
|
@ -24,27 +24,52 @@ namespace Components
|
|||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
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);
|
auto minidump = MinidumpUpload::CreateQueuedMinidump(ExceptionInfo, Exception::MiniDumpType);
|
||||||
if (!minidump)
|
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!");
|
OutputDebugStringA("Failed to create new minidump!");
|
||||||
Utils::OutputDebugLastError();
|
Utils::OutputDebugLastError();
|
||||||
|
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete minidump;
|
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;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
@ -62,33 +87,29 @@ namespace Components
|
|||||||
return SetUnhandledExceptionFilter(&Exception::ExceptionFilter);
|
return SetUnhandledExceptionFilter(&Exception::ExceptionFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Exception::SetMiniDumpType()
|
void Exception::SetMiniDumpType(bool codeseg, bool dataseg)
|
||||||
{
|
{
|
||||||
Exception::MiniDumpType = MiniDumpIgnoreInaccessibleMemory;
|
Exception::MiniDumpType = MiniDumpIgnoreInaccessibleMemory;
|
||||||
Exception::MiniDumpType |= MiniDumpWithUnloadedModules;
|
|
||||||
Exception::MiniDumpType |= MiniDumpWithThreadInfo;
|
|
||||||
Exception::MiniDumpType |= MiniDumpWithFullMemoryInfo;
|
|
||||||
Exception::MiniDumpType |= MiniDumpWithHandleData;
|
Exception::MiniDumpType |= MiniDumpWithHandleData;
|
||||||
Exception::MiniDumpType |= MiniDumpWithTokenInformation;
|
Exception::MiniDumpType |= MiniDumpScanMemory;
|
||||||
Exception::MiniDumpType |= MiniDumpWithProcessThreadData;
|
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;
|
Exception::MiniDumpType |= MiniDumpWithCodeSegs;
|
||||||
}
|
}
|
||||||
else if (Flags::HasFlag("reallybigminidumps"))
|
if (dataseg)
|
||||||
{
|
{
|
||||||
Exception::MiniDumpType |= MiniDumpWithModuleHeaders;
|
|
||||||
Exception::MiniDumpType |= MiniDumpWithCodeSegs;
|
|
||||||
Exception::MiniDumpType |= MiniDumpWithDataSegs;
|
Exception::MiniDumpType |= MiniDumpWithDataSegs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Exception::Exception()
|
Exception::Exception()
|
||||||
{
|
{
|
||||||
Exception::SetMiniDumpType();
|
Exception::SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps"));
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Display DEBUG branding, so we know we're on a debug build
|
// Display DEBUG branding, so we know we're on a debug build
|
||||||
|
@ -14,7 +14,7 @@ namespace Components
|
|||||||
static LPTOP_LEVEL_EXCEPTION_FILTER Hook();
|
static LPTOP_LEVEL_EXCEPTION_FILTER Hook();
|
||||||
|
|
||||||
static int MiniDumpType;
|
static int MiniDumpType;
|
||||||
static void SetMiniDumpType();
|
static void SetMiniDumpType(bool codeseg, bool dataseg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo);
|
static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo);
|
||||||
|
@ -36,6 +36,17 @@ namespace Utils
|
|||||||
LocalFree(messageBuffer);
|
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()
|
bool IsWineEnvironment()
|
||||||
{
|
{
|
||||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||||
|
@ -5,6 +5,7 @@ namespace Utils
|
|||||||
std::string GetMimeType(std::string url);
|
std::string GetMimeType(std::string url);
|
||||||
std::string ParseChallenge(std::string data);
|
std::string ParseChallenge(std::string data);
|
||||||
void OutputDebugLastError();
|
void OutputDebugLastError();
|
||||||
|
std::string GetLastWindowsError();
|
||||||
|
|
||||||
bool IsWineEnvironment();
|
bool IsWineEnvironment();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user