Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-08-02 07:26:26 +0400
committerRyan Dahl <ry@tinyclouds.org>2011-08-02 07:26:26 +0400
commit89b14fc0ff4da52ec112e0af4d8e7d87bfe5d637 (patch)
tree050220e278e91ba110648e4ce4ef80872ea626c6 /deps
parent1c09cc1550af44eaf9d8ba6365d5d7911c41fce3 (diff)
Upgrade libuv to 2e9a743
Diffstat (limited to 'deps')
-rw-r--r--deps/uv/config-mingw.mk2
-rw-r--r--deps/uv/include/uv-win.h1
-rw-r--r--deps/uv/msvs/libuv-test.vcxproj2
-rw-r--r--deps/uv/src/win/internal.h1
-rw-r--r--deps/uv/src/win/pipe.c67
-rw-r--r--deps/uv/src/win/process.c151
-rw-r--r--deps/uv/test/test-list.h6
-rw-r--r--deps/uv/test/test-spawn.c44
8 files changed, 185 insertions, 89 deletions
diff --git a/deps/uv/config-mingw.mk b/deps/uv/config-mingw.mk
index 242bba9435c..abd244e3aef 100644
--- a/deps/uv/config-mingw.mk
+++ b/deps/uv/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/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h
index ec2429a60d8..622bbeab4bb 100644
--- a/deps/uv/include/uv-win.h
+++ b/deps/uv/include/uv-win.h
@@ -178,6 +178,7 @@ typedef struct uv_buf_t {
HANDLE child_pipe; \
} stdio_pipes[3]; \
int exit_signal; \
+ DWORD spawn_errno; \
HANDLE wait_handle; \
HANDLE process_handle; \
HANDLE close_handle;
diff --git a/deps/uv/msvs/libuv-test.vcxproj b/deps/uv/msvs/libuv-test.vcxproj
index b91de56ae66..44b138bdb61 100644
--- a/deps/uv/msvs/libuv-test.vcxproj
+++ b/deps/uv/msvs/libuv-test.vcxproj
@@ -84,7 +84,7 @@
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
- <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;RpcRT4.Lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <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)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index e40ef3bea5f..37836426ec1 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/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/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index b6763249d57..1eb49731913 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/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/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index 6ad221f7e7c..5ce2d60eebd 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -496,16 +496,16 @@ wchar_t* make_program_env(char** env_block) {
}
-/*
- * Called on Windows thread-pool thread to indicate that
- * a child process has exited.
+/*
+ * Called on Windows thread-pool thread to indicate that
+ * a child process has exited.
*/
static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {
uv_process_t* process = (uv_process_t*)data;
-
+
assert(didTimeout == FALSE);
assert(process);
-
+
memset(&process->exit_req.overlapped, 0, sizeof(process->exit_req.overlapped));
/* Post completed */
@@ -518,13 +518,13 @@ static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {
}
-/*
- * Called on Windows thread-pool thread to indicate that
- * UnregisterWaitEx has completed.
+/*
+ * Called on Windows thread-pool thread to indicate that
+ * UnregisterWaitEx has completed.
*/
static void CALLBACK close_wait_callback(void* data, BOOLEAN didTimeout) {
uv_process_t* process = (uv_process_t*)data;
-
+
assert(didTimeout == FALSE);
assert(process);
@@ -540,6 +540,54 @@ static void CALLBACK close_wait_callback(void* data, BOOLEAN didTimeout) {
}
+/*
+ * Called on windows thread pool when CreateProcess failed. It writes an error
+ * message to the process' intended stderr and then posts a PROCESS_EXIT
+ * packet to the completion port.
+ */
+static DWORD WINAPI spawn_failure(void* data) {
+ char syscall[] = "CreateProcessW: ";
+ char unknown[] = "unknown error\n";
+ uv_process_t* process = (uv_process_t*) data;
+ HANDLE child_stderr = process->stdio_pipes[2].child_pipe;
+ char* buf = NULL;
+ DWORD count, written;
+
+ WriteFile(child_stderr, syscall, sizeof(syscall) - 1, &written, NULL);
+
+ count = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ process->spawn_errno,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &buf,
+ 0,
+ NULL);
+
+ if (buf != NULL && count > 0) {
+ WriteFile(child_stderr, buf, count, &written, NULL);
+ LocalFree(buf);
+ } else {
+ WriteFile(child_stderr, unknown, sizeof(unknown) - 1, &written, NULL);
+ }
+
+ FlushFileBuffers(child_stderr);
+
+ memset(&process->exit_req.overlapped, 0, sizeof(process->exit_req.overlapped));
+
+ /* Post completed */
+ if (!PostQueuedCompletionStatus(LOOP->iocp,
+ 0,
+ 0,
+ &process->exit_req.overlapped)) {
+ uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
+ }
+
+ return 0;
+}
+
+
/* Called on main thread after a child process has exited. */
void uv_process_proc_exit(uv_process_t* handle) {
int i;
@@ -559,15 +607,18 @@ void uv_process_proc_exit(uv_process_t* handle) {
handle->wait_handle = INVALID_HANDLE_VALUE;
}
- /* Clean-up the process handle. */
if (handle->process_handle != INVALID_HANDLE_VALUE) {
/* Get the exit code. */
if (!GetExitCodeProcess(handle->process_handle, &exit_code)) {
- exit_code = 1;
+ exit_code = 127;
}
+ /* Clean-up the process handle. */
CloseHandle(handle->process_handle);
handle->process_handle = INVALID_HANDLE_VALUE;
+ } else {
+ /* The process never even started in the first place. */
+ exit_code = 127;
}
/* Fire the exit callback. */
@@ -618,10 +669,10 @@ static int uv_create_stdio_pipe_pair(uv_pipe_t* server_pipe, HANDLE* child_pipe,
char pipe_name[64];
DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
- if (server_pipe->type != UV_NAMED_PIPE) {
+ if (server_pipe->type != UV_NAMED_PIPE) {
uv_set_error(UV_EINVAL, 0);
err = -1;
- goto done;
+ goto done;
}
/* Create server pipe handle. */
@@ -681,13 +732,13 @@ done:
int uv_spawn(uv_process_t* process, uv_process_options_t options) {
- int err, i;
+ int err = 0, i;
wchar_t* path;
int size;
wchar_t* application_path, *application, *arguments, *env, *cwd;
STARTUPINFOW startup;
PROCESS_INFORMATION info;
-
+
uv_process_init(process);
process->exit_cb = options.exit_cb;
@@ -721,15 +772,15 @@ int uv_spawn(uv_process_t* process, uv_process_options_t options) {
GetEnvironmentVariableW(L"PATH", path, size * sizeof(wchar_t));
path[size - 1] = L'\0';
- application_path = search_path(application,
+ application_path = search_path(application,
cwd,
path,
DEFAULT_PATH_EXT);
if (!application_path) {
- uv_set_error(UV_EINVAL, 0);
- err = -1;
- goto done;
+ /* CreateProcess will fail, but this allows us to pass this error to */
+ /* the user asynchronously. */
+ application_path = application;
}
/* Create stdio pipes. */
@@ -771,39 +822,45 @@ int uv_spawn(uv_process_t* process, uv_process_options_t options) {
startup.hStdOutput = process->stdio_pipes[1].child_pipe;
startup.hStdError = process->stdio_pipes[2].child_pipe;
- if (!CreateProcessW(application_path,
- arguments,
- NULL,
- NULL,
- 1,
- CREATE_UNICODE_ENVIRONMENT,
- env,
- cwd,
- &startup,
- &info)) {
- uv_set_sys_error(GetLastError());
- err = -1;
- goto done;
- }
+ if (CreateProcessW(application_path,
+ arguments,
+ NULL,
+ NULL,
+ 1,
+ CREATE_UNICODE_ENVIRONMENT,
+ env,
+ cwd,
+ &startup,
+ &info)) {
+ /* Spawn succeeded */
+ process->process_handle = info.hProcess;
+ process->pid = info.dwProcessId;
+
+ /* Setup notifications for when the child process exits. */
+ if (!RegisterWaitForSingleObject(&process->wait_handle, process->process_handle,
+ exit_wait_callback, (void*)process, INFINITE,
+ WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
+ uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
+ }
- process->process_handle = info.hProcess;
- process->pid = info.dwProcessId;
-
- /* Setup notifications for when the child process exits. */
- if (!RegisterWaitForSingleObject(&process->wait_handle, process->process_handle,
- exit_wait_callback, (void*)process, INFINITE,
- WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
- uv_set_sys_error(GetLastError());
- err = -1;
- goto done;
- }
+ CloseHandle(info.hThread);
- CloseHandle(info.hThread);
- err = 0;
+ } else {
+ /* CreateProcessW failed, but this failure should be delivered */
+ /* asynchronously to retain unix compatibility. So pretent spawn */
+ /* succeeded, and start a thread instead that prints an error */
+ /* to the child's intended stderr. */
+ process->spawn_errno = GetLastError();
+ if (!QueueUserWorkItem(spawn_failure, process, WT_EXECUTEDEFAULT)) {
+ uv_fatal_error(GetLastError(), "QueueUserWorkItem");
+ }
+ }
done:
- free(application_path);
free(application);
+ if (application_path != application) {
+ free(application_path);
+ }
free(arguments);
free(cwd);
free(env);
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index c4a4e43634b..ebfdeb65569 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/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/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index 2ab6e6ca6a1..6378aab9811 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/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