[PATCH v3 1/2] ws2_32/tests: Add tests for terminated thread asyncs completion.

Paul Gofman wine at gitlab.winehq.org
Fri Jun 3 15:12:06 CDT 2022


From: Paul Gofman <pgofman at codeweavers.com>

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ws2_32/tests/afd.c | 159 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)

diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c
index 5b64ccd7715..b8579a7c9f7 100644
--- a/dlls/ws2_32/tests/afd.c
+++ b/dlls/ws2_32/tests/afd.c
@@ -2355,6 +2355,164 @@ static void test_getsockname(void)
     CloseHandle(event);
 }
 
+struct ioctl_params
+{
+    HANDLE handle, event;
+    PIO_APC_ROUTINE apc;
+    void *apc_context;
+    IO_STATUS_BLOCK *io;
+    ULONG code;
+    void *in_buffer;
+    ULONG in_size;
+    void *out_buffer;
+    ULONG out_size;
+    NTSTATUS ret;
+    HANDLE complete_event;
+    BOOL kill_thread;
+};
+
+static DWORD WINAPI async_ioctl_thread(void *params)
+{
+    struct ioctl_params *io = params;
+
+    io->ret = NtDeviceIoControlFile(io->handle, io->event, io->apc, io->apc_context, io->io,
+            io->code, io->in_buffer, io->in_size, io->out_buffer, io->out_size);
+    SetEvent(io->complete_event);
+    if (io->kill_thread)
+        Sleep(3000);
+    return io->ret;
+}
+
+static NTSTATUS WINAPI thread_NtDeviceIoControlFile(BOOL kill_thread, HANDLE handle, HANDLE event,
+        PIO_APC_ROUTINE apc, void *apc_context, IO_STATUS_BLOCK *io, ULONG code, void *in_buffer, ULONG in_size,
+        void *out_buffer, ULONG out_size)
+{
+    struct ioctl_params p;
+    HANDLE thread;
+    DWORD ret;
+
+    p.handle = handle;
+    p.event = event;
+    p.apc = apc;
+    p.apc_context = apc_context;
+    p.io = io;
+    p.code = code;
+    p.in_buffer = in_buffer;
+    p.in_size = in_size;
+    p.out_buffer = out_buffer;
+    p.out_size = out_size;
+    p.complete_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    p.kill_thread = kill_thread;
+
+    thread = CreateThread(NULL, 0, async_ioctl_thread, &p, 0, NULL);
+    ok(!!thread, "got NULL.\n");
+    ret = WaitForSingleObject(p.complete_event, INFINITE);
+    ok(ret == WAIT_OBJECT_0, "got ret %#lx.\n", ret);
+    if (kill_thread)
+        TerminateThread(thread, -1);
+    CloseHandle(p.complete_event);
+    ret = WaitForSingleObject(thread, INFINITE);
+    ok(ret == WAIT_OBJECT_0, "got ret %#lx.\n", ret);
+    CloseHandle(thread);
+    return p.ret;
+}
+
+static void test_async_thread_termination(void)
+{
+    const struct sockaddr_in bind_addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+    char in_buffer[offsetof(struct afd_poll_params, sockets[3])];
+    char out_buffer[offsetof(struct afd_poll_params, sockets[3])];
+    struct afd_poll_params *in_params = (struct afd_poll_params *)in_buffer;
+    struct afd_poll_params *out_params = (struct afd_poll_params *)out_buffer;
+    LARGE_INTEGER zero = {{0}};
+    ULONG_PTR key, value;
+    IO_STATUS_BLOCK io;
+    HANDLE event, port;
+    ULONG params_size;
+    SOCKET listener;
+    int ret;
+
+    event = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+    listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    ret = bind(listener, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
+    ok(!ret, "got error %u\n", WSAGetLastError());
+    ret = listen(listener, 1);
+    ok(!ret, "got error %u\n", WSAGetLastError());
+
+    in_params->count = 1;
+    in_params->exclusive = FALSE;
+    in_params->sockets[0].socket = listener;
+    in_params->sockets[0].flags = ~0;
+    in_params->sockets[0].status = 0xdeadbeef;
+    params_size = offsetof(struct afd_poll_params, sockets[1]);
+    in_params->timeout = -10 * 1000 * 1000 * 5;
+
+    memset(&io, 0xcc, sizeof(io));
+    ret = thread_NtDeviceIoControlFile(TRUE, (HANDLE)listener, event, NULL, NULL, &io,
+            IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
+    ok(ret == STATUS_PENDING, "got %#x\n", ret);
+    ret = WaitForSingleObject(event, 1000);
+    todo_wine ok(!ret, "got %#x\n", ret);
+    todo_wine ok(io.Status == STATUS_CANCELLED, "got %#lx\n", io.Status);
+
+    memset(&io, 0xcc, sizeof(io));
+    ret = thread_NtDeviceIoControlFile(FALSE, (HANDLE)listener, event, NULL, NULL, &io,
+            IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
+    ok(ret == STATUS_PENDING, "got %#x\n", ret);
+    ret = WaitForSingleObject(event, 1000);
+    todo_wine ok(!ret, "got %#x\n", ret);
+    todo_wine ok(io.Status == STATUS_CANCELLED, "got %#lx\n", io.Status);
+
+    port = CreateIoCompletionPort((HANDLE)listener, NULL, 0, 0);
+
+    memset(&io, 0xcc, sizeof(io));
+    ret = thread_NtDeviceIoControlFile(TRUE, (HANDLE)listener, event, NULL, (void *)0xdeadbeef, &io,
+            IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
+    ok(ret == STATUS_PENDING, "got %#x\n", ret);
+
+    ret = WaitForSingleObject(event, 1000);
+    todo_wine ok(!ret, "got %#x\n", ret);
+    todo_wine ok(io.Status == STATUS_CANCELLED, "got %#lx\n", io.Status);
+
+    memset(&io, 0xcc, sizeof(io));
+    key = 0xcc;
+    value = 0;
+    ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero);
+    todo_wine
+    {
+        ok(!ret, "got %#x\n", ret);
+        ok(!key, "got key %#Ix\n", key);
+        ok(value == 0xdeadbeef, "got value %#Ix\n", value);
+        ok(io.Status == STATUS_CANCELLED, "got %#lx\n", io.Status);
+    }
+
+    memset(&io, 0xcc, sizeof(io));
+    ret = thread_NtDeviceIoControlFile(FALSE, (HANDLE)listener, event, NULL, (void *)0xdeadbeef, &io,
+            IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
+    ok(ret == STATUS_PENDING, "got %#x\n", ret);
+
+    ret = WaitForSingleObject(event, 1000);
+    todo_wine ok(!ret, "got %#x\n", ret);
+    todo_wine ok(io.Status == STATUS_CANCELLED, "got %#lx\n", io.Status);
+
+    memset(&io, 0xcc, sizeof(io));
+    key = 0xcc;
+    value = 0;
+    ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero);
+    todo_wine
+    {
+        ok(!ret, "got %#x\n", ret);
+        ok(!key, "got key %#Ix\n", key);
+        ok(value == 0xdeadbeef, "got value %#Ix\n", value);
+        ok(io.Status == STATUS_CANCELLED, "got %#lx\n", io.Status);
+    }
+
+    CloseHandle(port);
+    CloseHandle(event);
+    closesocket(listener);
+}
+
 START_TEST(afd)
 {
     WSADATA data;
@@ -2372,6 +2530,7 @@ START_TEST(afd)
     test_get_events_reset();
     test_bind();
     test_getsockname();
+    test_async_thread_termination();
 
     WSACleanup();
 }
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/135



More information about the wine-devel mailing list