[*] "Improve" win32 AuDebug
This commit is contained in:
parent
942373328c
commit
5aea27d56d
@ -258,14 +258,37 @@ namespace Aurora
|
|||||||
struct FIOConfig
|
struct FIOConfig
|
||||||
{
|
{
|
||||||
/// You can bypass branding by assigning an empty string to 'defaultBrand'
|
/// You can bypass branding by assigning an empty string to 'defaultBrand'
|
||||||
AuString defaultBrand = "Aurora";
|
AuString defaultBrand = "Aurora SDK Sample";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DebugConfig
|
struct DebugConfig
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief Precache/initialize symbols for printable stack traces under binaries not intended for shipping to consumers
|
||||||
|
*/
|
||||||
bool nonshipPrecachesSymbols {true};
|
bool nonshipPrecachesSymbols {true};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Activates the internal AddVectoredExceptionHandler handler. Might conflict with DRM and other debugging utilities
|
||||||
|
*/
|
||||||
bool enableWin32RootExceptionHandler {true};
|
bool enableWin32RootExceptionHandler {true};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
bool enableInjectedExceptionHandler {true};
|
bool enableInjectedExceptionHandler {true};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Causes a SysPanic
|
||||||
|
*/
|
||||||
|
bool isMemoryErrorFatal {false};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
bool isExceptionThrowFatal {false};
|
||||||
|
|
||||||
|
bool printExceptionStackTracesOut {true};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RuntimeStartInfo
|
struct RuntimeStartInfo
|
||||||
|
@ -237,8 +237,10 @@ extern "C" AUKN_SYM void __stdcall _ReportMSVCSEH(void *exception, const void *t
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
auto trace = AuDebug::GetStackTrace();
|
auto trace = AuDebug::GetStackTrace();
|
||||||
|
|
||||||
|
if (gRuntimeConfig.debug.printExceptionStackTracesOut)
|
||||||
|
{
|
||||||
AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace,
|
AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace,
|
||||||
[&](const AuString &str)
|
[&](const AuString &str)
|
||||||
{
|
{
|
||||||
@ -246,6 +248,12 @@ extern "C" AUKN_SYM void __stdcall _ReportMSVCSEH(void *exception, const void *t
|
|||||||
AuLogWarn("{}", StringifyStackTrace(trace));
|
AuLogWarn("{}", StringifyStackTrace(trace));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace,
|
||||||
|
[&](const AuString &str) {});
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -106,26 +106,53 @@ namespace Aurora::Debug
|
|||||||
return (info.Protect & (PAGE_READONLY | PAGE_READWRITE)) != 0;
|
return (info.Protect & (PAGE_READONLY | PAGE_READWRITE)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InPanic();
|
||||||
|
|
||||||
static LONG CALLBACK HandleVectorException(_EXCEPTION_POINTERS *ExceptionInfo)
|
static LONG CALLBACK HandleVectorException(_EXCEPTION_POINTERS *ExceptionInfo)
|
||||||
{
|
{
|
||||||
if (ExceptionInfo->ExceptionRecord->ExceptionCode == DBG_CONTROL_C)
|
if (ExceptionInfo->ExceptionRecord->ExceptionCode == DBG_CONTROL_C)
|
||||||
{
|
{
|
||||||
Exit::PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigTerminate);
|
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)
|
if (ExceptionInfo->ExceptionRecord->ExceptionCode < STATUS_GUARD_PAGE_VIOLATION)
|
||||||
{
|
{
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
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)
|
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||||
{
|
{
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
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)
|
if (minimal >= 5)
|
||||||
{
|
{
|
||||||
SysPanic("Nested Exception");
|
SysPanic("Nested Exception");
|
||||||
@ -177,7 +204,6 @@ namespace Aurora::Debug
|
|||||||
StackTrace backtrace;
|
StackTrace backtrace;
|
||||||
ParseStack(ExceptionInfo->ContextRecord, backtrace);
|
ParseStack(ExceptionInfo->ContextRecord, backtrace);
|
||||||
|
|
||||||
|
|
||||||
#if defined(_AU_USE_EXTENDED_FWD_FACING_DEBUGGING)
|
#if defined(_AU_USE_EXTENDED_FWD_FACING_DEBUGGING)
|
||||||
bool isInternal = true;
|
bool isInternal = true;
|
||||||
#else
|
#else
|
||||||
@ -190,27 +216,30 @@ namespace Aurora::Debug
|
|||||||
{
|
{
|
||||||
// Pre-submit callback -> its showtime
|
// Pre-submit callback -> its showtime
|
||||||
if ((isCritical || isInternal) && (minimal == 0))
|
if ((isCritical || isInternal) && (minimal == 0))
|
||||||
|
{
|
||||||
|
if (gRuntimeConfig.debug.printExceptionStackTracesOut)
|
||||||
{
|
{
|
||||||
AuLogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, str);
|
AuLogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, str);
|
||||||
AuLogWarn("{}", StringifyStackTrace(backtrace));
|
AuLogWarn("{}", StringifyStackTrace(backtrace));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Grug::Arrow empty;
|
||||||
|
Grug::HurlRaiseProblematicEvent(&empty);
|
||||||
|
|
||||||
if (isCritical)
|
if (isCritical)
|
||||||
{
|
{
|
||||||
Telemetry::Mayday();
|
Telemetry::Mayday();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCritical)
|
if (isCritical || gRuntimeConfig.debug.isExceptionThrowFatal) // exception = literally anything
|
||||||
{
|
{
|
||||||
PlatformHandleFatal(true);
|
PlatformHandleFatal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Grug::Arrow empty;
|
|
||||||
Grug::HurlRaiseProblematicEvent(&empty);
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
@ -314,15 +343,13 @@ namespace Aurora::Debug
|
|||||||
{
|
{
|
||||||
AuString path;
|
AuString path;
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
std::wstring wpath;
|
|
||||||
AuString utf8Path;
|
AuString utf8Path;
|
||||||
MINIDUMP_EXCEPTION_INFORMATION info;
|
MINIDUMP_EXCEPTION_INFORMATION info;
|
||||||
|
|
||||||
auto ok = AuIOFS::GetProfileDomain(path);
|
auto ok = AuIOFS::GetProfileDomain(path); // < could throw inside
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
AuLogWarn("Couldn't find minidump directory");
|
path = ".\\";
|
||||||
goto miniMiniDumpOut;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
info.ClientPointers = true;
|
info.ClientPointers = true;
|
||||||
@ -336,22 +363,22 @@ namespace Aurora::Debug
|
|||||||
MiniDumpWithThreadInfo;
|
MiniDumpWithThreadInfo;
|
||||||
|
|
||||||
|
|
||||||
while (wpath.empty())
|
static std::wstring pathStorage(8192, L' ');
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
utf8Path = path + "Crashes/" + GetDumpName();
|
|
||||||
wpath = Locale::ConvertFromUTF8(utf8Path);
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
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)
|
if (hFile != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
AuLogWarn("[1] Couldn't open minidump file. Has a debugger locked the .dmp file?");
|
AuLogWarn("[1] Couldn't open minidump file. Has a debugger locked the .dmp file?");
|
||||||
@ -370,7 +397,7 @@ namespace Aurora::Debug
|
|||||||
miniMiniDumpOut:
|
miniMiniDumpOut:
|
||||||
Telemetry::NewBlackBoxEntryMinidump report {};
|
Telemetry::NewBlackBoxEntryMinidump report {};
|
||||||
report.includesRx = false;
|
report.includesRx = false;
|
||||||
report.resource.path = path;
|
report.resource.path = dumpName; // <COPY
|
||||||
report.resource.type = Telemetry::ENewBlackBoxResourceType::eLocal;
|
report.resource.type = Telemetry::ENewBlackBoxResourceType::eLocal;
|
||||||
Telemetry::ReportDyingBreath(report);
|
Telemetry::ReportDyingBreath(report);
|
||||||
|
|
||||||
@ -382,7 +409,7 @@ namespace Aurora::Debug
|
|||||||
|
|
||||||
static void CacheInternalBuildSymbols()
|
static void CacheInternalBuildSymbols()
|
||||||
{
|
{
|
||||||
#if defined(DEBUG) || defined(STAGING)
|
#if defined(AU_CFG_ID_INTERNAL) || defined(AU_CFG_ID_DEBUG)
|
||||||
SymInitialize(GetCurrentProcess(), NULL, TRUE);
|
SymInitialize(GetCurrentProcess(), NULL, TRUE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -418,6 +445,9 @@ namespace Aurora::Debug
|
|||||||
DisableWindowsErrorReporting();
|
DisableWindowsErrorReporting();
|
||||||
|
|
||||||
// ..
|
// ..
|
||||||
|
if (gRuntimeConfig.debug.enableWin32RootExceptionHandler)
|
||||||
|
{
|
||||||
AddVectoredExceptionHandler(1, HandleVectorException);
|
AddVectoredExceptionHandler(1, HandleVectorException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
@ -14,12 +14,13 @@
|
|||||||
namespace Aurora::Debug
|
namespace Aurora::Debug
|
||||||
{
|
{
|
||||||
void PlatformHandleFatal();
|
void PlatformHandleFatal();
|
||||||
|
static bool gHandlingFatal = false;
|
||||||
|
|
||||||
AUKN_SYM void DebugBreak()
|
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(AURORA_PLATFORM_WIN32)
|
||||||
#if defined(STAGING)
|
#if defined(AU_CFG_ID_INTERNAL)
|
||||||
if (IsDebuggerPresent())
|
if (IsDebuggerPresent())
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -38,35 +39,27 @@ namespace Aurora::Debug
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InPanic()
|
||||||
|
{
|
||||||
|
return gHandlingFatal;
|
||||||
|
}
|
||||||
|
|
||||||
AUKN_SYM void Panic()
|
AUKN_SYM void Panic()
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
static bool handlingFatal = false;
|
if (gHandlingFatal)
|
||||||
if (AuExchange(handlingFatal, true))
|
|
||||||
{
|
{
|
||||||
goto failFast;
|
goto failFast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(AU_CFG_ID_DEBUG)
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
|
#endif
|
||||||
|
|
||||||
try
|
if (AuExchange(gHandlingFatal, true))
|
||||||
{
|
{
|
||||||
CheckErrors();
|
goto failFast;
|
||||||
}
|
}
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Grug::GrugFlushFlushs();
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -78,12 +71,14 @@ namespace Aurora::Debug
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool panicSingleshot = false;
|
failFast:
|
||||||
if (AuExchange(panicSingleshot, true))
|
|
||||||
|
static bool runPlatformFastFailOnce {};
|
||||||
|
if (!AuExchange(runPlatformFastFailOnce, true))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Telemetry::Mayday();
|
Debug::PlatformHandleFatal(true);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
@ -91,7 +86,6 @@ namespace Aurora::Debug
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failFast:
|
|
||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
__fastfail('FCKD');
|
__fastfail('FCKD');
|
||||||
#else
|
#else
|
||||||
|
@ -7,3 +7,7 @@
|
|||||||
***/
|
***/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
namespace Aurora::Debug
|
||||||
|
{
|
||||||
|
bool InPanic();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user