Commit 6060d270 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

ntdll: Use a critical section to ensure that RtlWaitOnAddress compares and queues atomically.

Currently a wake may occur between calling compare_addr() and performing the select request; in that case the thread will never be woken. Prevent this by taking a CS around both operations. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46099Signed-off-by: 's avatarZebediah Figura <z.figura12@gmail.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 0ea963a4
...@@ -1961,6 +1961,15 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, ...@@ -1961,6 +1961,15 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
return status; return status;
} }
static RTL_CRITICAL_SECTION addr_section;
static RTL_CRITICAL_SECTION_DEBUG addr_section_debug =
{
0, 0, &addr_section,
{ &addr_section_debug.ProcessLocksList, &addr_section_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": addr_section") }
};
static RTL_CRITICAL_SECTION addr_section = { &addr_section_debug, -1, 0, 0, 0, 0 };
static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size ) static BOOL compare_addr( const void *addr, const void *cmp, SIZE_T size )
{ {
switch (size) switch (size)
...@@ -2004,8 +2013,12 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size ...@@ -2004,8 +2013,12 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
for (;;) for (;;)
{ {
RtlEnterCriticalSection( &addr_section );
if (!compare_addr( addr, cmp, size )) if (!compare_addr( addr, cmp, size ))
{
RtlLeaveCriticalSection( &addr_section );
return STATUS_SUCCESS; return STATUS_SUCCESS;
}
SERVER_START_REQ( select ) SERVER_START_REQ( select )
{ {
...@@ -2021,6 +2034,9 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size ...@@ -2021,6 +2034,9 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
call = reply->call; call = reply->call;
} }
SERVER_END_REQ; SERVER_END_REQ;
RtlLeaveCriticalSection( &addr_section );
if (ret == STATUS_PENDING) ret = wait_select_reply( &cookie ); if (ret == STATUS_PENDING) ret = wait_select_reply( &cookie );
if (ret != STATUS_USER_APC) break; if (ret != STATUS_USER_APC) break;
if (invoke_apc( &call, &result )) if (invoke_apc( &call, &result ))
...@@ -2043,7 +2059,9 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size ...@@ -2043,7 +2059,9 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
*/ */
void WINAPI RtlWakeAddressAll( const void *addr ) void WINAPI RtlWakeAddressAll( const void *addr )
{ {
RtlEnterCriticalSection( &addr_section );
while (NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {} while (NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {}
RtlLeaveCriticalSection( &addr_section );
} }
/*********************************************************************** /***********************************************************************
...@@ -2051,5 +2069,7 @@ void WINAPI RtlWakeAddressAll( const void *addr ) ...@@ -2051,5 +2069,7 @@ void WINAPI RtlWakeAddressAll( const void *addr )
*/ */
void WINAPI RtlWakeAddressSingle( const void *addr ) void WINAPI RtlWakeAddressSingle( const void *addr )
{ {
RtlEnterCriticalSection( &addr_section );
NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ); NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout );
RtlLeaveCriticalSection( &addr_section );
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment