kernel32/tests: Add a test to demonstrate a deadlock by suspending a thread during a system APC.
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f91a7b2cfe
commit
659e585166
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue