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

Alexandre Julliard julliard at winehq.org
Tue Dec 4 16:33:55 CST 2018


Module: wine
Branch: master
Commit: 6060d2703c2e1382f076ad40ea43980781eaca2c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6060d2703c2e1382f076ad40ea43980781eaca2c

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Fri Nov 30 19:03:57 2018 -0600

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=46099
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/sync.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index e1a48d7..62cb3cd 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -1961,6 +1961,15 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
     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 )
 {
     switch (size)
@@ -2004,8 +2013,12 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
 
     for (;;)
     {
+        RtlEnterCriticalSection( &addr_section );
         if (!compare_addr( addr, cmp, size ))
+        {
+            RtlLeaveCriticalSection( &addr_section );
             return STATUS_SUCCESS;
+        }
 
         SERVER_START_REQ( select )
         {
@@ -2021,6 +2034,9 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
             call        = reply->call;
         }
         SERVER_END_REQ;
+
+        RtlLeaveCriticalSection( &addr_section );
+
         if (ret == STATUS_PENDING) ret = wait_select_reply( &cookie );
         if (ret != STATUS_USER_APC) break;
         if (invoke_apc( &call, &result ))
@@ -2043,7 +2059,9 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
  */
 void WINAPI RtlWakeAddressAll( const void *addr )
 {
+    RtlEnterCriticalSection( &addr_section );
     while (NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {}
+    RtlLeaveCriticalSection( &addr_section );
 }
 
 /***********************************************************************
@@ -2051,5 +2069,7 @@ void WINAPI RtlWakeAddressAll( const void *addr )
  */
 void WINAPI RtlWakeAddressSingle( const void *addr )
 {
+    RtlEnterCriticalSection( &addr_section );
     NtReleaseKeyedEvent( 0, addr, 0, &zero_timeout );
+    RtlLeaveCriticalSection( &addr_section );
 }




More information about the wine-cvs mailing list