server: Allow suspended threads to run system APCs.

This commit is contained in:
Alexandre Julliard 2007-01-10 21:55:23 +01:00
parent 443a5dbd80
commit 2520e387a1
2 changed files with 12 additions and 4 deletions

View File

@ -161,7 +161,7 @@ void wait_suspend( CONTEXT *context )
/* wait with 0 timeout, will only return once the thread is no longer suspended */ /* wait with 0 timeout, will only return once the thread is no longer suspended */
timeout.QuadPart = 0; timeout.QuadPart = 0;
NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout, 0 ); NTDLL_wait_for_multiple_objects( 0, NULL, SELECT_INTERRUPTIBLE, &timeout, 0 );
/* retrieve the new context */ /* retrieve the new context */
SERVER_START_REQ( get_thread_context ) SERVER_START_REQ( get_thread_context )

View File

@ -470,8 +470,13 @@ static int check_wait( struct thread *thread )
struct thread_wait *wait = thread->wait; struct thread_wait *wait = thread->wait;
struct wait_queue_entry *entry = wait->queues; struct wait_queue_entry *entry = wait->queues;
/* Suspended threads may not acquire locks */ /* Suspended threads may not acquire locks, but they can run system APCs */
if (thread->process->suspend + thread->suspend > 0) return -1; if (thread->process->suspend + thread->suspend > 0)
{
if ((wait->flags & SELECT_INTERRUPTIBLE) && !list_empty( &thread->system_apc ))
return STATUS_USER_APC;
return -1;
}
assert( wait ); assert( wait );
if (wait->flags & SELECT_ALL) if (wait->flags & SELECT_ALL)
@ -1077,6 +1082,7 @@ DECL_HANDLER(queue_apc)
DECL_HANDLER(get_apc) DECL_HANDLER(get_apc)
{ {
struct thread_apc *apc; struct thread_apc *apc;
int system_only = !req->alertable;
if (req->prev) if (req->prev)
{ {
@ -1088,9 +1094,11 @@ DECL_HANDLER(get_apc)
release_object( apc ); release_object( apc );
} }
if (current->suspend + current->process->suspend > 0) system_only = 1;
for (;;) for (;;)
{ {
if (!(apc = thread_dequeue_apc( current, !req->alertable ))) if (!(apc = thread_dequeue_apc( current, system_only )))
{ {
/* no more APCs */ /* no more APCs */
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );