Fix race condition.
Work around undocumented SignalObjectAndWait behavior; the docs refer to "the object", but the function takes two objects. (Cut and paste documentation ...)
This commit is contained in:
@@ -282,7 +282,8 @@ EventImpl_Win32::~EventImpl_Win32()
|
|||||||
static bool PortableSignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, bool bFirstParamIsMutex, unsigned iMilliseconds = INFINITE )
|
static bool PortableSignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, bool bFirstParamIsMutex, unsigned iMilliseconds = INFINITE )
|
||||||
{
|
{
|
||||||
static bool bSignalObjectAndWaitUnavailable = false;
|
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 );
|
DWORD ret = SignalObjectAndWait( hObjectToSignal, hObjectToWaitOn, iMilliseconds, false );
|
||||||
switch( ret )
|
switch( ret )
|
||||||
@@ -358,6 +359,14 @@ bool EventImpl_Win32::Wait( RageTimer *pTimeout )
|
|||||||
bool bSuccess = PortableSignalObjectAndWait( m_pParent->mutex, m_WakeupSema, true, iMilliseconds );
|
bool bSuccess = PortableSignalObjectAndWait( m_pParent->mutex, m_WakeupSema, true, iMilliseconds );
|
||||||
|
|
||||||
EnterCriticalSection( &m_iNumWaitingLock );
|
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;
|
--m_iNumWaiting;
|
||||||
bool bLastWaiting = m_iNumWaiting == 0;
|
bool bLastWaiting = m_iNumWaiting == 0;
|
||||||
LeaveCriticalSection( &m_iNumWaitingLock );
|
LeaveCriticalSection( &m_iNumWaitingLock );
|
||||||
|
|||||||
Reference in New Issue
Block a user