diff --git a/config-mingw.mk b/config-mingw.mk index 242bba94..abd244e3 100644 --- a/config-mingw.mk +++ b/config-mingw.mk @@ -33,7 +33,7 @@ WIN_OBJS=$(WIN_SRCS:.c=.o) RUNNER_CFLAGS=$(CFLAGS) -D_GNU_SOURCE # Need _GNU_SOURCE for strdup? RUNNER_LINKFLAGS=$(LINKFLAGS) -RUNNER_LIBS=-lws2_32 -lrpcrt4 -lole32 +RUNNER_LIBS=-lws2_32 RUNNER_SRC=test/runner-win.c uv.a: $(WIN_OBJS) src/uv-common.o src/uv-eio.o src/eio/eio.o $(CARES_OBJS) diff --git a/msvs/libuv-test.vcxproj b/msvs/libuv-test.vcxproj index b91de56a..44b138bd 100644 --- a/msvs/libuv-test.vcxproj +++ b/msvs/libuv-test.vcxproj @@ -84,7 +84,7 @@ MachineX86 true Console - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;RpcRT4.Lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies) diff --git a/src/win/internal.h b/src/win/internal.h index e40ef3be..37836426 100644 --- a/src/win/internal.h +++ b/src/win/internal.h @@ -166,7 +166,6 @@ int uv_pipe_init_with_handle(uv_pipe_t* handle, HANDLE pipeHandle); int uv_stdio_pipe_server(uv_pipe_t* handle, DWORD access, char* name, size_t nameSize); void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err); void uv_pipe_endgame(uv_pipe_t* handle); -int uv_unique_pipe_name(char* name, size_t size); int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client); diff --git a/src/win/pipe.c b/src/win/pipe.c index b6763249..1eb49731 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -32,29 +32,8 @@ static char uv_zero_[] = ""; -int uv_unique_pipe_name(char* name, size_t size) { - unsigned char* guid_str = NULL; - GUID guid; - int err; - - if (CoCreateGuid(&guid) != S_OK) { - err = -1; - goto done; - } - - if (UuidToStringA(&guid, &guid_str) != ERROR_SUCCESS) { - err = -1; - goto done; - } - - _snprintf(name, size, "\\\\.\\pipe\\uv\\%s", guid_str); - err = 0; - -done: - if (guid_str) { - RpcStringFreeA(&guid_str); - } - return err; +static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { + _snprintf(name, size, "\\\\.\\pipe\\uv\\%p-%d", ptr, GetCurrentProcessId()); } @@ -92,26 +71,36 @@ int uv_pipe_init_with_handle(uv_pipe_t* handle, HANDLE pipeHandle) { int uv_stdio_pipe_server(uv_pipe_t* handle, DWORD access, char* name, size_t nameSize) { HANDLE pipeHandle; + int errno; int err; + char* ptr = (char*)handle; - err = uv_unique_pipe_name(name, nameSize); - if (err) { - goto done; - } + while (TRUE) { + uv_unique_pipe_name(ptr, name, nameSize); - pipeHandle = CreateNamedPipeA(name, - access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - 1, - 65536, - 65536, - 0, - NULL); + pipeHandle = CreateNamedPipeA(name, + access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, + 1, + 65536, + 65536, + 0, + NULL); - if (pipeHandle == INVALID_HANDLE_VALUE) { - uv_set_sys_error(GetLastError()); - err = -1; - goto done; + if (pipeHandle != INVALID_HANDLE_VALUE) { + /* No name collisions. We're done. */ + break; + } + + errno = GetLastError(); + if (errno != ERROR_PIPE_BUSY && errno != ERROR_ACCESS_DENIED) { + uv_set_sys_error(errno); + err = -1; + goto done; + } + + /* Pipe name collision. Increment the pointer and try again. */ + ptr++; } if (CreateIoCompletionPort(pipeHandle, diff --git a/test/test-list.h b/test/test-list.h index c4a4e436..ebfdeb65 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -67,6 +67,9 @@ TEST_DECLARE (spawn_exit_code) TEST_DECLARE (spawn_stdout) TEST_DECLARE (spawn_stdin) TEST_DECLARE (spawn_and_kill) +#ifdef _WIN32 +TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) +#endif HELPER_DECLARE (tcp4_echo_server) HELPER_DECLARE (tcp6_echo_server) HELPER_DECLARE (pipe_echo_server) @@ -148,6 +151,9 @@ TASK_LIST_START TEST_ENTRY (spawn_stdout) TEST_ENTRY (spawn_stdin) TEST_ENTRY (spawn_and_kill) +#ifdef _WIN32 + TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) +#endif #if 0 /* These are for testing the test runner. */ diff --git a/test/test-spawn.c b/test/test-spawn.c index 2ab6e6ca..6378aab9 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -226,3 +226,47 @@ TEST_IMPL(spawn_and_kill) { return 0; } + +#ifdef _WIN32 +TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) { + int r; + uv_pipe_t out; + char name[64]; + HANDLE pipe_handle; + + uv_init(); + + init_process_options("spawn_helper2", exit_cb); + + uv_pipe_init(&out); + options.stdout_stream = &out; + + /* Create a pipe that'll cause a collision. */ + _snprintf(name, sizeof(name), "\\\\.\\pipe\\uv\\%p-%d", &out, GetCurrentProcessId()); + pipe_handle = CreateNamedPipeA(name, + PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, + 10, + 65536, + 65536, + 0, + NULL); + ASSERT(pipe_handle != INVALID_HANDLE_VALUE); + + r = uv_spawn(&process, options); + ASSERT(r == 0); + + r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); + ASSERT(r == 0); + + r = uv_run(); + ASSERT(r == 0); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */ + printf("output is: %s", output); + ASSERT(strcmp("hello world\n", output) == 0 || strcmp("hello world\r\n", output) == 0); + + return 0; +} +#endif \ No newline at end of file