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

Alexandre Julliard julliard at winehq.org
Thu Feb 25 16:45:36 CST 2021


Module: wine
Branch: master
Commit: 44fc44880f2074cbc3c586ffc8dea009608b63dc
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=44fc44880f2074cbc3c586ffc8dea009608b63dc

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Wed Feb 24 16:11:35 2021 -0600

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 61abc500f5. 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: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/pipe.c |  6 +++---
 server/thread.c            | 15 +++++++++------
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index f1feb6c53f0..0ac356c8483 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -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);
diff --git a/server/thread.c b/server/thread.c
index 3cee717e169..d544970f3c1 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -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 );




More information about the wine-cvs mailing list