Sebastian Lackner : kernel32/tests: Add a test to demonstrate a deadlock by suspending a thread during a system APC.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Nov 5 10:14:54 CST 2015


Module: wine
Branch: master
Commit: 659e585166d3440665588de939652294a5fd2e01
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=659e585166d3440665588de939652294a5fd2e01

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Thu Nov  5 05:41:43 2015 +0100

kernel32/tests: Add a test to demonstrate a deadlock by suspending a thread during a system APC.

Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/sync.c | 114 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index 1065d5e..4ac6a99 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -56,6 +56,9 @@ static VOID   (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK);
 static VOID   (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
 static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK);
 static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK);
+
+static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
+static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
 static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
 
 static void test_signalandwait(void)
@@ -2394,8 +2397,105 @@ static void test_alertable_wait(void)
     CloseHandle(semaphores[1]);
 }
 
+struct apc_deadlock_info
+{
+    PROCESS_INFORMATION *pi;
+    HANDLE event;
+    BOOL running;
+};
+
+static DWORD WINAPI apc_deadlock_thread(void *param)
+{
+    struct apc_deadlock_info *info = param;
+    PROCESS_INFORMATION *pi = info->pi;
+    NTSTATUS status;
+    SIZE_T size;
+    void *base;
+
+    while (info->running)
+    {
+        base = NULL;
+        size = 0x1000;
+        status = pNtAllocateVirtualMemory(pi->hProcess, &base, 0, &size,
+                                          MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+        ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
+        ok(base != NULL, "expected base != NULL, got %p\n", base);
+        SetEvent(info->event);
+
+        size = 0;
+        status = pNtFreeVirtualMemory(pi->hProcess, &base, &size, MEM_RELEASE);
+        ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
+        SetEvent(info->event);
+    }
+
+    return 0;
+}
+
+static void test_apc_deadlock(void)
+{
+    struct apc_deadlock_info info;
+    PROCESS_INFORMATION pi;
+    STARTUPINFOA si = { sizeof(si) };
+    char cmdline[MAX_PATH];
+    HANDLE event, thread;
+    DWORD result;
+    BOOL success;
+    char **argv;
+    int i;
+
+    winetest_get_mainargs(&argv);
+    sprintf(cmdline, "\"%s\" sync apc_deadlock", argv[0]);
+    success = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    ok(success, "CreateProcess failed with %u\n", GetLastError());
+
+    event = CreateEventA(NULL, FALSE, FALSE, NULL);
+    ok(event != NULL, "CreateEvent failed with %u\n", GetLastError());
+
+    info.pi = π
+    info.event = event;
+    info.running = TRUE;
+
+    thread = CreateThread(NULL, 0, apc_deadlock_thread, &info, 0, NULL);
+    ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
+    result = WaitForSingleObject(event, 1000);
+    ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
+
+    for (i = 0; i < 1000 && info.running; i++)
+    {
+        result = SuspendThread(pi.hThread);
+        ok(result == 0, "expected 0, got %u\n", result);
+
+        WaitForSingleObject(event, 0); /* reset event */
+        result = WaitForSingleObject(event, 1000);
+        if (result == WAIT_TIMEOUT)
+        {
+            todo_wine
+            ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
+            info.running = FALSE;
+        }
+        else
+            ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
+
+        result = ResumeThread(pi.hThread);
+        ok(result == 1, "expected 1, got %u\n", result);
+        Sleep(1);
+    }
+
+    info.running = FALSE;
+    result = WaitForSingleObject(thread, 1000);
+    ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
+    CloseHandle(thread);
+    CloseHandle(event);
+
+    TerminateProcess(pi.hProcess, 0);
+    CloseHandle(pi.hThread);
+    CloseHandle(pi.hProcess);
+}
+
 START_TEST(sync)
 {
+    char **argv;
+    int argc;
     HMODULE hdll = GetModuleHandleA("kernel32.dll");
     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
 
@@ -2424,8 +2524,21 @@ START_TEST(sync)
     pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
     pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive");
     pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared");
+    pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory");
+    pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory");
     pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects");
 
+    argc = winetest_get_mainargs( &argv );
+    if (argc >= 3)
+    {
+        if (!strcmp(argv[2], "apc_deadlock"))
+        {
+            HANDLE handle = GetCurrentThread();
+            for (;;) WaitForMultipleObjectsEx(1, &handle, FALSE, INFINITE, TRUE);
+        }
+        return;
+    }
+
     test_signalandwait();
     test_mutex();
     test_slist();
@@ -2442,4 +2555,5 @@ START_TEST(sync)
     test_srwlock_base();
     test_srwlock_example();
     test_alertable_wait();
+    test_apc_deadlock();
 }




More information about the wine-cvs mailing list