wineserver: Make sure while we are waking a thread we do not try to do it again.

Misha Koshelev mk144210 at
Wed Jan 31 11:26:01 CST 2007

Hi, this is my first patch. It is for the following bug: . This patch solves the
following problem: currently, in wineserver when a thread is being woken
and end_wait is called, the wait object is not updated in any meaningful
way until all the objects that need to be released from the thread->wait
object are in fact release. This causes a problem if one of the
release_objects methods for a specific object that is being released
ends up waking up the thread again, as occurs in this bug with the
directory objects and the dir_destroy method, which sends a user APC to
all the threads on its change queue. For Vector NTI, the same thread
that is being woken by a timeout after waiting for the directory object
is also on the change queue for this directory, so with this patch the
user APC is queued but the thread is not immediately woken because it is
already in the process of being woken for a timeout. In general, this
patch will keep a thread from being woken if it is in the process of
being woken, which could in theory come up in other situations.


	wineserver: Do not allow a thread to be woken when it is already in the
process of being woken.

 server/thread.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/server/thread.c b/server/thread.c
index b4a16cd..b477364 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -58,6 +58,8 @@ struct thread_wait
     struct thread          *thread;     /* owner thread */
     int                     count;      /* count of objects */
     int                     flags;
+    int                     waking;     /* whether we are currently
waking this
+					 * thread */
     void                   *cookie;     /* magic cookie to return to
client */
     struct timeval          timeout;
     struct timeout_user    *user;
@@ -447,6 +449,7 @@ static void end_wait( struct thread *thr
     int i;
     assert( wait );
+    thread->wait->waking = 1;
     for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
         entry->obj->ops->remove_queue( entry->obj, entry );
     if (wait->user) remove_timeout_user( wait->user );
@@ -467,6 +470,7 @@ static int wait_on( int count, struct ob
     wait->count   = count;
     wait->flags   = flags;
     wait->user    = NULL;
+    wait->waking  = 0;
     current->wait = wait;
     if (flags & SELECT_TIMEOUT)
@@ -495,6 +499,9 @@ static int check_wait( struct thread *th
     struct thread_wait *wait = thread->wait;
     struct wait_queue_entry *entry = wait->queues;
+    /* If we are already waking this thread, no need to wake it again
+    if (wait->waking) return -1;
     /* Suspended threads may not acquire locks, but they can run system
APCs */
     if (thread->process->suspend + thread->suspend > 0)

More information about the wine-patches mailing list