<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="MS Exchange Server version 6.5.7650.28">
<TITLE>wineserver: Make sure while we are waking a thread we do not try to do it again (try #2)</TITLE>
</HEAD>
<BODY>
<!-- Converted from text/plain format -->
<P><FONT SIZE=2>Hi, this is my first patch. It is for the following bug:<BR>
<A HREF="http://bugs.winehq.org/show_bug.cgi?id=7286">http://bugs.winehq.org/show_bug.cgi?id=7286</A> . This patch solves the<BR>
following problem: currently, in wineserver when a thread is being woken<BR>
and end_wait is called, the wait object is not updated in any meaningful<BR>
way until all the objects that need to be released from the thread->wait<BR>
object are in fact release. This causes a problem if one of the<BR>
release_objects methods for a specific object that is being released<BR>
ends up waking up the thread again, as occurs in this bug with the<BR>
directory objects and the dir_destroy method, which sends a user APC to<BR>
all the threads on its change queue. For Vector NTI, the same thread<BR>
that is being woken by a timeout after waiting for the directory object<BR>
is also on the change queue for this directory, so with this patch the<BR>
user APC is queued but the thread is not immediately woken because it is<BR>
already in the process of being woken for a timeout. In general, this<BR>
patch will keep a thread from being woken if it is in the process of<BR>
being woken, which could in theory come up in other situations.<BR>
<BR>
Changelog:<BR>
<BR>
wineserver: Do not allow a thread to be woken when it is already in the process of being woken.<BR>
<BR>
---<BR>
server/thread.c | 7 +++++++<BR>
1 files changed, 7 insertions(+), 0 deletions(-)<BR>
<BR>
diff --git a/server/thread.c b/server/thread.c<BR>
index b4a16cd..b477364 100644<BR>
--- a/server/thread.c<BR>
+++ b/server/thread.c<BR>
@@ -58,6 +58,8 @@ struct thread_wait<BR>
struct thread *thread; /* owner thread */<BR>
int count; /* count of objects */<BR>
int flags;<BR>
+ int waking; /* whether we are currently waking this<BR>
+ * thread */<BR>
void *cookie; /* magic cookie to return to client */<BR>
struct timeval timeout;<BR>
struct timeout_user *user;<BR>
@@ -447,6 +449,7 @@ static void end_wait( struct thread *thr<BR>
int i;<BR>
<BR>
assert( wait );<BR>
+ thread->wait->waking = 1;<BR>
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)<BR>
entry->obj->ops->remove_queue( entry->obj, entry );<BR>
if (wait->user) remove_timeout_user( wait->user );<BR>
@@ -467,6 +470,7 @@ static int wait_on( int count, struct ob<BR>
wait->count = count;<BR>
wait->flags = flags;<BR>
wait->user = NULL;<BR>
+ wait->waking = 0;<BR>
current->wait = wait;<BR>
if (flags & SELECT_TIMEOUT)<BR>
{<BR>
@@ -495,6 +499,9 @@ static int check_wait( struct thread *th<BR>
struct thread_wait *wait = thread->wait;<BR>
struct wait_queue_entry *entry = wait->queues;<BR>
<BR>
+ /* If we are already waking this thread, no need to wake it again */<BR>
+ if (wait->waking) return -1;<BR>
+<BR>
/* Suspended threads may not acquire locks, but they can run system APCs */<BR>
if (thread->process->suspend + thread->suspend > 0)<BR>
{<BR>
--<BR>
1.4.1<BR>
<BR>
<BR>
</FONT>
</P>
</BODY>
</HTML>