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