[*] "Improve" win32 AuDebug

This commit is contained in:
Reece Wilson 2022-06-16 01:27:00 +01:00
parent 942373328c
commit 5aea27d56d
5 changed files with 120 additions and 61 deletions

View File

@ -258,14 +258,37 @@ namespace Aurora
struct FIOConfig
{
/// You can bypass branding by assigning an empty string to 'defaultBrand'
AuString defaultBrand = "Aurora";
AuString defaultBrand = "Aurora SDK Sample";
};
struct DebugConfig
{
/**
* @brief Precache/initialize symbols for printable stack traces under binaries not intended for shipping to consumers
*/
bool nonshipPrecachesSymbols {true};
/**
* @brief Activates the internal AddVectoredExceptionHandler handler. Might conflict with DRM and other debugging utilities
*/
bool enableWin32RootExceptionHandler {true};
/**
* @brief
*/
bool enableInjectedExceptionHandler {true};
/**
* @brief Causes a SysPanic
*/
bool isMemoryErrorFatal {false};
/**
* @brief
*/
bool isExceptionThrowFatal {false};
bool printExceptionStackTracesOut {true};
};
struct RuntimeStartInfo

View File

@ -237,14 +237,22 @@ extern "C" AUKN_SYM void __stdcall _ReportMSVCSEH(void *exception, const void *t
try
{
auto trace = AuDebug::GetStackTrace();
AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace,
[&](const AuString &str)
if (gRuntimeConfig.debug.printExceptionStackTracesOut)
{
AuLogWarn("Local MSVC Exception: 0x{:x}, {}", exception, str.c_str());
AuLogWarn("{}", StringifyStackTrace(trace));
});
AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace,
[&](const AuString &str)
{
AuLogWarn("Local MSVC Exception: 0x{:x}, {}", exception, str.c_str());
AuLogWarn("{}", StringifyStackTrace(trace));
});
}
else
{
AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace,
[&](const AuString &str) {});
}
}
catch (...)
{

View File

@ -106,26 +106,53 @@ namespace Aurora::Debug
return (info.Protect & (PAGE_READONLY | PAGE_READWRITE)) != 0;
}
bool InPanic();
static LONG CALLBACK HandleVectorException(_EXCEPTION_POINTERS *ExceptionInfo)
{
if (ExceptionInfo->ExceptionRecord->ExceptionCode == DBG_CONTROL_C)
{
Exit::PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigTerminate);
return Exit::gHasCanceled ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
return AuExchange(Exit::gHasCanceled, false) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
}
// https://www.youtube.com/embed/w6P03sTzSqM?start=2&autoplay=1
if (ExceptionInfo->ExceptionRecord->ExceptionCode < STATUS_GUARD_PAGE_VIOLATION)
{
return EXCEPTION_CONTINUE_SEARCH;
}
#if defined(AU_CFG_ID_SHIP)
// you what?
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
{
SysPanic("");
return EXCEPTION_CONTINUE_EXECUTION;
}
#else
// debugger go brrr
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
{
return EXCEPTION_CONTINUE_SEARCH;
}
auto minimal = gDebugLocked++;
#endif
// debug builds can go do something stupid
// QA builds, staging, rel in any form should just give up trying if we're under a panic
#if !defined(AU_CFG_ID_DEBUG)
if (InPanic())
{
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
// something dumb like this mess w hat i had before.
// gave up trying
auto minimal = gDebugLocked++;
if (minimal >= 5)
{
SysPanic("Nested Exception");
@ -177,7 +204,6 @@ namespace Aurora::Debug
StackTrace backtrace;
ParseStack(ExceptionInfo->ContextRecord, backtrace);
#if defined(_AU_USE_EXTENDED_FWD_FACING_DEBUGGING)
bool isInternal = true;
#else
@ -191,26 +217,29 @@ namespace Aurora::Debug
// Pre-submit callback -> its showtime
if ((isCritical || isInternal) && (minimal == 0))
{
AuLogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, str);
AuLogWarn("{}", StringifyStackTrace(backtrace));
if (gRuntimeConfig.debug.printExceptionStackTracesOut)
{
AuLogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, str);
AuLogWarn("{}", StringifyStackTrace(backtrace));
}
}
});
}
try
{
Grug::Arrow empty;
Grug::HurlRaiseProblematicEvent(&empty);
if (isCritical)
{
Telemetry::Mayday();
}
if (isCritical)
if (isCritical || gRuntimeConfig.debug.isExceptionThrowFatal) // exception = literally anything
{
PlatformHandleFatal(true);
}
Grug::Arrow empty;
Grug::HurlRaiseProblematicEvent(&empty);
}
catch (...)
{
@ -314,15 +343,13 @@ namespace Aurora::Debug
{
AuString path;
HANDLE hFile;
std::wstring wpath;
AuString utf8Path;
MINIDUMP_EXCEPTION_INFORMATION info;
auto ok = AuIOFS::GetProfileDomain(path);
auto ok = AuIOFS::GetProfileDomain(path); // < could throw inside
if (!ok)
{
AuLogWarn("Couldn't find minidump directory");
goto miniMiniDumpOut;
path = ".\\";
}
info.ClientPointers = true;
@ -336,22 +363,22 @@ namespace Aurora::Debug
MiniDumpWithThreadInfo;
while (wpath.empty())
{
try
{
utf8Path = path + "Crashes/" + GetDumpName();
wpath = Locale::ConvertFromUTF8(utf8Path);
}
catch (...)
{
static std::wstring pathStorage(8192, L' ');
}
}
int index {};
AuIOFS::CreateDirectories(utf8Path, true);
index += MultiByteToWideChar(CP_UTF8, 0, path.c_str(), path.length(), pathStorage.data() + index, pathStorage.size() - index);
static const std::string crashesSlash = "Crashes\\";
index += MultiByteToWideChar(CP_UTF8, 0, crashesSlash.c_str(), crashesSlash.length(), pathStorage.data() + index, pathStorage.size() - index);
hFile = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
auto dumpName = GetDumpName();;
index += MultiByteToWideChar(CP_UTF8, 0, dumpName.c_str(), dumpName.length(), pathStorage.data() + index, pathStorage.size() - index);
pathStorage.resize(index);
AuIOFS::CreateDirectories(utf8Path, true); // potentially unsafe / could throw inside
hFile = CreateFileW(pathStorage.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile != INVALID_HANDLE_VALUE)
{
AuLogWarn("[1] Couldn't open minidump file. Has a debugger locked the .dmp file?");
@ -370,7 +397,7 @@ namespace Aurora::Debug
miniMiniDumpOut:
Telemetry::NewBlackBoxEntryMinidump report {};
report.includesRx = false;
report.resource.path = path;
report.resource.path = dumpName; // <COPY
report.resource.type = Telemetry::ENewBlackBoxResourceType::eLocal;
Telemetry::ReportDyingBreath(report);
@ -382,7 +409,7 @@ namespace Aurora::Debug
static void CacheInternalBuildSymbols()
{
#if defined(DEBUG) || defined(STAGING)
#if defined(AU_CFG_ID_INTERNAL) || defined(AU_CFG_ID_DEBUG)
SymInitialize(GetCurrentProcess(), NULL, TRUE);
#endif
}
@ -418,6 +445,9 @@ namespace Aurora::Debug
DisableWindowsErrorReporting();
// ..
AddVectoredExceptionHandler(1, HandleVectorException);
if (gRuntimeConfig.debug.enableWin32RootExceptionHandler)
{
AddVectoredExceptionHandler(1, HandleVectorException);
}
}
}

View File

@ -14,12 +14,13 @@
namespace Aurora::Debug
{
void PlatformHandleFatal();
static bool gHandlingFatal = false;
AUKN_SYM void DebugBreak()
{
#if defined(DEBUG) || defined(STAGING)
#if defined(AU_CFG_ID_INTERNAL) || defined(AU_CFG_ID_DEBUG)
#if defined(AURORA_PLATFORM_WIN32)
#if defined(STAGING)
#if defined(AU_CFG_ID_INTERNAL)
if (IsDebuggerPresent())
#endif
{
@ -38,35 +39,27 @@ namespace Aurora::Debug
#endif
}
bool InPanic()
{
return gHandlingFatal;
}
AUKN_SYM void Panic()
{
//
static bool handlingFatal = false;
if (AuExchange(handlingFatal, true))
if (gHandlingFatal)
{
goto failFast;
}
#if defined(AU_CFG_ID_DEBUG)
DebugBreak();
#endif
try
if (AuExchange(gHandlingFatal, true))
{
CheckErrors();
goto failFast;
}
catch (...)
{
}
try
{
Grug::GrugFlushFlushs();
}
catch (...)
{
}
try
{
@ -78,20 +71,21 @@ namespace Aurora::Debug
}
static bool panicSingleshot = false;
if (AuExchange(panicSingleshot, true))
failFast:
static bool runPlatformFastFailOnce {};
if (!AuExchange(runPlatformFastFailOnce, true))
{
try
{
Telemetry::Mayday();
Debug::PlatformHandleFatal(true);
}
catch (...)
{
}
}
failFast:
#if defined(AURORA_IS_MODERNNT_DERIVED)
__fastfail('FCKD');
#else

View File

@ -7,3 +7,7 @@
***/
#pragma once
namespace Aurora::Debug
{
bool InPanic();
}