[PATCH 4/4] server: Do not signal completion if the async failed synchronously.

Zebediah Figura zfigura at codeweavers.com
Fri Sep 10 00:15:34 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/ntoskrnl.exe/tests/ntoskrnl.c | 14 +++++------
 server/async.c                     | 39 ++++++++++++++++++------------
 2 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index f0e8021aa17..fb91783779b 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -729,7 +729,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
         todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status);
         todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information);
         ret = WaitForSingleObject(event, 0);
-        todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
+        ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
     }
     else
     {
@@ -753,7 +753,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero);
     if (!params->pending && NT_ERROR(params->iosb_status))
     {
-        todo_wine ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
+        ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
     }
     else
     {
@@ -781,7 +781,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
         todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status);
         todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information);
         ret = WaitForSingleObject(event, 0);
-        todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
+        ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
     }
     else
     {
@@ -813,7 +813,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
         todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status);
         todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information);
         ret = WaitForSingleObject(file, 0);
-        todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
+        ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
     }
     else
     {
@@ -849,7 +849,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
             todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status);
             todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information);
             ret = WaitForSingleObject(event, 0);
-            todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
+            ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
         }
         else
         {
@@ -932,8 +932,8 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params)
     ret = SleepEx(0, TRUE);
     if (!params->pending && NT_ERROR(params->iosb_status))
     {
-        todo_wine ok(!ret, "got %d\n", ret);
-        todo_wine ok(!got_return_status_apc, "got %u APC calls\n", got_return_status_apc);
+        ok(!ret, "got %d\n", ret);
+        ok(!got_return_status_apc, "got %u APC calls\n", got_return_status_apc);
     }
     else
     {
diff --git a/server/async.c b/server/async.c
index df30ae3c7da..7cffd24a18b 100644
--- a/server/async.c
+++ b/server/async.c
@@ -465,25 +465,32 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
         async->terminated = 1;
         if (async->iosb) async->iosb->status = status;
 
-        if (async->data.apc)
+        /* don't signal completion if the async failed synchronously
+         * this can happen if the initial status was unknown (i.e. for device files)
+         * note that we check the IOSB status here, not the initial status */
+        if (async->pending || !NT_ERROR( status ))
         {
-            apc_call_t data;
-            memset( &data, 0, sizeof(data) );
-            data.type         = APC_USER;
-            data.user.func    = async->data.apc;
-            data.user.args[0] = async->data.apc_context;
-            data.user.args[1] = async->data.iosb;
-            data.user.args[2] = 0;
-            thread_queue_apc( NULL, async->thread, NULL, &data );
-        }
-        else if (async->data.apc_context && (async->pending ||
-                 !(async->comp_flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)))
-        {
-            add_async_completion( async, async->data.apc_context, status, total );
+            if (async->data.apc)
+            {
+                apc_call_t data;
+                memset( &data, 0, sizeof(data) );
+                data.type         = APC_USER;
+                data.user.func    = async->data.apc;
+                data.user.args[0] = async->data.apc_context;
+                data.user.args[1] = async->data.iosb;
+                data.user.args[2] = 0;
+                thread_queue_apc( NULL, async->thread, NULL, &data );
+            }
+            else if (async->data.apc_context && (async->pending ||
+                     !(async->comp_flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)))
+            {
+                add_async_completion( async, async->data.apc_context, status, total );
+            }
+
+            if (async->event) set_event( async->event );
+            else if (async->fd) set_fd_signaled( async->fd, 1 );
         }
 
-        if (async->event) set_event( async->event );
-        else if (async->fd) set_fd_signaled( async->fd, 1 );
         if (!async->signaled)
         {
             async->signaled = 1;
-- 
2.33.0




More information about the wine-devel mailing list