Rémi Bernon : ntdll: Process system APCs while the signals are blocked.

Alexandre Julliard julliard at winehq.org
Wed Feb 5 16:53:35 CST 2020


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

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Wed Feb  5 11:49:40 2020 +0100

ntdll: Process system APCs while the signals are blocked.

This makes sure that system APC, such as APC_BREAK_PROCESS do not get
interrupted in the middle of their execution, and that the APC
completion notification is always correctly sent back to the caller.

Otherwise DbgBreakProcess sometimes did not return until
WaitForDebugEvent/ContinueDebugEvent are called, because of a race
condition between the APC servicing thread, and the newly created
exception thread.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/server.c | 5 ++++-
 dlls/ntdll/sync.c   | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index 15d53b348e..4facdc08a7 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -601,11 +601,13 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
     apc_call_t call;
     apc_result_t result;
     timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
+    sigset_t old_set;
 
     memset( &result, 0, sizeof(result) );
 
     do
     {
+        pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
         for (;;)
         {
             SERVER_START_REQ( select )
@@ -616,7 +618,7 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
                 req->timeout  = abs_timeout;
                 wine_server_add_data( req, &result, sizeof(result) );
                 wine_server_add_data( req, select_op, size );
-                ret = wine_server_call( req );
+                ret = server_call_unlocked( req );
                 abs_timeout = reply->timeout;
                 apc_handle  = reply->apc_handle;
                 call        = reply->call;
@@ -630,6 +632,7 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
             if (ret != STATUS_KERNEL_APC) break;
             invoke_apc( &call, &result );
         }
+        pthread_sigmask( SIG_SETMASK, &old_set, NULL );
 
         if (ret == STATUS_USER_APC)
         {
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 8b12e03eef..2b5b6ce44a 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -2457,6 +2457,7 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
     apc_call_t call;
     apc_result_t result;
     timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
+    sigset_t old_set;
 
     if (size != 1 && size != 2 && size != 4 && size != 8)
         return STATUS_INVALID_PARAMETER;
@@ -2479,6 +2480,7 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
             return STATUS_SUCCESS;
         }
 
+        pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
         for (;;)
         {
             SERVER_START_REQ( select )
@@ -2489,7 +2491,7 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
                 req->timeout  = abs_timeout;
                 wine_server_add_data( req, &result, sizeof(result) );
                 wine_server_add_data( req, &select_op, sizeof(select_op.keyed_event) );
-                ret = wine_server_call( req );
+                ret = server_call_unlocked( req );
                 abs_timeout = reply->timeout;
                 apc_handle  = reply->apc_handle;
                 call        = reply->call;
@@ -2499,6 +2501,7 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
             if (ret != STATUS_KERNEL_APC) break;
             invoke_apc( &call, &result );
         }
+        pthread_sigmask( SIG_SETMASK, &old_set, NULL );
 
         RtlLeaveCriticalSection( &addr_section );
 




More information about the wine-cvs mailing list