[*] Harden exit
This commit is contained in:
parent
fb5eb02594
commit
5599da3ab0
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace Aurora::Async
|
||||
|
||||
void ReleaseApp()
|
||||
{
|
||||
gAsyncAppMem->Shutdown();
|
||||
gAsyncAppMem.reset();
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user