From fa9bbe8a226e3b4cad078155887f25be280a87f5 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Wed, 28 Jul 2021 01:07:00 +0300 Subject: [PATCH] ntdll: Only queue IO callback if IO is pending in ioqueue_thread_proc(). Signed-off-by: Paul Gofman Signed-off-by: Alexandre Julliard --- dlls/ntdll/tests/threadpool.c | 18 ++++++++++++++++++ dlls/ntdll/threadpool.c | 31 ++++++++++++++++++------------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c index 6b301eafcbd..986cbbcf8f1 100644 --- a/dlls/ntdll/tests/threadpool.c +++ b/dlls/ntdll/tests/threadpool.c @@ -2139,6 +2139,24 @@ static void test_tp_io(void) ok(!userdata.length, "got length %lu\n", userdata.length); ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io); + userdata.count = 0; + pTpStartAsyncIoOperation(io); + pTpCancelAsyncIoOperation(io); + ret = ReadFile(server, in, sizeof(in), NULL, &ovl); + ok(!ret, "wrong ret %d\n", ret); + ret = WriteFile(client, out, sizeof(out), &ret_size, NULL); + ok(ret, "WriteFile() failed, error %u\n", GetLastError()); + ok(GetLastError() == ERROR_IO_PENDING, "wrong error %u\n", GetLastError()); + + pTpWaitForIoCompletion(io, FALSE); + if (0) + { + /* Add a sleep to check that callback is not called later. Commented out to + * save the test time. */ + Sleep(200); + } + ok(userdata.count == 0, "callback ran %u times\n", userdata.count); + CloseHandle(ovl.hEvent); CloseHandle(client); CloseHandle(server); diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index b82d06e5e42..c27f6d4a145 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -1536,22 +1536,25 @@ static void CALLBACK ioqueue_thread_proc( void *param ) { RtlEnterCriticalSection( &io->pool->cs ); - --io->u.io.pending_count; + TRACE( "pending_count %u.\n", io->u.io.pending_count ); - if (!array_reserve((void **)&io->u.io.completions, &io->u.io.completion_max, - io->u.io.completion_count + 1, sizeof(*io->u.io.completions))) + if (io->u.io.pending_count) { - ERR("Failed to allocate memory.\n"); - RtlLeaveCriticalSection( &io->pool->cs ); - continue; + --io->u.io.pending_count; + if (!array_reserve((void **)&io->u.io.completions, &io->u.io.completion_max, + io->u.io.completion_count + 1, sizeof(*io->u.io.completions))) + { + ERR( "Failed to allocate memory.\n" ); + RtlLeaveCriticalSection( &io->pool->cs ); + continue; + } + + completion = &io->u.io.completions[io->u.io.completion_count++]; + completion->iosb = iosb; + completion->cvalue = value; + + tp_object_submit( io, FALSE ); } - - completion = &io->u.io.completions[io->u.io.completion_count++]; - completion->iosb = iosb; - completion->cvalue = value; - - tp_object_submit( io, FALSE ); - RtlLeaveCriticalSection( &io->pool->cs ); } @@ -2525,6 +2528,8 @@ void WINAPI TpCancelAsyncIoOperation( TP_IO *io ) RtlEnterCriticalSection( &this->pool->cs ); + TRACE("pending_count %u.\n", this->u.io.pending_count); + this->u.io.pending_count--; if (object_is_finished( this, TRUE )) RtlWakeAllConditionVariable( &this->group_finished_event );