[*] Harden exit

This commit is contained in:
Reece Wilson 2022-04-02 01:48:29 +01:00
parent fb5eb02594
commit 5599da3ab0
9 changed files with 121 additions and 27 deletions

View File

@ -96,6 +96,7 @@ namespace AuTypes = Aurora::Types;
namespace AuLog = Aurora::Logging;
namespace AuMemory = Aurora::Memory;
namespace AuLoop = Aurora::Loop;
namespace AuExit = Aurora::Exit;
using AuWorkerId_t = AuAsync::WorkerId_t;
using AuWorkerPId_t = AuAsync::WorkerPId_t;

View File

@ -9,6 +9,8 @@
namespace Aurora::Threading::Threads
{
AUKN_SYM bool DeadTest();
template<typename T, bool isStatic = false>
class TLSVariable
{
@ -21,6 +23,10 @@ namespace Aurora::Threading::Threads
{
if constexpr (!isStatic)
{
if (DeadTest())
{
return;
}
GetThread()->GetTlsView()->Remove(GetHandle());
}
}

View File

@ -26,6 +26,7 @@ namespace Aurora::Async
void ReleaseApp()
{
gAsyncAppMem->Shutdown();
gAsyncAppMem.reset();
}

View File

@ -60,7 +60,8 @@ namespace Aurora::Debug
EXCEPTION_ENTRY(EXCEPTION_GUARD_PAGE),
EXCEPTION_ENTRY(EXCEPTION_INVALID_HANDLE),
//EXCEPTION_ENTRY(EXCEPTION_POSSIBLE_DEADLOCK),
EXCEPTION_ENTRY(CONTROL_C_EXIT)
EXCEPTION_ENTRY(CONTROL_C_EXIT),
EXCEPTION_ENTRY(DBG_CONTROL_C)
};
#undef EXCEPTION_ENTRY
#define EXCEPTION_ENTRY(n) {n, true}
@ -107,6 +108,12 @@ namespace Aurora::Debug
static LONG CALLBACK HandleVectorException(_EXCEPTION_POINTERS *ExceptionInfo)
{
if (ExceptionInfo->ExceptionRecord->ExceptionCode == DBG_CONTROL_C)
{
Exit::PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigTerminate);
return EXCEPTION_CONTINUE_SEARCH;
}
if (ExceptionInfo->ExceptionRecord->ExceptionCode < STATUS_GUARD_PAGE_VIOLATION)
{
return EXCEPTION_CONTINUE_SEARCH;
@ -117,12 +124,6 @@ namespace Aurora::Debug
return EXCEPTION_CONTINUE_SEARCH;
}
if (ExceptionInfo->ExceptionRecord->ExceptionCode == CONTROL_C_EXIT)
{
Exit::PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigTerminate);
return EXCEPTION_CONTINUE_SEARCH;
}
auto minimal = gDebugLocked++;
if (minimal >= 5)

View File

@ -40,6 +40,11 @@ namespace Aurora::Exit
void PostLevel(AuThreads::IAuroraThread *thread, ETriggerLevel level)
{
if (!gIsAppRunning)
{
return;
}
AU_LOCK_GUARD(gMutex);
bool isTerminate = level == ETriggerLevel::eSafeTermination;
@ -57,6 +62,18 @@ namespace Aurora::Exit
gIsAppRunning = false;
}
static AuUInt32 gProblemCounter = {};
if (level == ETriggerLevel::eProblematicEvent)
{
if (AuAtomicTestAndSet(&gProblemCounter, 1))
{
return;
}
}
// Dispatch
DispatchHandlersForThread(thread, level);
// ...
if (level == ETriggerLevel::eProblematicEvent)
{
@ -68,15 +85,14 @@ namespace Aurora::Exit
Grug::GrugFlushFlushs();
}
gProblemCounter = 0;
// Has already sent eSafeTermination?
if (isPreempting)
{
return;
}
// Dispatch
DispatchHandlersForThread(thread, level);
// ...
gHasSentTerminate |= isTerminate;

View File

@ -525,6 +525,13 @@ namespace Aurora::Process
AUKN_SYM void Exit(AuUInt32 exitcode)
{
#if defined(AURORA_PLATFORM_WIN32)
// TODO (Reece): ...
#endif
Aurora::RuntimeShutdown();
#if defined(AURORA_IS_MODERNNT_DERIVED)
ExitProcess(exitcode);
#elif defined(AURORA_IS_POSIX_DERIVED)

View File

@ -28,6 +28,20 @@
namespace Aurora::Threading::Threads
{
static struct DtorFlipper
{
DtorFlipper() : bActive(true)
{
}
~DtorFlipper()
{
bActive = false;
}
bool bActive;
} gGlobal;
static ThreadInfo gDummyThreadInfo;
OSThread::OSThread(const ThreadInfo &info) : info_(info)
@ -57,11 +71,24 @@ namespace Aurora::Threading::Threads
this->handle_ = reinterpret_cast<decltype(handle_)>(id);
}
bool DeadTest();
OSThread::~OSThread()
{
bool bDetached {};
bool bDetachedSuccess {};
if (DeadTest())
{
return;
}
if (!gGlobal.bActive)
{
return;
}
if (this->contextUsed_)
{
if (this->detached_)
@ -192,7 +219,7 @@ namespace Aurora::Threading::Threads
}
}
bool OSThread::Exit(bool willReturnToOS)
bool OSThread::Exit(bool willReturnToOS, bool isEOL)
{
if (GetThread() == this)
{

View File

@ -47,7 +47,7 @@ namespace Aurora::Threading::Threads
AuSPtr<Loop::ILoopSource> GetShutdownSignalLS() override;
protected:
bool Exit(bool willReturnToOS);
bool Exit(bool willReturnToOS, bool isEOL = false);
bool ExecuteNewOSContext(AuFunction<void()> task);
void UpdatePrio(EThreadThrottle throttle, EThreadPriority prio);
void UpdateAffinity(const HWInfo::CpuBitId &mask);

View File

@ -18,9 +18,18 @@ namespace Aurora::Threading::Threads
AuUInt64 unixThreadId;
};
static AuThreadPrimitives::SpinLock gMutex;
static AuHashMap<AuUInt, IAuroraThread *> gUnixHandlesToThreads;
static AuHashMap<AuUInt, IAuroraThread *> gNativeHandlesToThreads;
struct Temp
{
~Temp()
{
bActive = false;
}
bool bActive {true};
AuThreadPrimitives::SpinLock gMutex;
AuHashMap<AuUInt, IAuroraThread *> gUnixHandlesToThreads;
AuHashMap<AuUInt, IAuroraThread *> gNativeHandlesToThreads;
} gVariables;
static IAuroraThread *OsThreadAnnounce(AuUInt64 threadId);
static void OsThreadShutdown(AuUInt64 threadId);
@ -50,20 +59,28 @@ namespace Aurora::Threading::Threads
static void RegisterThisThread(BasicThreadId id, IAuroraThread *handle)
{
AU_LOCK_GUARD(gMutex);
if (!gVariables.bActive)
{
return;
}
AU_LOCK_GUARD(gVariables.gMutex);
#if defined(AURORA_IS_POSIX_DERIVED)
AuTryInsert(gUnixHandlesToThreads, id.unixThreadId, handle);
AuTryInsert(gVariables.gUnixHandlesToThreads, id.unixThreadId, handle);
#endif
AuTryInsert(gNativeHandlesToThreads, id.threadId, handle);
AuTryInsert(gVariables.gNativeHandlesToThreads, id.threadId, handle);
}
static void ReleaseThisThread(BasicThreadId id)
{
AU_LOCK_GUARD(gMutex);
if (!gVariables.bActive)
{
return;
}
AU_LOCK_GUARD(gVariables.gMutex);
#if defined(AURORA_IS_POSIX_DERIVED)
AuTryRemove(gUnixHandlesToThreads, id.unixThreadId);
AuTryRemove(gVariables.gUnixHandlesToThreads, id.unixThreadId);
#endif
AuTryRemove(gNativeHandlesToThreads, id.threadId);
AuTryRemove(gVariables.gNativeHandlesToThreads, id.threadId);
}
struct OSFallbackThread : BasicThreadId
@ -134,22 +151,40 @@ namespace Aurora::Threading::Threads
IAuroraThread *GetThreadByPOSIXPid(AuUInt validPid)
{
AU_LOCK_GUARD(gMutex);
auto itr = gUnixHandlesToThreads.find(validPid);
if (itr == gUnixHandlesToThreads.end()) return {};
if (!gVariables.bActive)
{
return {};
}
AU_LOCK_GUARD(gVariables.gMutex);
auto itr = gVariables.gUnixHandlesToThreads.find(validPid);
if (itr == gVariables.gUnixHandlesToThreads.end()) return {};
return itr->second;
}
IAuroraThread *GetThreadByOSHandle(AuUInt validPid)
{
AU_LOCK_GUARD(gMutex);
auto itr = gNativeHandlesToThreads.find(validPid);
if (itr == gNativeHandlesToThreads.end()) return {};
if (!gVariables.bActive)
{
return {};
}
AU_LOCK_GUARD(gVariables.gMutex);
auto itr = gVariables.gNativeHandlesToThreads.find(validPid);
if (itr == gVariables.gNativeHandlesToThreads.end()) return {};
return itr->second;
}
AUKN_SYM bool DeadTest()
{
return !gVariables.bActive;
}
AUKN_SYM IAuroraThread *GetThread()
{
if (DeadTest())
{
return {};
}
auto ret = tlsCurrentThread;
if (ret)
{