From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/unix/thread.c | 24 +++++++++++++----------- server/async.c | 16 ++++++++++++++++ server/file.h | 1 + server/thread.c | 1 + 4 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 15bb3be34b2..ad47a5fce74 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1610,20 +1610,22 @@ NTSTATUS WINAPI NtAlertThread( HANDLE handle ) NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code ) { NTSTATUS ret; - BOOL self = (handle == GetCurrentThread()); + BOOL self;
- if (!self || exit_code) + SERVER_START_REQ( terminate_thread ) { - SERVER_START_REQ( terminate_thread ) - { - req->handle = wine_server_obj_handle( handle ); - req->exit_code = exit_code; - ret = wine_server_call( req ); - self = !ret && reply->self; - } - SERVER_END_REQ; + req->handle = wine_server_obj_handle( handle ); + req->exit_code = exit_code; + ret = wine_server_call( req ); + self = !ret && reply->self; + } + SERVER_END_REQ; + + if (self) + { + server_select( NULL, 0, SELECT_INTERRUPTIBLE, 0, NULL, NULL ); + exit_thread( exit_code ); } - if (self) exit_thread( exit_code ); return ret; }
diff --git a/server/async.c b/server/async.c index a4fbeab555e..4832d69b7bf 100644 --- a/server/async.c +++ b/server/async.c @@ -593,6 +593,22 @@ void cancel_process_asyncs( struct process *process ) cancel_async( process, NULL, NULL, 0 ); }
+void cancel_terminating_thread_asyncs( struct thread *thread ) +{ + struct async *async; + +restart: + LIST_FOR_EACH_ENTRY( async, &thread->process->asyncs, struct async, process_entry ) + { + if (async->thread != thread || async->terminated || async->canceled) continue; + if (async->completion && async->data.apc_context && !async->event) continue; + + async->canceled = 1; + fd_cancel_async( async->fd, async ); + goto restart; + } +} + /* wake up async operations on the queue */ void async_wake_up( struct async_queue *queue, unsigned int status ) { diff --git a/server/file.h b/server/file.h index 9f9d4cd4e1a..0ffe0e2c8dc 100644 --- a/server/file.h +++ b/server/file.h @@ -245,6 +245,7 @@ extern struct iosb *async_get_iosb( struct async *async ); extern struct thread *async_get_thread( struct async *async ); extern struct async *find_pending_async( struct async_queue *queue ); extern void cancel_process_asyncs( struct process *process ); +extern void cancel_terminating_thread_asyncs( struct thread *thread );
static inline void init_async_queue( struct async_queue *queue ) { diff --git a/server/thread.c b/server/thread.c index 467ccd1f0db..f49fbf40b78 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1462,6 +1462,7 @@ DECL_HANDLER(terminate_thread) thread->exit_code = req->exit_code; if (thread != current) kill_thread( thread, 1 ); else reply->self = 1; + cancel_terminating_thread_asyncs( thread ); release_object( thread ); } }