server: Call the satisfied methods after removing the thread wait.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d5380f0d00
commit
e0760ce933
|
@ -583,7 +583,7 @@ void make_wait_abandoned( struct wait_queue_entry *entry )
|
|||
}
|
||||
|
||||
/* finish waiting */
|
||||
static void end_wait( struct thread *thread )
|
||||
static unsigned int end_wait( struct thread *thread, unsigned int status )
|
||||
{
|
||||
struct thread_wait *wait = thread->wait;
|
||||
struct wait_queue_entry *entry;
|
||||
|
@ -591,10 +591,26 @@ static void end_wait( struct thread *thread )
|
|||
|
||||
assert( wait );
|
||||
thread->wait = wait->next;
|
||||
|
||||
if (status < wait->count) /* wait satisfied, tell it to the objects */
|
||||
{
|
||||
if (wait->select == SELECT_WAIT_ALL)
|
||||
{
|
||||
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
||||
entry->obj->ops->satisfied( entry->obj, entry );
|
||||
}
|
||||
else
|
||||
{
|
||||
entry = wait->queues + status;
|
||||
entry->obj->ops->satisfied( entry->obj, entry );
|
||||
}
|
||||
if (wait->abandoned) status += STATUS_ABANDONED_WAIT_0;
|
||||
}
|
||||
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 );
|
||||
free( wait );
|
||||
return status;
|
||||
}
|
||||
|
||||
/* build the thread wait structure */
|
||||
|
@ -624,7 +640,7 @@ static int wait_on( const select_op_t *select_op, unsigned int count, struct obj
|
|||
if (!obj->ops->add_queue( obj, entry ))
|
||||
{
|
||||
wait->count = i;
|
||||
end_wait( current );
|
||||
end_wait( current, get_error() );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -672,25 +688,14 @@ static int check_wait( struct thread *thread )
|
|||
* want to do something when signaled, even if others are not */
|
||||
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
||||
not_ok |= !entry->obj->ops->signaled( entry->obj, entry );
|
||||
if (not_ok) goto other_checks;
|
||||
/* Wait satisfied: tell it to all objects */
|
||||
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
||||
entry->obj->ops->satisfied( entry->obj, entry );
|
||||
return wait->abandoned ? STATUS_ABANDONED_WAIT_0 : STATUS_WAIT_0;
|
||||
if (!not_ok) return STATUS_WAIT_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
||||
{
|
||||
if (!entry->obj->ops->signaled( entry->obj, entry )) continue;
|
||||
/* Wait satisfied: tell it to the object */
|
||||
entry->obj->ops->satisfied( entry->obj, entry );
|
||||
if (wait->abandoned) i += STATUS_ABANDONED_WAIT_0;
|
||||
return i;
|
||||
}
|
||||
if (entry->obj->ops->signaled( entry->obj, entry )) return i;
|
||||
}
|
||||
|
||||
other_checks:
|
||||
if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
|
||||
if (wait->timeout <= current_time) return STATUS_TIMEOUT;
|
||||
return -1;
|
||||
|
@ -728,8 +733,8 @@ int wake_thread( struct thread *thread )
|
|||
if ((signaled = check_wait( thread )) == -1) break;
|
||||
|
||||
cookie = thread->wait->cookie;
|
||||
signaled = end_wait( thread, signaled );
|
||||
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
|
||||
end_wait( thread );
|
||||
if (cookie && send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
|
||||
{
|
||||
if (!count) count = -1;
|
||||
|
@ -752,13 +757,9 @@ int wake_thread_queue_entry( struct wait_queue_entry *entry )
|
|||
|
||||
assert( wait->select != SELECT_WAIT_ALL );
|
||||
|
||||
signaled = entry - wait->queues;
|
||||
entry->obj->ops->satisfied( entry->obj, entry );
|
||||
if (wait->abandoned) signaled += STATUS_ABANDONED_WAIT_0;
|
||||
|
||||
cookie = wait->cookie;
|
||||
signaled = end_wait( thread, entry - wait->queues );
|
||||
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
|
||||
end_wait( thread );
|
||||
|
||||
if (!cookie || send_thread_wakeup( thread, cookie, signaled ) != -1)
|
||||
wake_thread( thread ); /* check other waits too */
|
||||
|
@ -778,7 +779,7 @@ static void thread_timeout( void *ptr )
|
|||
if (thread->suspend + thread->process->suspend > 0) return; /* suspended, ignore it */
|
||||
|
||||
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=TIMEOUT\n", thread->id );
|
||||
end_wait( thread );
|
||||
end_wait( thread, STATUS_TIMEOUT );
|
||||
|
||||
assert( cookie );
|
||||
if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return;
|
||||
|
@ -836,7 +837,7 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c
|
|||
{
|
||||
if (!signal_object( select_op->signal_and_wait.signal ))
|
||||
{
|
||||
end_wait( current );
|
||||
end_wait( current, get_error() );
|
||||
return timeout;
|
||||
}
|
||||
/* check if we woke ourselves up */
|
||||
|
@ -863,8 +864,7 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c
|
|||
if ((ret = check_wait( current )) != -1)
|
||||
{
|
||||
/* condition is already satisfied */
|
||||
end_wait( current );
|
||||
set_error( ret );
|
||||
set_error( end_wait( current, ret ));
|
||||
return timeout;
|
||||
}
|
||||
|
||||
|
@ -874,7 +874,7 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c
|
|||
if (!(current->wait->user = add_timeout_user( current->wait->timeout,
|
||||
thread_timeout, current->wait )))
|
||||
{
|
||||
end_wait( current );
|
||||
end_wait( current, get_error() );
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
|
@ -1106,7 +1106,7 @@ void kill_thread( struct thread *thread, int violent_death )
|
|||
thread->id, thread->exit_code );
|
||||
if (thread->wait)
|
||||
{
|
||||
while (thread->wait) end_wait( thread );
|
||||
while (thread->wait) end_wait( thread, STATUS_THREAD_IS_TERMINATING );
|
||||
send_thread_wakeup( thread, 0, thread->exit_code );
|
||||
/* if it is waiting on the socket, we don't need to send a SIGQUIT */
|
||||
violent_death = 0;
|
||||
|
|
Loading…
Reference in New Issue