[+] AuDebug::ErrorStack / AuErrorStack

[+] Begin stubbing out memory crunch apis
[*] Fixed MT consoletty missed flushes
This commit is contained in:
Reece Wilson 2022-11-30 11:11:18 +00:00
parent 72dc0d715e
commit 89d341b4fc
13 changed files with 384 additions and 5 deletions

View File

@ -81,8 +81,30 @@ namespace Aurora::Debug
AUKN_SYM AuResult<AuString> DemangleName(const AuString &pName);
AUKN_SYM void DebugBreak();
AUKN_SYM void AddMemoryCrunch();
AUKN_SYM void DecMemoryCrunch();
}
#include "SysPanic.hpp"
#include "SysAssertions.hpp"
#include "SysErrors.hpp"
#include "SysErrors.hpp"
#include "ErrorStack.hpp"
struct AuDbgStringSharedException : AuStringException
{
inline AuDbgStringSharedException(AuSPtr<AuString> pStr) noexcept :
AuStringException(pStr->c_str()),
pStr(pStr)
{
}
AuSPtr<AuString> pStr;
};
#if defined(AU_THROW_STRING)
#undef AU_THROW_STRING
#endif
#define AU_THROW_STRING(var) do { Aurora::Debug::AddMemoryCrunch(); auto pStr = AuMakeSharedPanic<AuString>(var); Aurora::Debug::DecMemoryCrunch(); throw AuDbgStringSharedException(pStr); } while (0)
#define AU_THROW_FORMATTED(var, ...) do { Aurora::Debug::AddMemoryCrunch(); auto pStr = AuMakeSharedPanic<AuString>(fmt::format(var, ##__VA_ARGS__)); Aurora::Debug::DecMemoryCrunch(); throw AuDbgStringSharedException(pStr); } while (0)

View File

@ -0,0 +1,86 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ErrorStack.hpp
Date: 2022-11-29
Author: Reece
***/
#pragma once
namespace Aurora::Debug
{
struct ErrorStack;
AUKN_SYM void PushStack(ErrorStack *pStack);
AUKN_SYM void PopStack(ErrorStack *pStack);
struct ErrorStackAccessor;
struct ThreadMessage
{
AuSPtr<ThreadMessage> pNextThreadMesage;
AuSPtr<AuString> pStringMessage;
AuOptional<EFailureCategory> eFailureCategory;
AuOptional<StackTrace> optStackTrace;
AuOptional<AuUInt> optOsErrorCode;
AUKN_SYM AuString ToString();
};
struct ErrorStack
{
inline ErrorStack()
{
PushStack(this);
}
inline ~ErrorStack()
{
PopStack(this);
}
inline bool HasCaptured()
{
CheckErrors();
return bool(this->pHead);
}
inline bool HasMultipleOccurred()
{
return this->HasCaptured() && bool(this->pHead->pNextThreadMesage);
}
inline StackTrace *ToStackTrace()
{
if (!this->HasCaptured())
{
return {};
}
if (!this->pHead->optStackTrace)
{
return {};
}
return &this->pHead->optStackTrace.value();
}
inline AuOptional<AuString> ToString()
{
return this->HasCaptured() ? this->pHead->ToString() : AuString {};
}
inline AuSPtr<ThreadMessage> FirstMessage()
{
return this->pHead;
}
protected:
AuSPtr<ThreadMessage> pHead;
ErrorStack *pNext {};
friend ErrorStackAccessor;
};
}
using AuErrorStack = Aurora::Debug::ErrorStack;

View File

@ -113,8 +113,8 @@ namespace Aurora::Debug
#define SysCheckReturn(x, ...) if (!(static_cast<bool>(x))) { Aurora::Debug::ErrorMakeNested(); return __VA_ARGS__; }
#define SysPushErrorError(error, ...) Aurora::Debug::SysPushError(Aurora::Debug::error, ## __VA_ARGS__)
#define SysPushUserError(exp, ...) Aurora::Debug::SysPushError((Aurora::Debug::EFailureCategory)exp, ## __VA_ARGS__)
#define SysPushErrorError(error, ...) do { Aurora::Debug::AddMemoryCrunch(); Aurora::Debug::SysPushError(Aurora::Debug::error, ## __VA_ARGS__) ;Aurora::Debug::DecMemoryCrunch(); } while (0)
#define SysPushUserError(exp, ...) do { Aurora::Debug::AddMemoryCrunch(); Aurora::Debug::SysPushError((Aurora::Debug::EFailureCategory)exp, ## __VA_ARGS__) ;Aurora::Debug::DecMemoryCrunch(); } while (0)
// legacy
#define SysPushErrorArg(...) SysPushErrorError(kFailureParam, ## __VA_ARGS__)

View File

@ -11,7 +11,15 @@
template<typename ... T>
static inline void AU_NORETURN SysPanic(T... args)
{
Aurora::Logging::WriteLinef(static_cast<AuUInt8>(Aurora::Logging::ELogLevel::eError), Aurora::Console::EAnsiColor::eBoldRed, "Fatal", AuForward<T>(args)...);
Aurora::Debug::AddMemoryCrunch();
try
{
Aurora::Logging::WriteLinef(static_cast<AuUInt8>(Aurora::Logging::ELogLevel::eError), Aurora::Console::EAnsiColor::eBoldRed, "Fatal", AuForward<T>(args)...);
}
catch (...)
{
}
Aurora::Debug::Panic();
}
#endif

View File

@ -154,6 +154,7 @@ namespace Aurora
AUKN_SYM void RuntimeShutdown()
{
RuntimeSysPump();
gRuntimeHasStarted = false;
Deinit();
}

View File

@ -119,6 +119,14 @@ namespace Aurora::Console
void Exit()
{
try
{
ConsoleTTY::PumpForce();
}
catch (...)
{
}
gDefaultSinks.clear();
gDefaultLogger.reset();
Logging::DeinitLoggers();

View File

@ -2069,6 +2069,11 @@ namespace Aurora::Console::ConsoleTTY
}
}
void PumpForce()
{
gTTYConsole.Pump();
}
AUKN_SYM AuSPtr<ITTYConsole> GetTTYConsole()
{
return AuUnsafeRaiiToShared<ITTYConsole>(&gTTYConsole);
@ -2094,6 +2099,11 @@ namespace Aurora::Console::ConsoleTTY
}
void PumpForce()
{
}
void Exit()
{

View File

@ -268,4 +268,5 @@ namespace Aurora::Console::ConsoleTTY
void OnEnter();
void WriteTTYOut(const AuConsole::ConsoleMessage &msg);
AUKN_SYM AuSPtr<ITTYConsole> GetTTYConsole();
void PumpForce();
}

View File

@ -19,6 +19,8 @@
#include "Stack.Unix.hpp"
#endif
#include "ErrorStack.hpp"
namespace Aurora::Debug
{
static thread_local AuUInt32 tlsLastBackTrace = 0xFFFFFFFF;
@ -310,6 +312,21 @@ namespace Aurora::Debug
tlsCategory = category;
try
{
if (ShouldPushErrorStackInternal())
{
auto pMessage = AuMakeSharedThrow<ThreadMessage>();
pMessage->pStringMessage = AuMakeSharedThrow<AuString>(msg);
pMessage->eFailureCategory = category;
PushErrorStackInternal(pMessage);
}
}
catch (...)
{
}
// Cry about it to telemetry with other errors if available
AuUInt32 rng = GetFenceId();
Telemetry::BeginBlock();
@ -333,7 +350,7 @@ namespace Aurora::Debug
{
return;
}
// Print to console if internal
#if defined(DEBUG) || defined(STAGING)
PrintError();
@ -345,6 +362,7 @@ namespace Aurora::Debug
AUKN_SYM AuString StackTraceEntry::Stringify() const
{
AddMemoryCrunch();
const auto frame = *this;
AuString backTraceBuffer;
@ -390,16 +408,19 @@ namespace Aurora::Debug
backTraceBuffer += "\t\t[proprietary]\n";
}
DecMemoryCrunch();
return backTraceBuffer;
}
catch (...)
{
DecMemoryCrunch();
return {};
}
}
AUKN_SYM AuString StringifyStackTrace(const StackTrace &backtrace)
{
AddMemoryCrunch();
AuString backTraceBuffer;
try
@ -414,10 +435,12 @@ namespace Aurora::Debug
backTraceBuffer += frame.Stringify();
}
DecMemoryCrunch();
return backTraceBuffer;
}
catch (...)
{
DecMemoryCrunch();
return {};
}
}
@ -432,4 +455,14 @@ namespace Aurora::Debug
InitNT();
#endif
}
AUKN_SYM void AddMemoryCrunch()
{
// TODO: ...
}
AUKN_SYM void DecMemoryCrunch()
{
// TODO: ...
}
}

156
Source/Debug/ErrorStack.cpp Normal file
View File

@ -0,0 +1,156 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ErrorStack.cpp
Date: 2022-11-29
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "Debug.hpp"
#include "ErrorStack.hpp"
namespace Aurora::Debug
{
struct ErrorStackAccessor
{
void SetNext(ErrorStack *pStack, ErrorStack *pNext)
{
pStack->pNext = pNext;
}
ErrorStack *GetNext(ErrorStack *pStack)
{
return pStack->pNext;
}
void SetHead(ErrorStack *pStack, AuSPtr<ThreadMessage> pHead)
{
pStack->pHead = pHead;
}
AuSPtr<ThreadMessage> GetHead(ErrorStack *pStack)
{
return pStack->pHead;
}
};
AUKN_SYM AuString ThreadMessage::ToString()
{
if (this->pStringMessage)
{
return *this->pStringMessage;
}
if (eFailureCategory)
{
return fmt::format("Debug::EFailureCategory = {}", (AuUInt)*eFailureCategory);
}
if (optOsErrorCode)
{
return fmt::format("OS = {}", (AuUInt)*optOsErrorCode);
}
return "Unknown error.";
}
static thread_local ErrorStack *tlsErrorStackBase;
AUKN_SYM void PushStack(ErrorStack *pStack)
{
if (!tlsErrorStackBase)
{
tlsErrorStackBase = pStack;
return;
}
ErrorStackAccessor dumb;
auto itr = tlsErrorStackBase;
while (auto pNext = dumb.GetNext(itr))
{
itr = pNext;
}
dumb.SetNext(itr, pStack);
}
AUKN_SYM void PopStack(ErrorStack *pStack)
{
if (!tlsErrorStackBase)
{
return;
}
ErrorStackAccessor dumb;
auto itr = tlsErrorStackBase;
if (itr == pStack)
{
tlsErrorStackBase = nullptr;
return;
}
while (auto pNext = dumb.GetNext(itr))
{
if (pNext == pStack)
{
dumb.SetNext(pStack, {});
return;
}
itr = pNext;
}
}
static void AddToInstance(ErrorStack *pStack, AuSPtr<ThreadMessage> pMessage)
{
ErrorStackAccessor dumb;
if (!dumb.GetHead(pStack))
{
dumb.SetHead(pStack, pMessage);
return;
}
AuSPtr<ThreadMessage> pMessage2 { dumb.GetHead(pStack) };
if (pMessage2 == pMessage)
{
return;
}
while (auto pNext = pMessage2->pNextThreadMesage)
{
if (pNext == pMessage)
{
return;
}
pMessage2 = pNext;
}
pMessage2->pNextThreadMesage = pMessage;
}
//////////////////////////////////////////////////////////////////
// internal api:
bool ShouldPushErrorStackInternal()
{
return bool(tlsErrorStackBase);
}
void PushErrorStackInternal(AuSPtr<ThreadMessage> pMessage)
{
ErrorStackAccessor dumb;
auto itr = tlsErrorStackBase;
if (itr)
{
AddToInstance(itr, pMessage);
while (auto pNext = dumb.GetNext(itr))
{
AddToInstance(itr, pMessage);
itr = pNext;
}
}
}
}

View File

@ -0,0 +1,14 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ErrorStack.hpp
Date: 2022-11-29
Author: Reece
***/
#pragma once
namespace Aurora::Debug
{
void PushErrorStackInternal(AuSPtr<ThreadMessage> pMessage);
bool ShouldPushErrorStackInternal();
}

View File

@ -18,6 +18,7 @@
#include <Source/Telemetry/Telemetry.hpp>
#include <Source/Grug/AuGrug.hpp>
#include <Source/Exit/AuExit.hpp>
#include "ErrorStack.hpp"
namespace Aurora::Debug
{
@ -135,6 +136,24 @@ namespace Aurora::Debug
}
try
{
auto pStr = AuMakeSharedThrow<AuString>(message);
// auto pTrace = AuMakeSharedThrow<StackTrace>(trace);
if (ShouldPushErrorStackInternal())
{
auto pMessage = AuMakeSharedThrow<ThreadMessage>();
pMessage->optStackTrace = trace;
pMessage->pStringMessage = pStr;
PushErrorStackInternal(pMessage);
}
}
catch (...)
{
}
return message;
}

View File

@ -10,6 +10,8 @@
#include "Panic.hpp"
//#include <intrin.h>
#include <Source/Grug/AuGrug.hpp>
#include <Source/Console/ConsoleTTY/ConsoleTTY.hpp>
#include <Source/Console/Console.hpp>
namespace Aurora::Debug
{
@ -64,6 +66,15 @@ namespace Aurora::Debug
goto failFast;
}
try
{
Console::ConsoleTTY::PumpForce();
}
catch (...)
{
}
try
{
Grug::GrugFlushFlushs();
@ -76,6 +87,16 @@ namespace Aurora::Debug
failFast:
try
{
Console::Pump();
}
catch (...)
{
}
static bool runPlatformFastFailOnce {};
if (!AuExchange(runPlatformFastFailOnce, true))
{