From b1e54d803ba1473d2c3b6b8a92b377ef431b2394 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 28 Sep 2026 10:38:29 +0200 Subject: [PATCH] WOW64: Get thread context in BTCpuThreadTerm to make sure the thread is actually suspended --- Source/Windows/WOW64/Module.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Windows/WOW64/Module.cpp b/Source/Windows/WOW64/Module.cpp index 257c39b5c..8c6b7f76e 100644 --- a/Source/Windows/WOW64/Module.cpp +++ b/Source/Windows/WOW64/Module.cpp @@ -622,18 +622,23 @@ void BTCpuThreadTerm(HANDLE Thread, LONG ExitCode) { return; } - auto ThreadDup = FEX::Windows::DupHandle(Thread, THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME); + auto ThreadDup = FEX::Windows::DupHandle(Thread, THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT); THREAD_BASIC_INFORMATION Info; if (auto Err = NtQueryInformationThread(*ThreadDup, ThreadBasicInformation, &Info, sizeof(Info), nullptr); Err) { return; } + LogMan::Msg::IFmt("Terminating {}", Info.ClientId.UniqueThread); const auto ThreadTID = reinterpret_cast(Info.ClientId.UniqueThread); bool Self = ThreadTID == GetCurrentThreadId(); if (!Self) { + CONTEXT TmpContext; // If we are suspending a thread that isn't ourselves, try to suspend it first so we know internal JIT locks aren't being held. RtlWow64SuspendThread(*ThreadDup, NULL); + // This will wait for the thread to be suspended + TmpContext.ContextFlags = CONTEXT_CONTROL; + NtGetContextThread(*ThreadDup, &TmpContext); } auto [Err, TLS] = GetThreadTLS(*ThreadDup);