Sebastian Lackner : ntdll: Wait_thread_proc should not terminate on user APC.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Oct 9 09:55:21 CDT 2015
Module: wine
Branch: master
Commit: 381c034be3698231e71d20062985a5005c3b32a8
URL: http://source.winehq.org/git/wine.git/?a=commit;h=381c034be3698231e71d20062985a5005c3b32a8
Author: Sebastian Lackner <sebastian at fds-team.de>
Date: Fri Oct 9 06:37:57 2015 +0200
ntdll: Wait_thread_proc should not terminate on user APC.
Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/tests/threadpool.c | 68 +++++++++++++++++++++++++++++++++++++++++--
dlls/ntdll/threadpool.c | 2 +-
2 files changed, 67 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
index d4e13bd..304fe91 100644
--- a/dlls/ntdll/tests/threadpool.c
+++ b/dlls/ntdll/tests/threadpool.c
@@ -148,6 +148,7 @@ struct rtl_wait_info
HANDLE semaphore1;
HANDLE semaphore2;
DWORD wait_result;
+ DWORD threadid;
LONG userdata;
};
@@ -162,6 +163,7 @@ static void CALLBACK rtl_wait_cb(void *userdata, BOOLEAN timeout)
InterlockedIncrement(&info->userdata);
else
InterlockedExchangeAdd(&info->userdata, 0x10000);
+ info->threadid = GetCurrentThreadId();
ReleaseSemaphore(info->semaphore1, 1, NULL);
if (info->semaphore2)
@@ -172,14 +174,22 @@ static void CALLBACK rtl_wait_cb(void *userdata, BOOLEAN timeout)
}
}
+static HANDLE rtl_wait_apc_semaphore;
+
+static void CALLBACK rtl_wait_apc_cb(ULONG_PTR userdata)
+{
+ trace("Running rtl_wait_apc callback\n");
+ if (rtl_wait_apc_semaphore)
+ ReleaseSemaphore(rtl_wait_apc_semaphore, 1, NULL);
+}
+
static void test_RtlRegisterWait(void)
{
+ HANDLE wait1, event, thread;
struct rtl_wait_info info;
HANDLE semaphores[2];
NTSTATUS status;
DWORD result;
- HANDLE wait1;
- HANDLE event;
semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL);
ok(semaphores[0] != NULL, "failed to create semaphore\n");
@@ -270,6 +280,60 @@ static void test_RtlRegisterWait(void)
status = RtlDeregisterWait(wait1);
ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+ /* test for IO threads */
+ info.userdata = 0;
+ info.threadid = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEINIOTHREAD);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ ok(info.threadid != 0, "expected info.threadid != 0, got %u\n", info.threadid);
+ thread = OpenThread(THREAD_SET_CONTEXT, FALSE, info.threadid);
+ ok(thread != NULL, "OpenThread failed with %u\n", GetLastError());
+ rtl_wait_apc_semaphore = semaphores[0];
+ result = QueueUserAPC(rtl_wait_apc_cb, thread, 0);
+ ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
+ result = WaitForSingleObject(semaphores[0], 200);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ rtl_wait_apc_semaphore = 0;
+ CloseHandle(thread);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 2, "expected info.userdata = 2, got %u\n", info.userdata);
+ Sleep(50);
+ status = RtlDeregisterWait(wait1);
+ ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+
+ info.userdata = 0;
+ info.threadid = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEDEFAULT);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ ok(info.threadid != 0, "expected info.threadid != 0, got %u\n", info.threadid);
+ thread = OpenThread(THREAD_SET_CONTEXT, FALSE, info.threadid);
+ ok(thread != NULL, "OpenThread failed with %u\n", GetLastError());
+ rtl_wait_apc_semaphore = semaphores[0];
+ result = QueueUserAPC(rtl_wait_apc_cb, thread, 0);
+ ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
+ result = WaitForSingleObject(semaphores[0], 200);
+ ok(result == WAIT_TIMEOUT || broken(result == WAIT_OBJECT_0) /* >= Win Vista */,
+ "WaitForSingleObject returned %u\n", result);
+ rtl_wait_apc_semaphore = 0;
+ CloseHandle(thread);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 2, "expected info.userdata = 2, got %u\n", info.userdata);
+ Sleep(50);
+ status = RtlDeregisterWait(wait1);
+ ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+
/* test RtlDeregisterWaitEx before wait expired */
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEDEFAULT);
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c
index 0ed0851..9c98040 100644
--- a/dlls/ntdll/threadpool.c
+++ b/dlls/ntdll/threadpool.c
@@ -537,7 +537,7 @@ static DWORD CALLBACK wait_thread_proc(LPVOID Arg)
if (wait_work_item->Flags & WT_EXECUTEONLYONCE)
break;
}
- else
+ else if (status != STATUS_USER_APC)
break;
}
More information about the wine-cvs
mailing list