Module: wine Branch: master Commit: c8b50c98a34f6f6e32a946ffcc8c758dcabb819c URL: https://source.winehq.org/git/wine.git/?a=commit;h=c8b50c98a34f6f6e32a946ffc...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Mar 11 17:03:33 2019 +0100
server: Wake waiters when new pipe server instance is created.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/kernel32/tests/pipe.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++ server/named_pipe.c | 1 + 2 files changed, 79 insertions(+)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c index 7817fd5..4c7df3d 100644 --- a/dlls/kernel32/tests/pipe.c +++ b/dlls/kernel32/tests/pipe.c @@ -3808,6 +3808,83 @@ static void test_multiple_instances(void) } }
+static DWORD WINAPI wait_pipe_proc(void *arg) +{ + BOOL ret; + ret = WaitNamedPipeA(PIPENAME, 1000); + ok(ret, "WaitNamedPipe failed (%u)\n", GetLastError()); + return 0; +} + +static HANDLE async_wait_pipe(void) +{ + HANDLE thread; + BOOL ret; + + thread = CreateThread(NULL, 0, wait_pipe_proc, NULL, 0, NULL); + ok(thread != NULL, "CreateThread failed: %u\n", GetLastError()); + + ret = WaitNamedPipeA(PIPENAME, 1); + ok(!ret && GetLastError() == ERROR_SEM_TIMEOUT, "WaitNamedPipe failed %x(%u)\n", ret, GetLastError()); + + return thread; +} + +static void test_wait_pipe(void) +{ + HANDLE server[2], client, wait; + OVERLAPPED ov; + DWORD res; + BOOL ret; + + ret = WaitNamedPipeA(PIPENAME, 0); + ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "WaitNamedPipe failed %x(%u)\n", ret, GetLastError()); + + server[0] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024, + NMPWAIT_USE_DEFAULT_WAIT, NULL); + ok(server[0] != INVALID_HANDLE_VALUE, "got invalid handle\n"); + + ret = WaitNamedPipeA(PIPENAME, 1); + ok(ret, "WaitNamedPipe failed (%u)\n", GetLastError()); + + client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); + ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n"); + + /* Creating a new pipe server wakes waiters */ + wait = async_wait_pipe(); + server[1] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024, + NMPWAIT_USE_DEFAULT_WAIT, NULL); + ok(server[1] != INVALID_HANDLE_VALUE, "got invalid handle\n"); + + res = WaitForSingleObject(wait, 100); + ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res); + + CloseHandle(wait); + CloseHandle(server[1]); + + CloseHandle(client); + ret = DisconnectNamedPipe(server[0]); + ok(ret, "DisconnectNamedPipe failed (%u)\n", GetLastError()); + + /* Putting pipe server into waiting listening state wakes waiters */ + wait = async_wait_pipe(); + memset(&ov, 0, sizeof(ov)); + ov.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + ret = ConnectNamedPipe(server[0], &ov); + ok(ret == FALSE, "got %d\n", ret); + ok(GetLastError() == ERROR_IO_PENDING, "got %d\n", GetLastError()); + + res = WaitForSingleObject(wait, 100); + ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res); + CloseHandle(server[0]); + + res = WaitForSingleObject(ov.hEvent, 0); + ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res); + CloseHandle(ov.hEvent); +} + START_TEST(pipe) { char **argv; @@ -3874,4 +3951,5 @@ START_TEST(pipe) test_namedpipe_process_id(); test_namedpipe_session_id(); test_multiple_instances(); + test_wait_pipe(); } diff --git a/server/named_pipe.c b/server/named_pipe.c index 85e7286..a6ec8ae 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -1173,6 +1173,7 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned } allow_fd_caching( server->pipe_end.fd ); set_fd_signaled( server->pipe_end.fd, 1 ); + async_wake_up( &pipe->waiters, STATUS_SUCCESS ); return server; }