From 51447083920885defa679d88579e13f838a2494c Mon Sep 17 00:00:00 2001 From: Sebastian Lackner <sebastian@fds-team.de> Date: Sat, 20 Aug 2016 21:22:54 +0200 Subject: [PATCH] ntdll/tests: Add tests for releasing threadpool objects during TpReleaseCleanupGroupMembers. Signed-off-by: Sebastian Lackner <sebastian@fds-team.de> Signed-off-by: Alexandre Julliard <julliard@winehq.org> --- dlls/ntdll/tests/threadpool.c | 109 +++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c index 9b4b522bc9f..7672d632b7a 100644 --- a/dlls/ntdll/tests/threadpool.c +++ b/dlls/ntdll/tests/threadpool.c @@ -1,7 +1,7 @@ /* * Unit test suite for thread pool functions * - * Copyright 2015 Sebastian Lackner + * Copyright 2015-2016 Sebastian Lackner * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -705,6 +705,112 @@ static void test_tp_work_scheduler(void) pTpReleasePool(pool); } +static void CALLBACK work_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_WORK *work) +{ + HANDLE semaphore = userdata; + trace("Running work release callback\n"); + ReleaseSemaphore(semaphore, 1, NULL); + Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */ + pTpReleaseWork(work); +} + +static void CALLBACK timer_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_TIMER *timer) +{ + HANDLE semaphore = userdata; + trace("Running timer release callback\n"); + ReleaseSemaphore(semaphore, 1, NULL); + Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */ + pTpReleaseTimer(timer); +} + +static void CALLBACK wait_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, + TP_WAIT *wait, TP_WAIT_RESULT result) +{ + HANDLE semaphore = userdata; + trace("Running wait release callback\n"); + ReleaseSemaphore(semaphore, 1, NULL); + Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */ + pTpReleaseWait(wait); +} + +static void test_tp_group_wait(void) +{ + TP_CALLBACK_ENVIRON environment; + TP_CLEANUP_GROUP *group; + LARGE_INTEGER when; + HANDLE semaphore; + NTSTATUS status; + TP_TIMER *timer; + TP_WAIT *wait; + TP_WORK *work; + TP_POOL *pool; + DWORD result; + + semaphore = CreateSemaphoreA(NULL, 0, 1, NULL); + ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError()); + + /* allocate new threadpool */ + pool = NULL; + status = pTpAllocPool(&pool, NULL); + ok(!status, "TpAllocPool failed with status %x\n", status); + ok(pool != NULL, "expected pool != NULL\n"); + + /* allocate a cleanup group */ + group = NULL; + status = pTpAllocCleanupGroup(&group); + ok(!status, "TpAllocCleanupGroup failed with status %x\n", status); + ok(group != NULL, "expected pool != NULL\n"); + + /* release work object during TpReleaseCleanupGroupMembers */ + work = NULL; + memset(&environment, 0, sizeof(environment)); + environment.Version = 1; + environment.Pool = pool; + environment.CleanupGroup = group; + status = pTpAllocWork(&work, work_release_cb, semaphore, &environment); + ok(!status, "TpAllocWork failed with status %x\n", status); + ok(work != NULL, "expected work != NULL\n"); + pTpPostWork(work); + result = WaitForSingleObject(semaphore, 1000); + ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); + pTpReleaseCleanupGroupMembers(group, FALSE, NULL); + + /* release timer object during TpReleaseCleanupGroupMembers */ + timer = NULL; + memset(&environment, 0, sizeof(environment)); + environment.Version = 1; + environment.Pool = pool; + environment.CleanupGroup = group; + status = pTpAllocTimer(&timer, timer_release_cb, semaphore, &environment); + ok(!status, "TpAllocTimer failed with status %x\n", status); + ok(timer != NULL, "expected timer != NULL\n"); + when.QuadPart = 0; + pTpSetTimer(timer, &when, 0, 0); + result = WaitForSingleObject(semaphore, 1000); + ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); + pTpReleaseCleanupGroupMembers(group, FALSE, NULL); + + /* release wait object during TpReleaseCleanupGroupMembers */ + wait = NULL; + memset(&environment, 0, sizeof(environment)); + environment.Version = 1; + environment.Pool = pool; + environment.CleanupGroup = group; + status = pTpAllocWait(&wait, wait_release_cb, semaphore, &environment); + ok(!status, "TpAllocWait failed with status %x\n", status); + ok(wait != NULL, "expected wait != NULL\n"); + when.QuadPart = 0; + pTpSetWait(wait, INVALID_HANDLE_VALUE, &when); + result = WaitForSingleObject(semaphore, 1000); + ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); + pTpReleaseCleanupGroupMembers(group, FALSE, NULL); + + /* cleanup */ + pTpReleaseCleanupGroup(group); + pTpReleasePool(pool); + CloseHandle(semaphore); +} + static DWORD group_cancel_tid; static void CALLBACK group_cancel_cb(TP_CALLBACK_INSTANCE *instance, void *userdata) @@ -1679,6 +1785,7 @@ START_TEST(threadpool) test_tp_simple(); test_tp_work(); test_tp_work_scheduler(); + test_tp_group_wait(); test_tp_group_cancel(); test_tp_instance(); test_tp_disassociate(); -- GitLab