From 5599da3ab06885d365bab1234459c76f623a7c45 Mon Sep 17 00:00:00 2001 From: Reece Date: Sat, 2 Apr 2022 01:48:29 +0100 Subject: [PATCH] [*] Harden exit --- Include/Aurora/Runtime.hpp | 1 + .../Aurora/Threading/Threads/TLSVariable.hpp | 6 ++ Source/Async/AsyncApp.cpp | 1 + Source/Debug/ExceptionWatcher.Win32.cpp | 15 +++-- Source/Exit/Exit.cpp | 22 ++++++- Source/Process/Process.cpp | 7 ++ Source/Threading/Threads/OSThread.cpp | 29 ++++++++- Source/Threading/Threads/OSThread.hpp | 2 +- Source/Threading/Threads/ThreadHandles.cpp | 65 ++++++++++++++----- 9 files changed, 121 insertions(+), 27 deletions(-) diff --git a/Include/Aurora/Runtime.hpp b/Include/Aurora/Runtime.hpp index 6231c19c..6104bb5f 100644 --- a/Include/Aurora/Runtime.hpp +++ b/Include/Aurora/Runtime.hpp @@ -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; diff --git a/Include/Aurora/Threading/Threads/TLSVariable.hpp b/Include/Aurora/Threading/Threads/TLSVariable.hpp index 60a4c2b1..dd30186d 100644 --- a/Include/Aurora/Threading/Threads/TLSVariable.hpp +++ b/Include/Aurora/Threading/Threads/TLSVariable.hpp @@ -9,6 +9,8 @@ namespace Aurora::Threading::Threads { + AUKN_SYM bool DeadTest(); + template class TLSVariable { @@ -21,6 +23,10 @@ namespace Aurora::Threading::Threads { if constexpr (!isStatic) { + if (DeadTest()) + { + return; + } GetThread()->GetTlsView()->Remove(GetHandle()); } } diff --git a/Source/Async/AsyncApp.cpp b/Source/Async/AsyncApp.cpp index ac54d739..bfb6ce1a 100644 --- a/Source/Async/AsyncApp.cpp +++ b/Source/Async/AsyncApp.cpp @@ -26,6 +26,7 @@ namespace Aurora::Async void ReleaseApp() { + gAsyncAppMem->Shutdown(); gAsyncAppMem.reset(); } diff --git a/Source/Debug/ExceptionWatcher.Win32.cpp b/Source/Debug/ExceptionWatcher.Win32.cpp index 0fb0f61f..66700473 100644 --- a/Source/Debug/ExceptionWatcher.Win32.cpp +++ b/Source/Debug/ExceptionWatcher.Win32.cpp @@ -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) diff --git a/Source/Exit/Exit.cpp b/Source/Exit/Exit.cpp index 614611e5..cd9a9fd2 100644 --- a/Source/Exit/Exit.cpp +++ b/Source/Exit/Exit.cpp @@ -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; diff --git a/Source/Process/Process.cpp b/Source/Process/Process.cpp index 6afc09c7..8b74cfff 100644 --- a/Source/Process/Process.cpp +++ b/Source/Process/Process.cpp @@ -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) diff --git a/Source/Threading/Threads/OSThread.cpp b/Source/Threading/Threads/OSThread.cpp index 2fd0e82f..8ed29fcf 100644 --- a/Source/Threading/Threads/OSThread.cpp +++ b/Source/Threading/Threads/OSThread.cpp @@ -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(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) { diff --git a/Source/Threading/Threads/OSThread.hpp b/Source/Threading/Threads/OSThread.hpp index 01511539..3bac2ff4 100644 --- a/Source/Threading/Threads/OSThread.hpp +++ b/Source/Threading/Threads/OSThread.hpp @@ -47,7 +47,7 @@ namespace Aurora::Threading::Threads AuSPtr GetShutdownSignalLS() override; protected: - bool Exit(bool willReturnToOS); + bool Exit(bool willReturnToOS, bool isEOL = false); bool ExecuteNewOSContext(AuFunction task); void UpdatePrio(EThreadThrottle throttle, EThreadPriority prio); void UpdateAffinity(const HWInfo::CpuBitId &mask); diff --git a/Source/Threading/Threads/ThreadHandles.cpp b/Source/Threading/Threads/ThreadHandles.cpp index b594f89d..1112e4e0 100644 --- a/Source/Threading/Threads/ThreadHandles.cpp +++ b/Source/Threading/Threads/ThreadHandles.cpp @@ -18,9 +18,18 @@ namespace Aurora::Threading::Threads AuUInt64 unixThreadId; }; - static AuThreadPrimitives::SpinLock gMutex; - static AuHashMap gUnixHandlesToThreads; - static AuHashMap gNativeHandlesToThreads; + struct Temp + { + ~Temp() + { + bActive = false; + } + + bool bActive {true}; + AuThreadPrimitives::SpinLock gMutex; + AuHashMap gUnixHandlesToThreads; + AuHashMap 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) {