mirror of
https://github.com/nodejs/node-v0.x-archive.git
synced 2026-04-28 03:01:10 -04:00
Upgrade libuv to 2e9a743
This commit is contained in:
2
deps/uv/config-mingw.mk
vendored
2
deps/uv/config-mingw.mk
vendored
@@ -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)
|
||||
|
||||
1
deps/uv/include/uv-win.h
vendored
1
deps/uv/include/uv-win.h
vendored
@@ -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;
|
||||
|
||||
2
deps/uv/msvs/libuv-test.vcxproj
vendored
2
deps/uv/msvs/libuv-test.vcxproj
vendored
@@ -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'">
|
||||
|
||||
1
deps/uv/src/win/internal.h
vendored
1
deps/uv/src/win/internal.h
vendored
@@ -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);
|
||||
|
||||
67
deps/uv/src/win/pipe.c
vendored
67
deps/uv/src/win/pipe.c
vendored
@@ -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,
|
||||
|
||||
151
deps/uv/src/win/process.c
vendored
151
deps/uv/src/win/process.c
vendored
@@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
/* 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");
|
||||
}
|
||||
|
||||
CloseHandle(info.hThread);
|
||||
err = 0;
|
||||
CloseHandle(info.hThread);
|
||||
|
||||
} 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);
|
||||
|
||||
6
deps/uv/test/test-list.h
vendored
6
deps/uv/test/test-list.h
vendored
@@ -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. */
|
||||
|
||||
44
deps/uv/test/test-spawn.c
vendored
44
deps/uv/test/test-spawn.c
vendored
@@ -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
|
||||
Reference in New Issue
Block a user