From 46f414e7e57832d5eff4d900e482cfffdfded5cd Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Sat, 29 Jan 2005 20:25:52 +0000 Subject: [PATCH] Fix race condition. Work around undocumented SignalObjectAndWait behavior; the docs refer to "the object", but the function takes two objects. (Cut and paste documentation ...) --- stepmania/src/arch/Threads/Threads_Win32.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/stepmania/src/arch/Threads/Threads_Win32.cpp b/stepmania/src/arch/Threads/Threads_Win32.cpp index 51ecc89aef..141c098c56 100644 --- a/stepmania/src/arch/Threads/Threads_Win32.cpp +++ b/stepmania/src/arch/Threads/Threads_Win32.cpp @@ -282,7 +282,8 @@ EventImpl_Win32::~EventImpl_Win32() static bool PortableSignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, bool bFirstParamIsMutex, unsigned iMilliseconds = INFINITE ) { static bool bSignalObjectAndWaitUnavailable = false; - if( !bSignalObjectAndWaitUnavailable ) + /* Watch out: SignalObjectAndWait doesn't work when iMilliseconds is zero. */ + if( !bSignalObjectAndWaitUnavailable && iMilliseconds != 0 ) { DWORD ret = SignalObjectAndWait( hObjectToSignal, hObjectToWaitOn, iMilliseconds, false ); switch( ret ) @@ -358,6 +359,14 @@ bool EventImpl_Win32::Wait( RageTimer *pTimeout ) bool bSuccess = PortableSignalObjectAndWait( m_pParent->mutex, m_WakeupSema, true, iMilliseconds ); EnterCriticalSection( &m_iNumWaitingLock ); + if( !bSuccess ) + { + /* Avoid a race condition: someone may have signalled the object between PortableSignalObjectAndWait + * and EnterCriticalSection. While we hold m_iNumWaitingLock, poll (with a zero timeout) the + * object one last time. */ + if( WaitForSingleObject( m_WakeupSema, 0 ) == WAIT_OBJECT_0 ) + bSuccess = true; + } --m_iNumWaiting; bool bLastWaiting = m_iNumWaiting == 0; LeaveCriticalSection( &m_iNumWaitingLock );