From 2e293bbbf17639471d6d570212a09d097801da66 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Wed, 29 Oct 2025 09:35:25 +0100 Subject: fix for Latch race (#617) Because the counter is decreased in `CountDown()` and subsequently checked against zero to determine if the completion event should be set: `Latch::Wait` checks the counter against zero on entry and would exit early, before waiting on the completion event. This could then lead to the `Latch` instance being torn down before the `CountDown()` does a `Set()` which could then lead to unexpected and unwanted things happening. --- src/zencore/thread.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/zencore/thread.cpp') diff --git a/src/zencore/thread.cpp b/src/zencore/thread.cpp index 7bd21a229..9e3486e49 100644 --- a/src/zencore/thread.cpp +++ b/src/zencore/thread.cpp @@ -200,7 +200,7 @@ Event::Set() SetEvent(m_EventHandle); #else std::atomic_thread_fence(std::memory_order_acquire); - auto* Inner = (EventInner*)m_EventHandle; + auto* Inner = (EventInner*)m_EventHandle.load(); { std::unique_lock Lock(Inner->Mutex); Inner->bSet.store(true); @@ -216,7 +216,7 @@ Event::Reset() ResetEvent(m_EventHandle); #else std::atomic_thread_fence(std::memory_order_acquire); - auto* Inner = (EventInner*)m_EventHandle; + auto* Inner = (EventInner*)m_EventHandle.load(); { std::unique_lock Lock(Inner->Mutex); Inner->bSet.store(false); @@ -232,7 +232,7 @@ Event::Close() m_EventHandle = nullptr; #else std::atomic_thread_fence(std::memory_order_acquire); - auto* Inner = (EventInner*)m_EventHandle; + auto* Inner = (EventInner*)m_EventHandle.load(); { std::unique_lock Lock(Inner->Mutex); Inner->bSet.store(true); @@ -260,7 +260,7 @@ Event::Wait(int TimeoutMs) return (Result == WAIT_OBJECT_0); #else std::atomic_thread_fence(std::memory_order_acquire); - auto* Inner = reinterpret_cast(m_EventHandle); + auto* Inner = reinterpret_cast(m_EventHandle.load()); if (Inner->bSet.load()) { @@ -372,7 +372,7 @@ NamedEvent::Close() #if ZEN_PLATFORM_WINDOWS CloseHandle(m_EventHandle); #elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC - int Fd = int(intptr_t(m_EventHandle) & 0xffff'ffff); + int Fd = int(intptr_t(m_EventHandle.load()) & 0xffff'ffff); if (flock(Fd, LOCK_EX | LOCK_NB) == 0) { @@ -390,7 +390,7 @@ NamedEvent::Close() flock(Fd, LOCK_UN | LOCK_NB); close(Fd); - int Sem = int(intptr_t(m_EventHandle) >> 32); + int Sem = int(intptr_t(m_EventHandle.load()) >> 32); semctl(Sem, 0, IPC_RMID); } #endif @@ -408,7 +408,7 @@ NamedEvent::Set() return MakeErrorCodeFromLastError(); } #elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC - int Sem = int(intptr_t(m_EventHandle) >> 32); + int Sem = int(intptr_t(m_EventHandle.load()) >> 32); if (semctl(Sem, 0, SETVAL, 0) == -1) { return MakeErrorCodeFromLastError(); @@ -434,7 +434,7 @@ NamedEvent::Wait(int TimeoutMs) return (Result == WAIT_OBJECT_0); #elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC - int Sem = int(intptr_t(m_EventHandle) >> 32); + int Sem = int(intptr_t(m_EventHandle.load()) >> 32); int Result; struct sembuf SemOp = {}; -- cgit v1.2.3