forked from Mirrors/wine-wine
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>oldstable
parent
f91a7b2cfe
commit
659e585166
|
@ -56,6 +56,9 @@ static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK);
|
||||||
static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
|
static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
|
||||||
static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK);
|
static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK);
|
||||||
static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(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 NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
|
||||||
|
|
||||||
static void test_signalandwait(void)
|
static void test_signalandwait(void)
|
||||||
|
@ -2394,8 +2397,105 @@ static void test_alertable_wait(void)
|
||||||
CloseHandle(semaphores[1]);
|
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)
|
START_TEST(sync)
|
||||||
{
|
{
|
||||||
|
char **argv;
|
||||||
|
int argc;
|
||||||
HMODULE hdll = GetModuleHandleA("kernel32.dll");
|
HMODULE hdll = GetModuleHandleA("kernel32.dll");
|
||||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||||
|
|
||||||
|
@ -2424,8 +2524,21 @@ START_TEST(sync)
|
||||||
pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
|
pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
|
||||||
pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive");
|
pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive");
|
||||||
pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared");
|
pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared");
|
||||||
|
pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory");
|
||||||
|
pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory");
|
||||||
pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects");
|
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_signalandwait();
|
||||||
test_mutex();
|
test_mutex();
|
||||||
test_slist();
|
test_slist();
|
||||||
|
@ -2442,4 +2555,5 @@ START_TEST(sync)
|
||||||
test_srwlock_base();
|
test_srwlock_base();
|
||||||
test_srwlock_example();
|
test_srwlock_example();
|
||||||
test_alertable_wait();
|
test_alertable_wait();
|
||||||
|
test_apc_deadlock();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue