[PATCH v2 3/3] ntdll/tests: Add a test for closing a completion port being waited on.
Alexey Prokhin
alexey at prokhin.ru
Wed Apr 29 10:26:42 CDT 2020
The test reproduces a hang by Planet Zoo when exiting the game.
Signed-off-by: Alexey Prokhin <alexey at prokhin.ru>
---
v2: Update kernelbase patch. Supersedes 184509
Given it is one of my first contributions to wine, I have a few
questions/notes:
1.
> LPTHREAD_START_ROUTINE test_routines[] = {
I didn't find such pattern anywhere else in the tests, but I hope
it's ok.
2.
> ok( info[0].CompletionKey == 0xdeadbeef || info[0].CompletionKey == 0,
I am not sure if info should be checked at all in the case. And if
it is, should I mark the second equality as broken? (Because info
is only zeroed out on win server 2008)
3. Is it ok there is a test for GetQueuedCompletionStatus. Or
should it be moved to kernelbase?
4. Should a test for GetQueuedCompletionStatusEx also be added?
---
dlls/ntdll/tests/file.c | 101 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 31c18454f0..c5fb28e16f 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -4953,6 +4953,106 @@ static void test_file_readonly_access(void)
DeleteFileW(path);
}
+static DWORD WINAPI io_thread_NtRemoveIoCompletion(void *data)
+{
+ LARGE_INTEGER timeout;
+ IO_STATUS_BLOCK iosb;
+ ULONG_PTR key, value;
+ HANDLE h = data;
+ NTSTATUS res;
+
+ timeout.QuadPart = -30000000;
+ res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout );
+ ok( res == STATUS_ABANDONED_WAIT_0 || broken( res == STATUS_TIMEOUT ), /* XP/2003 */
+ "expected STATUS_ABANDONED_WAIT_0, got %#x\n", res );
+ /* key, value and iosb either are unchanged or contain garbage */
+
+ return 0;
+}
+
+static DWORD WINAPI io_thread_NtRemoveIoCompletionEx(void *data)
+{
+ FILE_IO_COMPLETION_INFORMATION info[2] = {{0}};
+ LARGE_INTEGER timeout;
+ HANDLE h = data;
+ NTSTATUS res;
+ ULONG count;
+
+ if (!pNtRemoveIoCompletionEx)
+ {
+ skip("NtRemoveIoCompletionEx() not present\n");
+ return 1;
+ }
+
+ timeout.QuadPart = -30000000;
+ count = 0xdeadbeef;
+ info[0].CompletionKey = 0xdeadbeef;
+ info[0].CompletionValue = 0xdeadbeef;
+ info[0].IoStatusBlock.Information = 0xdeadbeef;
+ U(info[0].IoStatusBlock).Status = 0xdeadbeef;
+
+ res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE );
+ ok( res == STATUS_ABANDONED_WAIT_0, "expected STATUS_ABANDONED_WAIT_0, got %#x\n", res );
+ ok( count == 1, "wrong count %u\n", count );
+ ok( info[0].CompletionKey == 0xdeadbeef || info[0].CompletionKey == 0,
+ "wrong key %#lx\n", info[0].CompletionKey );
+ ok( info[0].CompletionValue == 0xdeadbeef || info[0].CompletionValue == 0,
+ "wrong value %#lx\n", info[0].CompletionValue );
+ ok( info[0].IoStatusBlock.Information == 0xdeadbeef || info[0].IoStatusBlock.Information == 0,
+ "wrong information %#lx\n", info[0].IoStatusBlock.Information );
+ ok( U(info[0].IoStatusBlock).Status == 0xdeadbeef || U(info[0].IoStatusBlock).Status == 0,
+ "wrong status %#x\n", U(info[0].IoStatusBlock).Status);
+
+ return 0;
+}
+
+static DWORD WINAPI io_thread_GetQueuedCompletionStatus(void *data)
+{
+ HANDLE h = data;
+ OVERLAPPED *pov;
+ NTSTATUS error;
+ ULONG_PTR key;
+ DWORD count;
+ BOOL ret;
+
+ pov = (void *)0xdeadbeaf;
+ SetLastError(0xdeadbeef);
+ ret = GetQueuedCompletionStatus( h, &count, &key, &pov, 3000 );
+ error = GetLastError();
+ ok( !ret, "GetQueuedCompletionStatus succeeded\n" );
+ ok( error == ERROR_ABANDONED_WAIT_0 || broken( error == WAIT_TIMEOUT ), /* XP/2003 */
+ "expected ERROR_ABANDONED_WAIT_0, got %#x\n", error );
+ ok( pov == NULL, "expected NULL, got %p\n", pov );
+
+ return 0;
+}
+
+static void test_close_io_completion(void)
+{
+ HANDLE h, hThread;
+ NTSTATUS res;
+ LPTHREAD_START_ROUTINE test_routines[] = {
+ io_thread_NtRemoveIoCompletion,
+ io_thread_NtRemoveIoCompletionEx,
+ io_thread_GetQueuedCompletionStatus
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(test_routines); ++i)
+ {
+ res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
+ ok( res == STATUS_SUCCESS, "%d: NtCreateIoCompletion failed: %#x\n", i, res );
+ ok( h && h != INVALID_HANDLE_VALUE, "%d: got invalid handle %p\n", i, h );
+
+ hThread = CreateThread( NULL, 0, test_routines[i], h, 0, NULL );
+ Sleep( 400 );
+
+ CloseHandle( h );
+
+ ok( WaitForSingleObject( hThread, 10000 ) == 0, "%d: wait failed\n", i );
+ CloseHandle( hThread );
+ }
+}
+
START_TEST(file)
{
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
@@ -5023,4 +5123,5 @@ START_TEST(file)
test_query_attribute_information_file();
test_ioctl();
test_flush_buffers_file();
+ test_close_io_completion();
}
--
2.26.2
More information about the wine-devel
mailing list