diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c index c17d2a0..5b47240 100644 --- a/dlls/kernel32/tests/pipe.c +++ b/dlls/kernel32/tests/pipe.c @@ -2801,16 +2801,28 @@ static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL test_flush_done(flush_thread); } -static void child_process_write_pipe(HANDLE pipe) +static DWORD WINAPI write_pipe_proc(HANDLE pipe) { - OVERLAPPED overlapped; - char buf[10000]; + static OVERLAPPED overlapped; + static char buf[10000]; memset(buf, 'x', sizeof(buf)); overlapped_write_async(pipe, buf, sizeof(buf), &overlapped); - /* sleep until parent process tesrminates this process. */ + /* sleep until thread is terminated */ Sleep(INFINITE); + return 1; +} + +static HANDLE tp_thread; + +static void WINAPI tp_write_pipe(TP_CALLBACK_INSTANCE *instance, void *context, TP_WORK *work) +{ + BOOL res = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), + &tp_thread, 0, FALSE, DUPLICATE_SAME_ACCESS); + ok(res, "DuplicateHandle failed: %u\n", GetLastError()); + trace("thread handle %p\n", tp_thread); + write_pipe_proc(context); } static HANDLE create_writepipe_process(HANDLE pipe) @@ -2864,8 +2876,9 @@ static void test_overlapped_transport(DWORD read_mode) OVERLAPPED overlapped, overlapped2; HANDLE server, client, flush; DWORD read_bytes; - HANDLE process; + HANDLE process, thread; char buf[60000]; + TP_WORK *tp_work; BOOL res; create_overlapped_pipe(read_mode, &client, &server); @@ -2928,6 +2941,55 @@ static void test_overlapped_transport(DWORD read_mode) CloseHandle(process); CloseHandle(server); CloseHandle(client); + + /* terminate thread with pending write */ + create_overlapped_pipe(read_mode, &client, &server); + thread = CreateThread(NULL, 0, write_pipe_proc, client, 0, NULL); + ok(thread != NULL, "CreateThread failed: %u\n", GetLastError()); + /* succesfully read part of write that is pending in different thread */ + res = ReadFile(server, buf, 10, &read_bytes, NULL); + if(read_mode == PIPE_READMODE_BYTE) + ok(res, "ReadFile failed: %u\n", GetLastError()); + else + ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %u\n", res, GetLastError()); + ok(read_bytes == 10, "read_bytes = %u\n", read_bytes); + TerminateThread(thread, 0); + WaitForSingleObject(thread, INFINITE); + /* after terminating thread, there is no pending write and pipe buffer is empty */ + overlapped_read_async(server, buf, 10, &overlapped); + overlapped_write_sync(client, buf, 1); + test_overlapped_result(server, &overlapped, 1, FALSE); + CloseHandle(thread); + CloseHandle(server); + CloseHandle(client); + + /* The code below is an ugly attempt to test thread pools. + * It throws an exception on Windows in TerminateThread, but not on Wine. */ + return; + + /* terminate thread in thread pool with pending write */ + create_overlapped_pipe(read_mode, &client, &server); + tp_work = CreateThreadpoolWork(tp_write_pipe, client, NULL); + ok(tp_work != NULL, "CreateThreadpoolWork failed: %u\n", GetLastError()); + SubmitThreadpoolWork(tp_work); + /* succesfully read part of write that is pending in different thread */ + res = ReadFile(server, buf, 10, &read_bytes, NULL); + if(read_mode == PIPE_READMODE_BYTE) + ok(res, "ReadFile failed: %u\n", GetLastError()); + else + ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %u\n", res, GetLastError()); + ok(read_bytes == 10, "read_bytes = %u\n", read_bytes); + trace("terminating thread %p\n", tp_thread); + TerminateThread(tp_thread, 0); + trace("terminated\n"); + WaitForSingleObject(tp_thread, INFINITE); + /* after terminating thread, there is no pending write and pipe buffer is empty */ + overlapped_read_async(server, buf, 10, &overlapped); + overlapped_write_sync(client, buf, 1); + test_overlapped_result(server, &overlapped, 1, FALSE); + CloseHandle(tp_thread); + CloseHandle(server); + CloseHandle(client); } START_TEST(pipe) @@ -2948,7 +3010,7 @@ START_TEST(pipe) { UINT_PTR handle; sscanf(argv[3], "%lx", &handle); - child_process_write_pipe((HANDLE)handle); + write_pipe_proc((HANDLE)handle); return; }