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@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 */