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