[PATCH 01/15] server: Wait before suspending threads in APC.

Rémi Bernon rbernon at codeweavers.com
Mon Jan 27 06:07:04 CST 2020


The APC_BREAK_PROCESS call creates a thread that raises an exception,
suspending the whole process. There's a race condition between this
thread and the APC thread notifying the server of its completion.

This fixes "winedbg --gdb" sometimes not responding after Ctrl-C.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 server/thread.c | 5 +++++
 server/thread.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/server/thread.c b/server/thread.c
index 80db41b48d2..a2fd4908792 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -199,6 +199,7 @@ static inline void init_thread_structure( struct thread *thread )
     thread->exit_code       = 0;
     thread->priority        = 0;
     thread->suspend         = 0;
+    thread->in_apc          = 0;
     thread->desktop_users   = 0;
     thread->token           = NULL;
     thread->desc            = NULL;
@@ -583,6 +584,7 @@ static void set_thread_info( struct thread *thread,
 /* stop a thread (at the Unix level) */
 void stop_thread( struct thread *thread )
 {
+    if (thread->in_apc) return;  /* currently doing apc, will be suspended on return */
     if (thread->context) return;  /* already inside a debug event, no need for a signal */
     /* can't stop a thread while initialisation is in progress */
     if (is_process_init_done(thread->process)) send_thread_signal( thread, SIGUSR1 );
@@ -1575,6 +1577,8 @@ DECL_HANDLER(select)
         wake_up( &apc->obj, 0 );
         close_handle( current->process, req->prev_apc );
         release_object( apc );
+        current->in_apc = 0;
+        stop_thread_if_suspended( current );
     }
 
     reply->timeout = select_on( &select_op, op_size, req->cookie, req->flags, req->timeout );
@@ -1591,6 +1595,7 @@ DECL_HANDLER(select)
             if (apc->call.type != APC_NONE &&
                 (reply->apc_handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 )))
             {
+                current->in_apc = 1;
                 reply->call = apc->call;
                 release_object( apc );
                 break;
diff --git a/server/thread.h b/server/thread.h
index 66e35603d36..08700455972 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -82,6 +82,7 @@ struct thread
     affinity_t             affinity;      /* affinity mask */
     int                    priority;      /* priority level */
     int                    suspend;       /* suspend count */
+    int                    in_apc;        /* currently doing apc */
     obj_handle_t           desktop;       /* desktop handle */
     int                    desktop_users; /* number of objects using the thread desktop */
     timeout_t              creation_time; /* Thread creation time */
-- 
2.25.0




More information about the wine-devel mailing list