Added patch to delay signaling threads until they are really gone (fixes Wine Staging Bug #473).

This commit is contained in:
Sebastian Lackner
2015-10-19 00:38:33 +02:00
parent 922e5a0e06
commit be51f622f7
7 changed files with 134 additions and 22 deletions

View File

@@ -0,0 +1,87 @@
From 67856c891a6d40c6e484f5f29db30a8899a39e04 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 19 Oct 2015 00:34:01 +0200
Subject: server: Do not signal thread until it is really gone.
---
server/thread.c | 22 ++++++++++++++++++++--
server/thread.h | 1 +
2 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/server/thread.c b/server/thread.c
index 6383000..ba84bee 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -195,6 +195,7 @@ static inline void init_thread_structure( struct thread *thread )
thread->suspend = 0;
thread->desktop_users = 0;
thread->token = NULL;
+ thread->exit_poll = NULL;
thread->creation_time = current_time;
thread->exit_time = 0;
@@ -316,6 +317,7 @@ static void destroy_thread( struct object *obj )
list_remove( &thread->entry );
cleanup_thread( thread );
release_object( thread->process );
+ if (thread->exit_poll) remove_timeout_user( thread->exit_poll );
if (thread->id) free_ptid( thread->id );
if (thread->token) release_object( thread->token );
}
@@ -333,7 +335,7 @@ static void dump_thread( struct object *obj, int verbose )
static int thread_signaled( struct object *obj, struct wait_queue_entry *entry )
{
struct thread *mythread = (struct thread *)obj;
- return (mythread->state == TERMINATED);
+ return (mythread->state == TERMINATED && !mythread->exit_poll);
}
static unsigned int thread_map_access( struct object *obj, unsigned int access )
@@ -1091,6 +1093,22 @@ int thread_get_inflight_fd( struct thread *thread, int client )
return -1;
}
+static void check_terminated( void *arg )
+{
+ struct thread *thread = arg;
+ assert( thread->obj.ops == &thread_ops );
+ assert( thread->state == TERMINATED );
+
+ if (thread->unix_tid != -1 && !kill( thread->unix_tid, 0 ))
+ {
+ thread->exit_poll = add_timeout_user( -TICKS_PER_SEC / 100, check_terminated, thread );
+ return;
+ }
+
+ thread->exit_poll = NULL;
+ wake_up( &thread->obj, 0 );
+}
+
/* kill a thread on the spot */
void kill_thread( struct thread *thread, int violent_death )
{
@@ -1111,8 +1129,8 @@ void kill_thread( struct thread *thread, int violent_death )
kill_console_processes( thread, 0 );
debug_exit_thread( thread );
abandon_mutexes( thread );
- wake_up( &thread->obj, 0 );
if (violent_death) send_thread_signal( thread, SIGQUIT );
+ check_terminated( thread );
cleanup_thread( thread );
remove_process_thread( thread->process, thread );
release_object( thread );
diff --git a/server/thread.h b/server/thread.h
index 2821991..ac9af24 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -88,6 +88,7 @@ struct thread
timeout_t creation_time; /* Thread creation time */
timeout_t exit_time; /* Thread exit time */
struct token *token; /* security token associated with this thread */
+ struct timeout_user *exit_poll; /* poll if the thread/process has exited already */
};
struct thread_snapshot
--
2.6.1

View File

@@ -0,0 +1 @@
Fixes: Do not signal threads until they are really gone