mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-10 11:00:19 +02:00
Windows: Avoid potential race between thread init and termination
With the prior locking, we could try to terminate a thread while it was initializing and perhaps holding global locks leading to deadlock.
This commit is contained in:
1 parent
972c8a97dc
commit
4df17abea7
2 files changed
+25
-25
No files matched your search
@@ -911,6 +911,7 @@ void BTCpu64NotifyMemoryDirty(void* Address, SIZE_T Size) {
|
||||
void BTCpu64NotifyReadFile(HANDLE Handle, void* Address, SIZE_T Size, BOOL After, NTSTATUS Status) {}
|
||||
|
||||
NTSTATUS ThreadInit() {
|
||||
std::scoped_lock Lock(ThreadCreationMutex);
|
||||
FEX::Windows::InitCRTThread();
|
||||
static constexpr size_t EmulatorStackSize = 0x40000;
|
||||
const uint64_t EmulatorStack = reinterpret_cast<uint64_t>(::VirtualAlloc(nullptr, EmulatorStackSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||
@@ -945,7 +946,6 @@ NTSTATUS ThreadInit() {
|
||||
Exception::LoadStateFromECContext(Thread, CPUArea.ContextAmd64().AMD64_Context);
|
||||
|
||||
{
|
||||
std::scoped_lock Lock(ThreadCreationMutex);
|
||||
auto ThreadTID = GetCurrentThreadId();
|
||||
Threads.emplace(ThreadTID, Thread);
|
||||
if (StatAllocHandler) {
|
||||
@@ -959,29 +959,29 @@ NTSTATUS ThreadInit() {
|
||||
}
|
||||
|
||||
NTSTATUS ThreadTerm(HANDLE Thread, LONG ExitCode) {
|
||||
const auto [Err, CPUArea] = GetThreadCPUArea(Thread);
|
||||
if (Err) {
|
||||
return Err;
|
||||
}
|
||||
auto* OldThreadState = CPUArea.ThreadState();
|
||||
CPUArea.ThreadState() = nullptr;
|
||||
|
||||
THREAD_BASIC_INFORMATION Info;
|
||||
if (NTSTATUS Err = NtQueryInformationThread(Thread, ThreadBasicInformation, &Info, sizeof(Info), nullptr); Err) {
|
||||
if (auto Err = NtQueryInformationThread(Thread, ThreadBasicInformation, &Info, sizeof(Info), nullptr); Err) {
|
||||
return Err;
|
||||
}
|
||||
|
||||
const auto ThreadTID = reinterpret_cast<uint64_t>(Info.ClientId.UniqueThread);
|
||||
bool Self = ThreadTID == GetCurrentThreadId();
|
||||
|
||||
const auto [Err, CPUArea] = GetThreadCPUArea(Thread);
|
||||
if (Err) {
|
||||
return Err;
|
||||
}
|
||||
|
||||
{
|
||||
std::scoped_lock Lock(ThreadCreationMutex);
|
||||
Threads.erase(ThreadTID);
|
||||
if (StatAllocHandler) {
|
||||
StatAllocHandler->DeallocateSlot(OldThreadState->ThreadStats);
|
||||
StatAllocHandler->DeallocateSlot(CPUArea.ThreadState()->ThreadStats);
|
||||
}
|
||||
}
|
||||
|
||||
FEX::Windows::CallRetStack::DestroyThread(OldThreadState);
|
||||
CTX->DestroyThread(OldThreadState);
|
||||
FEX::Windows::CallRetStack::DestroyThread(CPUArea.ThreadState());
|
||||
CTX->DestroyThread(CPUArea.ThreadState());
|
||||
::VirtualFree(reinterpret_cast<void*>(CPUArea.EmulatorStackLimit()), 0, MEM_RELEASE);
|
||||
if (ThreadTID == GetCurrentThreadId()) {
|
||||
FEX::Windows::DeinitCRTThread();
|
||||
|
||||
Reference in new issue
Block a user