Commit 44fc4488 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

server: Always set the async result when the APC object is destroyed.

This can happen if the async is terminated while there is no thread to queue the APC to (as in the relevant test), or if the client dies before getting the APC, or before transferring the APC results back to the server. This also fixes a leak of async objects present since 61abc500. If a process dies while accept asyncs are pending, the asyncs will be terminated but will not find a valid thread to queue the APC to, and thus async_set_result() and the completion callback are never called. Signed-off-by: 's avatarZebediah Figura <z.figura12@gmail.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 4eddeff1
......@@ -4168,9 +4168,9 @@ static void test_exit_process_async(void)
size = 0xdeadbeef;
ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped, 1000);
ok(!ret, "expected failure\n");
todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "got error %u\n", GetLastError());
todo_wine ok(!size, "got size %u\n", size);
todo_wine ok(key == 123, "got key %Iu\n", key);
ok(GetLastError() == ERROR_OPERATION_ABORTED, "got error %u\n", GetLastError());
ok(!size, "got size %u\n", size);
ok(key == 123, "got key %Iu\n", key);
CloseHandle(port);
CloseHandle(server);
......
......@@ -490,8 +490,16 @@ static int thread_apc_signaled( struct object *obj, struct wait_queue_entry *ent
static void thread_apc_destroy( struct object *obj )
{
struct thread_apc *apc = (struct thread_apc *)obj;
if (apc->caller) release_object( apc->caller );
if (apc->owner) release_object( apc->owner );
if (apc->owner)
{
if (apc->result.type == APC_ASYNC_IO)
async_set_result( apc->owner, apc->result.async_io.status, apc->result.async_io.total );
else if (apc->call.type == APC_ASYNC_IO)
async_set_result( apc->owner, apc->call.async_io.status, 0 );
release_object( apc->owner );
}
}
/* queue an async procedure call */
......@@ -1649,11 +1657,6 @@ DECL_HANDLER(select)
apc->result.create_thread.handle = handle;
clear_error(); /* ignore errors from the above calls */
}
else if (apc->result.type == APC_ASYNC_IO)
{
if (apc->owner)
async_set_result( apc->owner, apc->result.async_io.status, apc->result.async_io.total );
}
wake_up( &apc->obj, 0 );
close_handle( current->process, req->prev_apc );
release_object( apc );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment