summaryrefslogtreecommitdiffstats
path: root/Utilities/cmlibuv/src/win
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/win')
-rw-r--r--Utilities/cmlibuv/src/win/async.c10
-rw-r--r--Utilities/cmlibuv/src/win/atomicops-inl.h8
-rw-r--r--Utilities/cmlibuv/src/win/core.c58
-rw-r--r--Utilities/cmlibuv/src/win/dl.c11
-rw-r--r--Utilities/cmlibuv/src/win/error.c4
-rw-r--r--Utilities/cmlibuv/src/win/fs-event.c25
-rw-r--r--Utilities/cmlibuv/src/win/fs.c184
-rw-r--r--Utilities/cmlibuv/src/win/getaddrinfo.c40
-rw-r--r--Utilities/cmlibuv/src/win/getnameinfo.c50
-rw-r--r--Utilities/cmlibuv/src/win/handle-inl.h25
-rw-r--r--Utilities/cmlibuv/src/win/handle.c12
-rw-r--r--Utilities/cmlibuv/src/win/internal.h114
-rw-r--r--Utilities/cmlibuv/src/win/loop-watcher.c2
-rw-r--r--Utilities/cmlibuv/src/win/pipe.c1130
-rw-r--r--Utilities/cmlibuv/src/win/poll.c55
-rw-r--r--Utilities/cmlibuv/src/win/process-stdio.c59
-rw-r--r--Utilities/cmlibuv/src/win/process.c70
-rw-r--r--Utilities/cmlibuv/src/win/req.c25
-rw-r--r--Utilities/cmlibuv/src/win/signal.c50
-rw-r--r--Utilities/cmlibuv/src/win/stream.c36
-rw-r--r--Utilities/cmlibuv/src/win/tcp.c213
-rw-r--r--Utilities/cmlibuv/src/win/thread.c246
-rw-r--r--Utilities/cmlibuv/src/win/timer.c195
-rw-r--r--Utilities/cmlibuv/src/win/tty.c177
-rw-r--r--Utilities/cmlibuv/src/win/udp.c95
-rw-r--r--Utilities/cmlibuv/src/win/util.c298
-rw-r--r--Utilities/cmlibuv/src/win/winapi.c60
-rw-r--r--Utilities/cmlibuv/src/win/winapi.h80
-rw-r--r--Utilities/cmlibuv/src/win/winsock.c8
29 files changed, 1610 insertions, 1730 deletions
diff --git a/Utilities/cmlibuv/src/win/async.c b/Utilities/cmlibuv/src/win/async.c
index 0b636ed..d787f66 100644
--- a/Utilities/cmlibuv/src/win/async.c
+++ b/Utilities/cmlibuv/src/win/async.c
@@ -29,7 +29,7 @@
void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
- if (handle->flags & UV__HANDLE_CLOSING &&
+ if (handle->flags & UV_HANDLE_CLOSING &&
!handle->async_sent) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
uv__handle_close(handle);
@@ -71,9 +71,9 @@ int uv_async_send(uv_async_t* handle) {
return -1;
}
- /* The user should make sure never to call uv_async_send to a closing */
- /* or closed handle. */
- assert(!(handle->flags & UV__HANDLE_CLOSING));
+ /* The user should make sure never to call uv_async_send to a closing or
+ * closed handle. */
+ assert(!(handle->flags & UV_HANDLE_CLOSING));
if (!uv__atomic_exchange_set(&handle->async_sent)) {
POST_COMPLETION_FOR_REQ(loop, &handle->async_req);
@@ -90,7 +90,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
handle->async_sent = 0;
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*)handle);
} else if (handle->async_cb != NULL) {
handle->async_cb(handle);
diff --git a/Utilities/cmlibuv/src/win/atomicops-inl.h b/Utilities/cmlibuv/src/win/atomicops-inl.h
index 6d8126f..52713cf 100644
--- a/Utilities/cmlibuv/src/win/atomicops-inl.h
+++ b/Utilities/cmlibuv/src/win/atomicops-inl.h
@@ -29,10 +29,10 @@
/* Atomic set operation on char */
#ifdef _MSC_VER /* MSVC */
-/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less */
-/* efficient than InterlockedExchange, but InterlockedExchange8 does not */
-/* exist, and interlocked operations on larger targets might require the */
-/* target to be aligned. */
+/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less
+ * efficient than InterlockedExchange, but InterlockedExchange8 does not exist,
+ * and interlocked operations on larger targets might require the target to be
+ * aligned. */
#pragma intrinsic(_InterlockedOr8)
static char INLINE uv__atomic_exchange_set(char volatile* target) {
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index b8aad11..58309c6 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -33,6 +33,7 @@
#include "internal.h"
#include "queue.h"
#include "handle-inl.h"
+#include "heap-inl.h"
#include "req-inl.h"
/* uv_once initialization guards */
@@ -221,6 +222,7 @@ static void uv_init(void) {
int uv_loop_init(uv_loop_t* loop) {
+ struct heap* timer_heap;
int err;
/* Initialize libuv itself first */
@@ -246,7 +248,13 @@ int uv_loop_init(uv_loop_t* loop) {
loop->endgame_handles = NULL;
- RB_INIT(&loop->timers);
+ loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap));
+ if (timer_heap == NULL) {
+ err = UV_ENOMEM;
+ goto fail_timers_alloc;
+ }
+
+ heap_init(timer_heap);
loop->check_handles = NULL;
loop->prepare_handles = NULL;
@@ -273,7 +281,7 @@ int uv_loop_init(uv_loop_t* loop) {
goto fail_async_init;
uv__handle_unref(&loop->wq_async);
- loop->wq_async.flags |= UV__HANDLE_INTERNAL;
+ loop->wq_async.flags |= UV_HANDLE_INTERNAL;
err = uv__loops_add(loop);
if (err)
@@ -285,6 +293,10 @@ fail_async_init:
uv_mutex_destroy(&loop->wq_mutex);
fail_mutex_init:
+ uv__free(timer_heap);
+ loop->timer_heap = NULL;
+
+fail_timers_alloc:
CloseHandle(loop->iocp);
loop->iocp = INVALID_HANDLE_VALUE;
@@ -292,6 +304,13 @@ fail_mutex_init:
}
+void uv_update_time(uv_loop_t* loop) {
+ uint64_t new_time = uv__hrtime(1000);
+ assert(new_time >= loop->time);
+ loop->time = new_time;
+}
+
+
void uv__once_init(void) {
uv_once(&uv_init_guard_, uv_init);
}
@@ -320,6 +339,9 @@ void uv__loop_close(uv_loop_t* loop) {
uv_mutex_unlock(&loop->wq_mutex);
uv_mutex_destroy(&loop->wq_mutex);
+ uv__free(loop->timer_heap);
+ loop->timer_heap = NULL;
+
CloseHandle(loop->iocp);
}
@@ -359,7 +381,7 @@ int uv_backend_timeout(const uv_loop_t* loop) {
}
-static void uv_poll(uv_loop_t* loop, DWORD timeout) {
+static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
DWORD bytes;
ULONG_PTR key;
OVERLAPPED* overlapped;
@@ -410,7 +432,7 @@ static void uv_poll(uv_loop_t* loop, DWORD timeout) {
}
-static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
+static void uv__poll(uv_loop_t* loop, DWORD timeout) {
BOOL success;
uv_req_t* req;
OVERLAPPED_ENTRY overlappeds[128];
@@ -422,12 +444,12 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
timeout_time = loop->time + timeout;
for (repeat = 0; ; repeat++) {
- success = pGetQueuedCompletionStatusEx(loop->iocp,
- overlappeds,
- ARRAY_SIZE(overlappeds),
- &count,
- timeout,
- FALSE);
+ success = GetQueuedCompletionStatusEx(loop->iocp,
+ overlappeds,
+ ARRAY_SIZE(overlappeds),
+ &count,
+ timeout,
+ FALSE);
if (success) {
for (i = 0; i < count; i++) {
@@ -485,12 +507,6 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
DWORD timeout;
int r;
int ran_pending;
- void (*poll)(uv_loop_t* loop, DWORD timeout);
-
- if (pGetQueuedCompletionStatusEx)
- poll = &uv_poll_ex;
- else
- poll = &uv_poll;
r = uv__loop_alive(loop);
if (!r)
@@ -498,7 +514,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
while (r != 0 && loop->stop_flag == 0) {
uv_update_time(loop);
- uv_process_timers(loop);
+ uv__run_timers(loop);
ran_pending = uv_process_reqs(loop);
uv_idle_invoke(loop);
@@ -508,7 +524,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
- (*poll)(loop, timeout);
+ if (pGetQueuedCompletionStatusEx)
+ uv__poll(loop, timeout);
+ else
+ uv__poll_wine(loop, timeout);
+
uv_check_invoke(loop);
uv_process_endgames(loop);
@@ -522,7 +542,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
* the check.
*/
- uv_process_timers(loop);
+ uv__run_timers(loop);
}
r = uv__loop_alive(loop);
diff --git a/Utilities/cmlibuv/src/win/dl.c b/Utilities/cmlibuv/src/win/dl.c
index 97ac1c1..676be4d 100644
--- a/Utilities/cmlibuv/src/win/dl.c
+++ b/Utilities/cmlibuv/src/win/dl.c
@@ -64,7 +64,8 @@ void uv_dlclose(uv_lib_t* lib) {
int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
- *ptr = (void*) GetProcAddress(lib->handle, name);
+ /* Cast though integer to suppress pedantic warning about forbidden cast. */
+ *ptr = (void*)(uintptr_t) GetProcAddress(lib->handle, name);
return uv__dlerror(lib, "", *ptr ? 0 : GetLastError());
}
@@ -75,8 +76,9 @@ const char* uv_dlerror(const uv_lib_t* lib) {
static void uv__format_fallback_error(uv_lib_t* lib, int errorno){
- DWORD_PTR args[1] = { (DWORD_PTR) errorno };
- LPSTR fallback_error = "error: %1!d!";
+ static const CHAR fallback_error[] = "error: %1!d!";
+ DWORD_PTR args[1];
+ args[0] = (DWORD_PTR) errorno;
FormatMessageA(FORMAT_MESSAGE_FROM_STRING |
FORMAT_MESSAGE_ARGUMENT_ARRAY |
@@ -107,7 +109,8 @@ static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) {
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPSTR) &lib->errmsg, 0, NULL);
- if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) {
+ if (!res && (GetLastError() == ERROR_MUI_FILE_NOT_FOUND ||
+ GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)) {
res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
diff --git a/Utilities/cmlibuv/src/win/error.c b/Utilities/cmlibuv/src/win/error.c
index 9b03bfe..24924ba 100644
--- a/Utilities/cmlibuv/src/win/error.c
+++ b/Utilities/cmlibuv/src/win/error.c
@@ -46,8 +46,8 @@ void uv_fatal_error(const int errorno, const char* syscall) {
errmsg = "Unknown error";
}
- /* FormatMessage messages include a newline character already, */
- /* so don't add another. */
+ /* FormatMessage messages include a newline character already, so don't add
+ * another. */
if (syscall) {
fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg);
} else {
diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c
index 14c9af9..acf8e11 100644
--- a/Utilities/cmlibuv/src/win/fs-event.c
+++ b/Utilities/cmlibuv/src/win/fs-event.c
@@ -83,7 +83,7 @@ static void uv_relative_path(const WCHAR* filename,
static int uv_split_path(const WCHAR* filename, WCHAR** dir,
WCHAR** file) {
size_t len, i;
-
+
if (filename == NULL) {
if (dir != NULL)
*dir = NULL;
@@ -215,11 +215,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv__free(long_path);
long_path = NULL;
}
- }
- if (long_path) {
- uv__free(pathw);
- pathw = long_path;
+ if (long_path) {
+ uv__free(pathw);
+ pathw = long_path;
+ }
}
dir_to_watch = pathw;
@@ -230,8 +230,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
*/
/* Convert to short path. */
- short_path = short_path_buffer;
- if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) {
+ if (GetShortPathNameW(pathw,
+ short_path_buffer,
+ ARRAY_SIZE(short_path_buffer))) {
+ short_path = short_path_buffer;
+ } else {
short_path = NULL;
}
@@ -419,7 +422,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
* - We are not active, just ignore the callback
*/
if (!uv__is_active(handle)) {
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*) handle);
}
return;
@@ -543,7 +546,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
}
offset = file_info->NextEntryOffset;
- } while (offset && !(handle->flags & UV__HANDLE_CLOSING));
+ } while (offset && !(handle->flags & UV_HANDLE_CLOSING));
} else {
handle->cb(handle, NULL, UV_CHANGE, 0);
}
@@ -552,7 +555,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
handle->cb(handle, NULL, 0, uv_translate_sys_error(err));
}
- if (!(handle->flags & UV__HANDLE_CLOSING)) {
+ if (!(handle->flags & UV_HANDLE_CLOSING)) {
uv_fs_event_queue_readdirchanges(loop, handle);
} else {
uv_want_endgame(loop, (uv_handle_t*)handle);
@@ -573,7 +576,7 @@ void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
- if ((handle->flags & UV__HANDLE_CLOSING) && !handle->req_pending) {
+ if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
if (handle->buffer) {
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index 30b87ac..65d936b 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -55,7 +55,11 @@
do { \
if (cb != NULL) { \
uv__req_register(loop, req); \
- uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
+ uv__work_submit(loop, \
+ &req->work_req, \
+ UV__WORK_FAST_IO, \
+ uv__fs_work, \
+ uv__fs_done); \
return 0; \
} else { \
uv__fs_work(&req->work_req); \
@@ -92,14 +96,17 @@
return; \
}
+#define MILLIONu (1000U * 1000U)
+#define BILLIONu (1000U * 1000U * 1000U)
+
#define FILETIME_TO_UINT(filetime) \
- (*((uint64_t*) &(filetime)) - 116444736000000000ULL)
+ (*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)
#define FILETIME_TO_TIME_T(filetime) \
- (FILETIME_TO_UINT(filetime) / 10000000ULL)
+ (FILETIME_TO_UINT(filetime) / (10u * MILLIONu))
#define FILETIME_TO_TIME_NS(filetime, secs) \
- ((FILETIME_TO_UINT(filetime) - (secs * 10000000ULL)) * 100)
+ ((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)
#define FILETIME_TO_TIMESPEC(ts, filetime) \
do { \
@@ -109,8 +116,8 @@
#define TIME_T_TO_FILETIME(time, filetime_ptr) \
do { \
- uint64_t bigtime = ((uint64_t) ((time) * 10000000ULL)) + \
- 116444736000000000ULL; \
+ uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) + \
+ (uint64_t) 116444736 * BILLIONu; \
(filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \
(filetime_ptr)->dwHighDateTime = bigtime >> 32; \
} while(0)
@@ -326,12 +333,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
- /* Real symlinks can contain pretty much everything, but the only thing */
- /* we really care about is undoing the implicit conversion to an NT */
- /* namespaced path that CreateSymbolicLink will perform on absolute */
- /* paths. If the path is win32-namespaced then the user must have */
- /* explicitly made it so, and we better just return the unmodified */
- /* reparse data. */
+ /* Real symlinks can contain pretty much everything, but the only thing we
+ * really care about is undoing the implicit conversion to an NT namespaced
+ * path that CreateSymbolicLink will perform on absolute paths. If the path
+ * is win32-namespaced then the user must have explicitly made it so, and
+ * we better just return the unmodified reparse data. */
if (w_target_len >= 4 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
@@ -352,8 +358,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
(w_target[5] == L'N' || w_target[5] == L'n') &&
(w_target[6] == L'C' || w_target[6] == L'c') &&
w_target[7] == L'\\') {
- /* \??\UNC\<server>\<share>\ - make sure the final path looks like */
- /* \\<server>\<share>\ */
+ /* \??\UNC\<server>\<share>\ - make sure the final path looks like
+ * \\<server>\<share>\ */
w_target += 6;
w_target[0] = L'\\';
w_target_len -= 6;
@@ -368,11 +374,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
- /* Only treat junctions that look like \??\<drive>:\ as symlink. */
- /* Junctions can also be used as mount points, like \??\Volume{<guid>}, */
- /* but that's confusing for programs since they wouldn't be able to */
- /* actually understand such a path when returned by uv_readlink(). */
- /* UNC paths are never valid for junctions so we don't care about them. */
+ /* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions
+ * can also be used as mount points, like \??\Volume{<guid>}, but that's
+ * confusing for programs since they wouldn't be able to actually
+ * understand such a path when returned by uv_readlink(). UNC paths are
+ * never valid for junctions so we don't care about them. */
if (!(w_target_len >= 6 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
@@ -409,8 +415,8 @@ void fs__open(uv_fs_t* req) {
int fd, current_umask;
int flags = req->fs.info.file_flags;
- /* Obtain the active umask. umask() never fails and returns the previous */
- /* umask. */
+ /* Obtain the active umask. umask() never fails and returns the previous
+ * umask. */
current_umask = umask(0);
umask(current_umask);
@@ -502,6 +508,33 @@ void fs__open(uv_fs_t* req) {
}
if (flags & UV_FS_O_DIRECT) {
+ /*
+ * FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive.
+ * Windows returns 87, ERROR_INVALID_PARAMETER if these are combined.
+ *
+ * FILE_APPEND_DATA is included in FILE_GENERIC_WRITE:
+ *
+ * FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE |
+ * FILE_WRITE_DATA |
+ * FILE_WRITE_ATTRIBUTES |
+ * FILE_WRITE_EA |
+ * FILE_APPEND_DATA |
+ * SYNCHRONIZE
+ *
+ * Note: Appends are also permitted by FILE_WRITE_DATA.
+ *
+ * In order for direct writes and direct appends to succeed, we therefore
+ * exclude FILE_APPEND_DATA if FILE_WRITE_DATA is specified, and otherwise
+ * fail if the user's sole permission is a direct append, since this
+ * particular combination is invalid.
+ */
+ if (access & FILE_APPEND_DATA) {
+ if (access & FILE_WRITE_DATA) {
+ access &= ~FILE_APPEND_DATA;
+ } else {
+ goto einval;
+ }
+ }
attributes |= FILE_FLAG_NO_BUFFERING;
}
@@ -530,8 +563,8 @@ void fs__open(uv_fs_t* req) {
DWORD error = GetLastError();
if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
!(flags & UV_FS_O_EXCL)) {
- /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was */
- /* specified, it means the path referred to a directory. */
+ /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was
+ * specified, it means the path referred to a directory. */
SET_REQ_UV_ERROR(req, UV_EISDIR, error);
} else {
SET_REQ_WIN32_ERROR(req, GetLastError());
@@ -756,9 +789,9 @@ void fs__unlink(uv_fs_t* req) {
}
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- /* Do not allow deletion of directories, unless it is a symlink. When */
- /* the path refers to a non-symlink directory, report EPERM as mandated */
- /* by POSIX.1. */
+ /* Do not allow deletion of directories, unless it is a symlink. When the
+ * path refers to a non-symlink directory, report EPERM as mandated by
+ * POSIX.1. */
/* Check if it is a reparse point. If it's not, it's a normal directory. */
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
@@ -767,8 +800,8 @@ void fs__unlink(uv_fs_t* req) {
return;
}
- /* Read the reparse point and check if it is a valid symlink. */
- /* If not, don't unlink. */
+ /* Read the reparse point and check if it is a valid symlink. If not, don't
+ * unlink. */
if (fs__readlink_handle(handle, NULL, NULL) < 0) {
DWORD error = GetLastError();
if (error == ERROR_SYMLINK_NOT_SUPPORTED)
@@ -783,9 +816,8 @@ void fs__unlink(uv_fs_t* req) {
/* Remove read-only attribute */
FILE_BASIC_INFORMATION basic = { 0 };
- basic.FileAttributes = info.dwFileAttributes
- & ~(FILE_ATTRIBUTE_READONLY)
- | FILE_ATTRIBUTE_ARCHIVE;
+ basic.FileAttributes = (info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) |
+ FILE_ATTRIBUTE_ARCHIVE;
status = pNtSetInformationFile(handle,
&iosb,
@@ -1196,7 +1228,7 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
/* st_blocks contains the on-disk allocation size in 512-byte units. */
statbuf->st_blocks =
- file_info.StandardInformation.AllocationSize.QuadPart >> 9ULL;
+ (uint64_t) file_info.StandardInformation.AllocationSize.QuadPart >> 9;
statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks;
@@ -1490,6 +1522,7 @@ static void fs__chmod(uv_fs_t* req) {
static void fs__fchmod(uv_fs_t* req) {
int fd = req->file.fd;
+ int clear_archive_flag;
HANDLE handle;
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
@@ -1497,7 +1530,11 @@ static void fs__fchmod(uv_fs_t* req) {
VERIFY_FD(fd, req);
- handle = uv__get_osfhandle(fd);
+ handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);
+ if (handle == INVALID_HANDLE_VALUE) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
nt_status = pNtQueryInformationFile(handle,
&io_status,
@@ -1507,7 +1544,27 @@ static void fs__fchmod(uv_fs_t* req) {
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
- return;
+ goto fchmod_cleanup;
+ }
+
+ /* Test if the Archive attribute is cleared */
+ if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {
+ /* Set Archive flag, otherwise setting or clearing the read-only
+ flag will not work */
+ file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
+ nt_status = pNtSetInformationFile(handle,
+ &io_status,
+ &file_info,
+ sizeof file_info,
+ FileBasicInformation);
+ if (!NT_SUCCESS(nt_status)) {
+ SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
+ goto fchmod_cleanup;
+ }
+ /* Remeber to clear the flag later on */
+ clear_archive_flag = 1;
+ } else {
+ clear_archive_flag = 0;
}
if (req->fs.info.mode & _S_IWRITE) {
@@ -1524,10 +1581,28 @@ static void fs__fchmod(uv_fs_t* req) {
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
- return;
+ goto fchmod_cleanup;
+ }
+
+ if (clear_archive_flag) {
+ file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
+ if (file_info.FileAttributes == 0) {
+ file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+ nt_status = pNtSetInformationFile(handle,
+ &io_status,
+ &file_info,
+ sizeof file_info,
+ FileBasicInformation);
+ if (!NT_SUCCESS(nt_status)) {
+ SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
+ goto fchmod_cleanup;
+ }
}
SET_REQ_SUCCESS(req);
+fchmod_cleanup:
+ CloseHandle(handle);
}
@@ -1787,17 +1862,13 @@ static void fs__symlink(uv_fs_t* req) {
fs__create_junction(req, pathw, new_pathw);
return;
}
- if (!pCreateSymbolicLinkW) {
- SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
- return;
- }
if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
else
flags = uv__file_symlink_usermode_flag;
- if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) {
+ if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {
SET_REQ_RESULT(req, 0);
return;
}
@@ -1848,13 +1919,13 @@ static void fs__readlink(uv_fs_t* req) {
}
-static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
+static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
int r;
DWORD w_realpath_len;
WCHAR* w_realpath_ptr = NULL;
WCHAR* w_realpath_buf;
- w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
+ w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
if (w_realpath_len == 0) {
return -1;
}
@@ -1866,10 +1937,8 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
}
w_realpath_ptr = w_realpath_buf;
- if (pGetFinalPathNameByHandleW(handle,
- w_realpath_ptr,
- w_realpath_len,
- VOLUME_NAME_DOS) == 0) {
+ if (GetFinalPathNameByHandleW(
+ handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {
uv__free(w_realpath_buf);
SetLastError(ERROR_INVALID_HANDLE);
return -1;
@@ -1901,11 +1970,6 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
static void fs__realpath(uv_fs_t* req) {
HANDLE handle;
- if (!pGetFinalPathNameByHandleW) {
- SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
- return;
- }
-
handle = CreateFileW(req->file.pathw,
0,
0,
@@ -1940,6 +2004,10 @@ static void fs__fchown(uv_fs_t* req) {
}
+static void fs__lchown(uv_fs_t* req) {
+ req->result = 0;
+}
+
static void uv__fs_work(struct uv__work* w) {
uv_fs_t* req;
@@ -1977,6 +2045,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(REALPATH, realpath)
XX(CHOWN, chown)
XX(FCHOWN, fchown);
+ XX(LCHOWN, lchown);
default:
assert(!"bad uv_fs_type");
}
@@ -2262,6 +2331,19 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
}
+int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
+ uv_gid_t gid, uv_fs_cb cb) {
+ int err;
+
+ INIT(UV_FS_LCHOWN);
+ err = fs__capture_path(req, path, NULL, cb != NULL);
+ if (err) {
+ return uv_translate_sys_error(err);
+ }
+ POST;
+}
+
+
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
int err;
diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c
index 5adc766..dfab860 100644
--- a/Utilities/cmlibuv/src/win/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/win/getaddrinfo.c
@@ -24,6 +24,7 @@
#include "uv.h"
#include "internal.h"
#include "req-inl.h"
+#include "idna.h"
/* EAI_* constants. */
#include <winsock2.h>
@@ -71,8 +72,8 @@ int uv__getaddrinfo_translate_error(int sys_err) {
#endif
-/* adjust size value to be multiple of 4. Use to keep pointer aligned */
-/* Do we need different versions of this for different architectures? */
+/* Adjust size value to be multiple of 4. Use to keep pointer aligned.
+ * Do we need different versions of this for different architectures? */
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
#ifndef NDIS_IF_MAX_STRING_SIZE
@@ -124,8 +125,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
}
if (req->retcode == 0) {
- /* convert addrinfoW to addrinfo */
- /* first calculate required length */
+ /* Convert addrinfoW to addrinfo. First calculate required length. */
addrinfow_ptr = req->addrinfow;
while (addrinfow_ptr != NULL) {
addrinfo_len += addrinfo_struct_len +
@@ -260,11 +260,13 @@ int uv_getaddrinfo(uv_loop_t* loop,
const char* node,
const char* service,
const struct addrinfo* hints) {
+ char hostname_ascii[256];
int nodesize = 0;
int servicesize = 0;
int hintssize = 0;
char* alloc_ptr = NULL;
int err;
+ long rc;
if (req == NULL || (node == NULL && service == NULL)) {
return UV_EINVAL;
@@ -278,12 +280,19 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* calculate required memory size for all input values */
if (node != NULL) {
- nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, node, -1, NULL, 0) *
- sizeof(WCHAR));
+ rc = uv__idna_toascii(node,
+ node + strlen(node),
+ hostname_ascii,
+ hostname_ascii + sizeof(hostname_ascii));
+ if (rc < 0)
+ return rc;
+ nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,
+ -1, NULL, 0) * sizeof(WCHAR));
if (nodesize == 0) {
err = GetLastError();
goto error;
}
+ node = hostname_ascii;
}
if (service != NULL) {
@@ -313,8 +322,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* save alloc_ptr now so we can free if error */
req->alloc = (void*)alloc_ptr;
- /* convert node string to UTF16 into allocated memory and save pointer in */
- /* the request. */
+ /* Convert node string to UTF16 into allocated memory and save pointer in the
+ * request. */
if (node != NULL) {
req->node = (WCHAR*)alloc_ptr;
if (MultiByteToWideChar(CP_UTF8,
@@ -331,8 +340,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
req->node = NULL;
}
- /* convert service string to UTF16 into allocated memory and save pointer */
- /* in the req. */
+ /* Convert service string to UTF16 into allocated memory and save pointer in
+ * the req. */
if (service != NULL) {
req->service = (WCHAR*)alloc_ptr;
if (MultiByteToWideChar(CP_UTF8,
@@ -369,6 +378,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
if (getaddrinfo_cb) {
uv__work_submit(loop,
&req->work_req,
+ UV__WORK_SLOW_IO,
uv__getaddrinfo_work,
uv__getaddrinfo_done);
return 0;
@@ -392,21 +402,15 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
DWORD bufsize;
int r;
- uv__once_init();
-
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
- if (pConvertInterfaceIndexToLuid == NULL)
- return UV_ENOSYS;
- r = pConvertInterfaceIndexToLuid(ifindex, &luid);
+ r = ConvertInterfaceIndexToLuid(ifindex, &luid);
if (r != 0)
return uv_translate_sys_error(r);
- if (pConvertInterfaceLuidToNameW == NULL)
- return UV_ENOSYS;
- r = pConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
+ r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
if (r != 0)
return uv_translate_sys_error(r);
diff --git a/Utilities/cmlibuv/src/win/getnameinfo.c b/Utilities/cmlibuv/src/win/getnameinfo.c
index 9f10cd2..b377338 100644
--- a/Utilities/cmlibuv/src/win/getnameinfo.c
+++ b/Utilities/cmlibuv/src/win/getnameinfo.c
@@ -42,7 +42,7 @@ static void uv__getnameinfo_work(struct uv__work* w) {
uv_getnameinfo_t* req;
WCHAR host[NI_MAXHOST];
WCHAR service[NI_MAXSERV];
- int ret = 0;
+ int ret;
req = container_of(w, uv_getnameinfo_t, work_req);
if (GetNameInfoW((struct sockaddr*)&req->storage,
@@ -53,27 +53,34 @@ static void uv__getnameinfo_work(struct uv__work* w) {
ARRAY_SIZE(service),
req->flags)) {
ret = WSAGetLastError();
+ req->retcode = uv__getaddrinfo_translate_error(ret);
+ return;
+ }
+
+ ret = WideCharToMultiByte(CP_UTF8,
+ 0,
+ host,
+ -1,
+ req->host,
+ sizeof(req->host),
+ NULL,
+ NULL);
+ if (ret == 0) {
+ req->retcode = uv_translate_sys_error(GetLastError());
+ return;
+ }
+
+ ret = WideCharToMultiByte(CP_UTF8,
+ 0,
+ service,
+ -1,
+ req->service,
+ sizeof(req->service),
+ NULL,
+ NULL);
+ if (ret == 0) {
+ req->retcode = uv_translate_sys_error(GetLastError());
}
- req->retcode = uv__getaddrinfo_translate_error(ret);
-
- /* convert results to UTF-8 */
- WideCharToMultiByte(CP_UTF8,
- 0,
- host,
- -1,
- req->host,
- sizeof(req->host),
- NULL,
- NULL);
-
- WideCharToMultiByte(CP_UTF8,
- 0,
- service,
- -1,
- req->service,
- sizeof(req->service),
- NULL,
- NULL);
}
@@ -138,6 +145,7 @@ int uv_getnameinfo(uv_loop_t* loop,
if (getnameinfo_cb) {
uv__work_submit(loop,
&req->work_req,
+ UV__WORK_SLOW_IO,
uv__getnameinfo_work,
uv__getnameinfo_done);
return 0;
diff --git a/Utilities/cmlibuv/src/win/handle-inl.h b/Utilities/cmlibuv/src/win/handle-inl.h
index 8d0334c..82c657d 100644
--- a/Utilities/cmlibuv/src/win/handle-inl.h
+++ b/Utilities/cmlibuv/src/win/handle-inl.h
@@ -32,7 +32,7 @@
#define DECREASE_ACTIVE_COUNT(loop, handle) \
do { \
if (--(handle)->activecnt == 0 && \
- !((handle)->flags & UV__HANDLE_CLOSING)) { \
+ !((handle)->flags & UV_HANDLE_CLOSING)) { \
uv__handle_stop((handle)); \
} \
assert((handle)->activecnt >= 0); \
@@ -53,7 +53,7 @@
assert(handle->reqs_pending > 0); \
handle->reqs_pending--; \
\
- if (handle->flags & UV__HANDLE_CLOSING && \
+ if (handle->flags & UV_HANDLE_CLOSING && \
handle->reqs_pending == 0) { \
uv_want_endgame(loop, (uv_handle_t*)handle); \
} \
@@ -62,14 +62,14 @@
#define uv__handle_closing(handle) \
do { \
- assert(!((handle)->flags & UV__HANDLE_CLOSING)); \
+ assert(!((handle)->flags & UV_HANDLE_CLOSING)); \
\
- if (!(((handle)->flags & UV__HANDLE_ACTIVE) && \
- ((handle)->flags & UV__HANDLE_REF))) \
+ if (!(((handle)->flags & UV_HANDLE_ACTIVE) && \
+ ((handle)->flags & UV_HANDLE_REF))) \
uv__active_handle_add((uv_handle_t*) (handle)); \
\
- (handle)->flags |= UV__HANDLE_CLOSING; \
- (handle)->flags &= ~UV__HANDLE_ACTIVE; \
+ (handle)->flags |= UV_HANDLE_CLOSING; \
+ (handle)->flags &= ~UV_HANDLE_ACTIVE; \
} while (0)
@@ -126,7 +126,8 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
break;
case UV_TIMER:
- uv_timer_endgame(loop, (uv_timer_t*) handle);
+ uv__timer_close((uv_timer_t*) handle);
+ uv__handle_close(handle);
break;
case UV_PREPARE:
@@ -164,10 +165,10 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
INLINE static HANDLE uv__get_osfhandle(int fd)
{
- /* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */
- /* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */
- /* for invalid FDs in release builds (or if you let the assert continue). */
- /* So this wrapper function disables asserts when calling _get_osfhandle. */
+ /* _get_osfhandle() raises an assert in debug builds if the FD is invalid.
+ * But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for
+ * invalid FDs in release builds (or if you let the assert continue). So this
+ * wrapper function disables asserts when calling _get_osfhandle. */
HANDLE handle;
UV_BEGIN_DISABLE_CRT_ASSERT();
diff --git a/Utilities/cmlibuv/src/win/handle.c b/Utilities/cmlibuv/src/win/handle.c
index 3915070..9d76c3f 100644
--- a/Utilities/cmlibuv/src/win/handle.c
+++ b/Utilities/cmlibuv/src/win/handle.c
@@ -59,15 +59,15 @@ uv_handle_type uv_guess_handle(uv_file file) {
int uv_is_active(const uv_handle_t* handle) {
- return (handle->flags & UV__HANDLE_ACTIVE) &&
- !(handle->flags & UV__HANDLE_CLOSING);
+ return (handle->flags & UV_HANDLE_ACTIVE) &&
+ !(handle->flags & UV_HANDLE_CLOSING);
}
void uv_close(uv_handle_t* handle, uv_close_cb cb) {
uv_loop_t* loop = handle->loop;
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
assert(0);
return;
}
@@ -150,10 +150,14 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
int uv_is_closing(const uv_handle_t* handle) {
- return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED));
+ return !!(handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED));
}
uv_os_fd_t uv_get_osfhandle(int fd) {
return uv__get_osfhandle(fd);
}
+
+int uv_open_osfhandle(uv_os_fd_t os_fd) {
+ return _open_osfhandle((intptr_t) os_fd, 0);
+}
diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h
index 849bc82..206ab5f 100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@ -29,7 +29,7 @@
#include "uv.h"
#include "../uv-common.h"
-#include "tree.h"
+#include "uv/tree.h"
#include "winapi.h"
#include "winsock.h"
@@ -62,77 +62,19 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
#endif
/*
- * Handles
- * (also see handle-inl.h)
- */
-
-/* Used by all handles. */
-#define UV_HANDLE_CLOSED 0x00000002
-#define UV_HANDLE_ENDGAME_QUEUED 0x00000008
-
-/* uv-common.h: #define UV__HANDLE_CLOSING 0x00000001 */
-/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */
-/* uv-common.h: #define UV__HANDLE_REF 0x00000020 */
-/* uv-common.h: #define UV_HANDLE_INTERNAL 0x00000080 */
-
-/* Used by streams and UDP handles. */
-#define UV_HANDLE_READING 0x00000100
-#define UV_HANDLE_BOUND 0x00000200
-#define UV_HANDLE_LISTENING 0x00000800
-#define UV_HANDLE_CONNECTION 0x00001000
-#define UV_HANDLE_READABLE 0x00008000
-#define UV_HANDLE_WRITABLE 0x00010000
-#define UV_HANDLE_READ_PENDING 0x00020000
-#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000
-#define UV_HANDLE_ZERO_READ 0x00080000
-#define UV_HANDLE_EMULATE_IOCP 0x00100000
-#define UV_HANDLE_BLOCKING_WRITES 0x00200000
-#define UV_HANDLE_CANCELLATION_PENDING 0x00400000
-
-/* Used by uv_tcp_t and uv_udp_t handles */
-#define UV_HANDLE_IPV6 0x01000000
-
-/* Only used by uv_tcp_t handles. */
-#define UV_HANDLE_TCP_NODELAY 0x02000000
-#define UV_HANDLE_TCP_KEEPALIVE 0x04000000
-#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000
-#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000
-#define UV_HANDLE_TCP_SOCKET_CLOSED 0x20000000
-#define UV_HANDLE_SHARED_TCP_SOCKET 0x40000000
-
-/* Only used by uv_pipe_t handles. */
-#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000
-#define UV_HANDLE_PIPESERVER 0x02000000
-#define UV_HANDLE_PIPE_READ_CANCELABLE 0x04000000
-
-/* Only used by uv_tty_t handles. */
-#define UV_HANDLE_TTY_READABLE 0x01000000
-#define UV_HANDLE_TTY_RAW 0x02000000
-#define UV_HANDLE_TTY_SAVED_POSITION 0x04000000
-#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x08000000
-
-/* Only used by uv_poll_t handles. */
-#define UV_HANDLE_POLL_SLOW 0x02000000
-
-
-/*
- * Requests: see req-inl.h
- */
-
-
-/*
- * Streams: see stream-inl.h
- */
-
-
-/*
* TCP
*/
+typedef enum {
+ UV__IPC_SOCKET_XFER_NONE = 0,
+ UV__IPC_SOCKET_XFER_TCP_CONNECTION,
+ UV__IPC_SOCKET_XFER_TCP_SERVER
+} uv__ipc_socket_xfer_type_t;
+
typedef struct {
WSAPROTOCOL_INFOW socket_info;
- int delayed_error;
-} uv__ipc_socket_info_ex;
+ uint32_t delayed_error;
+} uv__ipc_socket_xfer_info_t;
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
@@ -154,11 +96,13 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
-int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
- int tcp_connection);
-
-int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
- LPWSAPROTOCOL_INFOW protocol_info);
+int uv__tcp_xfer_export(uv_tcp_t* handle,
+ int pid,
+ uv__ipc_socket_xfer_type_t* xfer_type,
+ uv__ipc_socket_xfer_info_t* xfer_info);
+int uv__tcp_xfer_import(uv_tcp_t* tcp,
+ uv__ipc_socket_xfer_type_t xfer_type,
+ uv__ipc_socket_xfer_info_t* xfer_info);
/*
@@ -182,14 +126,14 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
-int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
- const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
-int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
- const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle,
- uv_write_cb cb);
-void uv__pipe_pause_read(uv_pipe_t* handle);
-void uv__pipe_unpause_read(uv_pipe_t* handle);
-void uv__pipe_stop_read(uv_pipe_t* handle);
+void uv__pipe_read_stop(uv_pipe_t* handle);
+int uv__pipe_write(uv_loop_t* loop,
+ uv_write_t* req,
+ uv_pipe_t* handle,
+ const uv_buf_t bufs[],
+ size_t nbufs,
+ uv_stream_t* send_handle,
+ uv_write_cb cb);
void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_req_t* req);
@@ -252,15 +196,6 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
/*
- * Timers
- */
-void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle);
-
-DWORD uv__next_timeout(const uv_loop_t* loop);
-void uv_process_timers(uv_loop_t* loop);
-
-
-/*
* Loop watchers
*/
void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle);
@@ -336,7 +271,6 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
void uv__util_init(void);
uint64_t uv__hrtime(double scale);
-int uv_current_pid(void);
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
diff --git a/Utilities/cmlibuv/src/win/loop-watcher.c b/Utilities/cmlibuv/src/win/loop-watcher.c
index 20e4509..ad7fbea 100644
--- a/Utilities/cmlibuv/src/win/loop-watcher.c
+++ b/Utilities/cmlibuv/src/win/loop-watcher.c
@@ -27,7 +27,7 @@
void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
handle->flags |= UV_HANDLE_CLOSED;
uv__handle_close(handle);
diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c
index 83ee4f9..277f649 100644
--- a/Utilities/cmlibuv/src/win/pipe.c
+++ b/Utilities/cmlibuv/src/win/pipe.c
@@ -21,39 +21,28 @@
#include <assert.h>
#include <io.h>
-#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
-#include "uv.h"
-#include "internal.h"
#include "handle-inl.h"
-#include "stream-inl.h"
+#include "internal.h"
#include "req-inl.h"
+#include "stream-inl.h"
+#include "uv-common.h"
+#include "uv.h"
#include <aclapi.h>
#include <accctrl.h>
-typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t;
-
-struct uv__ipc_queue_item_s {
- /*
- * NOTE: It is important for socket_info_ex to be the first field,
- * because we will we assigning it to the pending_ipc_info.socket_info
- */
- uv__ipc_socket_info_ex socket_info_ex;
- QUEUE member;
- int tcp_connection;
-};
-
/* A zero-size buffer for use by uv_pipe_read */
static char uv_zero_[] = "";
/* Null uv_buf_t */
static const uv_buf_t uv_null_buf_ = { 0, NULL };
-/* The timeout that the pipe will wait for the remote end to write data */
-/* when the local ends wants to shut it down. */
+/* The timeout that the pipe will wait for the remote end to write data when
+ * the local ends wants to shut it down. */
static const int64_t eof_timeout = 50; /* ms */
static const int default_pending_pipe_instances = 4;
@@ -62,22 +51,44 @@ static const int default_pending_pipe_instances = 4;
static char pipe_prefix[] = "\\\\?\\pipe";
static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
-/* IPC protocol flags. */
-#define UV_IPC_RAW_DATA 0x0001
-#define UV_IPC_TCP_SERVER 0x0002
-#define UV_IPC_TCP_CONNECTION 0x0004
+/* IPC incoming xfer queue item. */
+typedef struct {
+ uv__ipc_socket_xfer_type_t xfer_type;
+ uv__ipc_socket_xfer_info_t xfer_info;
+ QUEUE member;
+} uv__ipc_xfer_queue_item_t;
+
+/* IPC frame header flags. */
+/* clang-format off */
+enum {
+ UV__IPC_FRAME_HAS_DATA = 0x01,
+ UV__IPC_FRAME_HAS_SOCKET_XFER = 0x02,
+ UV__IPC_FRAME_XFER_IS_TCP_CONNECTION = 0x04,
+ /* These are combinations of the flags above. */
+ UV__IPC_FRAME_XFER_FLAGS = 0x06,
+ UV__IPC_FRAME_VALID_FLAGS = 0x07
+};
+/* clang-format on */
/* IPC frame header. */
typedef struct {
- int flags;
- uint64_t raw_data_length;
-} uv_ipc_frame_header_t;
-
-/* IPC frame, which contains an imported TCP socket stream. */
+ uint32_t flags;
+ uint32_t reserved1; /* Ignored. */
+ uint32_t data_length; /* Must be zero if there is no data. */
+ uint32_t reserved2; /* Must be zero. */
+} uv__ipc_frame_header_t;
+
+/* To implement the IPC protocol correctly, these structures must have exactly
+ * the right size. */
+STATIC_ASSERT(sizeof(uv__ipc_frame_header_t) == 16);
+STATIC_ASSERT(sizeof(uv__ipc_socket_xfer_info_t) == 632);
+
+/* Coalesced write request. */
typedef struct {
- uv_ipc_frame_header_t header;
- uv__ipc_socket_info_ex socket_info_ex;
-} uv_ipc_frame_uv_stream;
+ uv_write_t req; /* Internal heap-allocated write request. */
+ uv_write_t* user_req; /* Pointer to user-specified uv_write_t. */
+} uv__coalesced_write_t;
+
static void eof_timer_init(uv_pipe_t* pipe);
static void eof_timer_start(uv_pipe_t* pipe);
@@ -98,15 +109,12 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
handle->reqs_pending = 0;
handle->handle = INVALID_HANDLE_VALUE;
handle->name = NULL;
- handle->pipe.conn.ipc_pid = 0;
- handle->pipe.conn.remaining_ipc_rawdata_bytes = 0;
- QUEUE_INIT(&handle->pipe.conn.pending_ipc_info.queue);
- handle->pipe.conn.pending_ipc_info.queue_len = 0;
+ handle->pipe.conn.ipc_remote_pid = 0;
+ handle->pipe.conn.ipc_data_frame.payload_remaining = 0;
+ QUEUE_INIT(&handle->pipe.conn.ipc_xfer_queue);
+ handle->pipe.conn.ipc_xfer_queue_length = 0;
handle->ipc = ipc;
handle->pipe.conn.non_overlapped_writes_tail = NULL;
- handle->pipe.conn.readfile_thread = NULL;
-
- UV_REQ_INIT(&handle->pipe.conn.ipc_header_write_req, UV_UNKNOWN_REQ);
return 0;
}
@@ -117,10 +125,9 @@ static void uv_pipe_connection_init(uv_pipe_t* handle) {
handle->read_req.data = handle;
handle->pipe.conn.eof_timer = NULL;
assert(!(handle->flags & UV_HANDLE_PIPESERVER));
- if (pCancelSynchronousIo &&
- handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
- uv_mutex_init(&handle->pipe.conn.readfile_mutex);
- handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE;
+ if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
+ handle->pipe.conn.readfile_thread_handle = NULL;
+ InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);
}
}
@@ -347,12 +354,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_PIPE_LOCAL_INFORMATION pipe_info;
- uv__ipc_queue_item_t* item;
-
- if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- handle->flags &= ~UV_HANDLE_PIPE_READ_CANCELABLE;
- uv_mutex_destroy(&handle->pipe.conn.readfile_mutex);
- }
+ uv__ipc_xfer_queue_item_t* xfer_queue_item;
if ((handle->flags & UV_HANDLE_CONNECTION) &&
handle->stream.conn.shutdown_req != NULL &&
@@ -362,7 +364,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
/* Clear the shutdown_req field so we don't go here again. */
handle->stream.conn.shutdown_req = NULL;
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
UNREGISTER_HANDLE_REQ(loop, handle, req);
/* Already closing. Cancel the shutdown. */
@@ -423,33 +425,33 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
}
}
- if (handle->flags & UV__HANDLE_CLOSING &&
+ if (handle->flags & UV_HANDLE_CLOSING &&
handle->reqs_pending == 0) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
if (handle->flags & UV_HANDLE_CONNECTION) {
/* Free pending sockets */
- while (!QUEUE_EMPTY(&handle->pipe.conn.pending_ipc_info.queue)) {
+ while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {
QUEUE* q;
SOCKET socket;
- q = QUEUE_HEAD(&handle->pipe.conn.pending_ipc_info.queue);
+ q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);
QUEUE_REMOVE(q);
- item = QUEUE_DATA(q, uv__ipc_queue_item_t, member);
+ xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
/* Materialize socket and close it */
socket = WSASocketW(FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
- &item->socket_info_ex.socket_info,
+ &xfer_queue_item->xfer_info.socket_info,
0,
WSA_FLAG_OVERLAPPED);
- uv__free(item);
+ uv__free(xfer_queue_item);
if (socket != INVALID_SOCKET)
closesocket(socket);
}
- handle->pipe.conn.pending_ipc_info.queue_len = 0;
+ handle->pipe.conn.ipc_xfer_queue_length = 0;
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
@@ -461,6 +463,9 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
handle->read_req.event_handle = NULL;
}
}
+
+ if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)
+ DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);
}
if (handle->flags & UV_HANDLE_PIPESERVER) {
@@ -595,8 +600,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
loop = handle->loop;
assert(loop);
- /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. */
- /* We wait for the pipe to become available with WaitNamedPipe. */
+ /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait
+ * for the pipe to become available with WaitNamedPipe. */
while (WaitNamedPipeW(handle->name, 30000)) {
/* The pipe is now available, try to connect. */
pipeHandle = open_named_pipe(handle->name, &duplex_flags);
@@ -706,55 +711,68 @@ error:
}
-void uv__pipe_pause_read(uv_pipe_t* handle) {
- if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- /* Pause the ReadFile task briefly, to work
- around the Windows kernel bug that causes
- any access to a NamedPipe to deadlock if
- any process has called ReadFile */
- HANDLE h;
- uv_mutex_lock(&handle->pipe.conn.readfile_mutex);
- h = handle->pipe.conn.readfile_thread;
- while (h) {
- /* spinlock: we expect this to finish quickly,
- or we are probably about to deadlock anyways
- (in the kernel), so it doesn't matter */
- pCancelSynchronousIo(h);
- SwitchToThread(); /* yield thread control briefly */
- h = handle->pipe.conn.readfile_thread;
- }
- }
-}
+void uv__pipe_interrupt_read(uv_pipe_t* handle) {
+ BOOL r;
+
+ if (!(handle->flags & UV_HANDLE_READ_PENDING))
+ return; /* No pending reads. */
+ if (handle->flags & UV_HANDLE_CANCELLATION_PENDING)
+ return; /* Already cancelled. */
+ if (handle->handle == INVALID_HANDLE_VALUE)
+ return; /* Pipe handle closed. */
+ if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) {
+ /* Cancel asynchronous read. */
+ r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
+ assert(r || GetLastError() == ERROR_NOT_FOUND);
-void uv__pipe_unpause_read(uv_pipe_t* handle) {
- if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- uv_mutex_unlock(&handle->pipe.conn.readfile_mutex);
+ } else {
+ /* Cancel synchronous read (which is happening in the thread pool). */
+ HANDLE thread;
+ volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
+
+ EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock);
+
+ thread = *thread_ptr;
+ if (thread == NULL) {
+ /* The thread pool thread has not yet reached the point of blocking, we
+ * can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */
+ *thread_ptr = INVALID_HANDLE_VALUE;
+
+ } else {
+ /* Spin until the thread has acknowledged (by setting the thread to
+ * INVALID_HANDLE_VALUE) that it is past the point of blocking. */
+ while (thread != INVALID_HANDLE_VALUE) {
+ r = CancelSynchronousIo(thread);
+ assert(r || GetLastError() == ERROR_NOT_FOUND);
+ SwitchToThread(); /* Yield thread. */
+ thread = *thread_ptr;
+ }
+ }
+
+ LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock);
}
+
+ /* Set flag to indicate that read has been cancelled. */
+ handle->flags |= UV_HANDLE_CANCELLATION_PENDING;
}
-void uv__pipe_stop_read(uv_pipe_t* handle) {
- if (pCancelIoEx &&
- !(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) &&
- !(handle->flags & UV_HANDLE_EMULATE_IOCP) &&
- handle->flags & UV_HANDLE_READING &&
- handle->read_req.type == UV_READ) {
- pCancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
- }
+void uv__pipe_read_stop(uv_pipe_t* handle) {
handle->flags &= ~UV_HANDLE_READING;
- uv__pipe_pause_read((uv_pipe_t*)handle);
- uv__pipe_unpause_read((uv_pipe_t*)handle);
+ DECREASE_ACTIVE_COUNT(handle->loop, handle);
+
+ uv__pipe_interrupt_read(handle);
}
-/* Cleans up uv_pipe_t (server or connection) and all resources associated */
-/* with it. */
+/* Cleans up uv_pipe_t (server or connection) and all resources associated with
+ * it. */
void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
int i;
HANDLE pipeHandle;
- uv__pipe_stop_read(handle);
+ uv__pipe_interrupt_read(handle);
if (handle->name) {
uv__free(handle->name);
@@ -864,23 +882,22 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
uv_pipe_t* pipe_client;
uv_pipe_accept_t* req;
QUEUE* q;
- uv__ipc_queue_item_t* item;
+ uv__ipc_xfer_queue_item_t* item;
int err;
if (server->ipc) {
- if (QUEUE_EMPTY(&server->pipe.conn.pending_ipc_info.queue)) {
+ if (QUEUE_EMPTY(&server->pipe.conn.ipc_xfer_queue)) {
/* No valid pending sockets. */
return WSAEWOULDBLOCK;
}
- q = QUEUE_HEAD(&server->pipe.conn.pending_ipc_info.queue);
+ q = QUEUE_HEAD(&server->pipe.conn.ipc_xfer_queue);
QUEUE_REMOVE(q);
- server->pipe.conn.pending_ipc_info.queue_len--;
- item = QUEUE_DATA(q, uv__ipc_queue_item_t, member);
+ server->pipe.conn.ipc_xfer_queue_length--;
+ item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
- err = uv_tcp_import((uv_tcp_t*)client,
- &item->socket_info_ex,
- item->tcp_connection);
+ err = uv__tcp_xfer_import(
+ (uv_tcp_t*) client, item->xfer_type, &item->xfer_info);
if (err != 0)
return err;
@@ -889,8 +906,8 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
} else {
pipe_client = (uv_pipe_t*)client;
- /* Find a connection instance that has been connected, but not yet */
- /* accepted. */
+ /* Find a connection instance that has been connected, but not yet
+ * accepted. */
req = server->pipe.serv.pending_accepts;
if (!req) {
@@ -908,7 +925,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
req->next_pending = NULL;
req->pipeHandle = INVALID_HANDLE_VALUE;
- if (!(server->flags & UV__HANDLE_CLOSING)) {
+ if (!(server->flags & UV_HANDLE_CLOSING)) {
uv_pipe_queue_accept(loop, server, req, FALSE);
}
}
@@ -953,74 +970,75 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
}
-static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) {
- int result;
- DWORD bytes;
- uv_read_t* req = (uv_read_t*) parameter;
+static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* arg) {
+ uv_read_t* req = (uv_read_t*) arg;
uv_pipe_t* handle = (uv_pipe_t*) req->data;
uv_loop_t* loop = handle->loop;
- HANDLE hThread = NULL;
+ volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
+ CRITICAL_SECTION* lock = &handle->pipe.conn.readfile_thread_lock;
+ HANDLE thread;
+ DWORD bytes;
DWORD err;
- uv_mutex_t *m = &handle->pipe.conn.readfile_mutex;
- assert(req != NULL);
assert(req->type == UV_READ);
assert(handle->type == UV_NAMED_PIPE);
- if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */
- if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
- GetCurrentProcess(), &hThread,
- 0, FALSE, DUPLICATE_SAME_ACCESS)) {
- handle->pipe.conn.readfile_thread = hThread;
- } else {
- hThread = NULL;
- }
- uv_mutex_unlock(m);
+ err = 0;
+
+ /* Create a handle to the current thread. */
+ if (!DuplicateHandle(GetCurrentProcess(),
+ GetCurrentThread(),
+ GetCurrentProcess(),
+ &thread,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ err = GetLastError();
+ goto out1;
}
-restart_readfile:
- if (handle->flags & UV_HANDLE_READING) {
- result = ReadFile(handle->handle,
- &uv_zero_,
- 0,
- &bytes,
- NULL);
- if (!result) {
- err = GetLastError();
- if (err == ERROR_OPERATION_ABORTED &&
- handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- if (handle->flags & UV_HANDLE_READING) {
- /* just a brief break to do something else */
- handle->pipe.conn.readfile_thread = NULL;
- /* resume after it is finished */
- uv_mutex_lock(m);
- handle->pipe.conn.readfile_thread = hThread;
- uv_mutex_unlock(m);
- goto restart_readfile;
- } else {
- result = 1; /* successfully stopped reading */
- }
- }
- }
+
+ /* The lock needs to be held when thread handle is modified. */
+ EnterCriticalSection(lock);
+ if (*thread_ptr == INVALID_HANDLE_VALUE) {
+ /* uv__pipe_interrupt_read() cancelled reading before we got here. */
+ err = ERROR_OPERATION_ABORTED;
} else {
- result = 1; /* successfully aborted read before it even started */
- }
- if (hThread) {
- assert(hThread == handle->pipe.conn.readfile_thread);
- /* mutex does not control clearing readfile_thread */
- handle->pipe.conn.readfile_thread = NULL;
- uv_mutex_lock(m);
- /* only when we hold the mutex lock is it safe to
- open or close the handle */
- CloseHandle(hThread);
- uv_mutex_unlock(m);
+ /* Let main thread know which worker thread is doing the blocking read. */
+ assert(*thread_ptr == NULL);
+ *thread_ptr = thread;
}
+ LeaveCriticalSection(lock);
- if (!result) {
- SET_REQ_ERROR(req, err);
- }
+ if (err)
+ goto out2;
+
+ /* Block the thread until data is available on the pipe, or the read is
+ * cancelled. */
+ if (!ReadFile(handle->handle, &uv_zero_, 0, &bytes, NULL))
+ err = GetLastError();
+
+ /* Let the main thread know the worker is past the point of blocking. */
+ assert(thread == *thread_ptr);
+ *thread_ptr = INVALID_HANDLE_VALUE;
+
+ /* Briefly acquire the mutex. Since the main thread holds the lock while it
+ * is spinning trying to cancel this thread's I/O, we will block here until
+ * it stops doing that. */
+ EnterCriticalSection(lock);
+ LeaveCriticalSection(lock);
+out2:
+ /* Close the handle to the current thread. */
+ CloseHandle(thread);
+
+out1:
+ /* Set request status and post a completion record to the IOCP. */
+ if (err)
+ SET_REQ_ERROR(req, err);
+ else
+ SET_REQ_SUCCESS(req);
POST_COMPLETION_FOR_REQ(loop, req);
+
return 0;
}
@@ -1102,6 +1120,7 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
req = &handle->read_req;
if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
+ handle->pipe.conn.readfile_thread_handle = NULL; /* Reset cancellation. */
if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc,
req,
WT_EXECUTELONGFUNCTION)) {
@@ -1169,8 +1188,8 @@ int uv_pipe_read_start(uv_pipe_t* handle,
handle->read_cb = read_cb;
handle->alloc_cb = alloc_cb;
- /* If reading was stopped and then started again, there could still be a */
- /* read request pending. */
+ /* If reading was stopped and then started again, there could still be a read
+ * request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING))
uv_pipe_queue_read(loop, handle);
@@ -1226,154 +1245,110 @@ static void uv_queue_non_overlapped_write(uv_pipe_t* handle) {
}
-static int uv_pipe_write_impl(uv_loop_t* loop,
- uv_write_t* req,
- uv_pipe_t* handle,
- const uv_buf_t bufs[],
- unsigned int nbufs,
- uv_stream_t* send_handle,
- uv_write_cb cb) {
- int err;
- int result;
- uv_tcp_t* tcp_send_handle;
- uv_write_t* ipc_header_req = NULL;
- uv_ipc_frame_uv_stream ipc_frame;
+static int uv__build_coalesced_write_req(uv_write_t* user_req,
+ const uv_buf_t bufs[],
+ size_t nbufs,
+ uv_write_t** req_out,
+ uv_buf_t* write_buf_out) {
+ /* Pack into a single heap-allocated buffer:
+ * (a) a uv_write_t structure where libuv stores the actual state.
+ * (b) a pointer to the original uv_write_t.
+ * (c) data from all `bufs` entries.
+ */
+ char* heap_buffer;
+ size_t heap_buffer_length, heap_buffer_offset;
+ uv__coalesced_write_t* coalesced_write_req; /* (a) + (b) */
+ char* data_start; /* (c) */
+ size_t data_length;
+ unsigned int i;
+
+ /* Compute combined size of all combined buffers from `bufs`. */
+ data_length = 0;
+ for (i = 0; i < nbufs; i++)
+ data_length += bufs[i].len;
+
+ /* The total combined size of data buffers should not exceed UINT32_MAX,
+ * because WriteFile() won't accept buffers larger than that. */
+ if (data_length > UINT32_MAX)
+ return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
+
+ /* Compute heap buffer size. */
+ heap_buffer_length = sizeof *coalesced_write_req + /* (a) + (b) */
+ data_length; /* (c) */
+
+ /* Allocate buffer. */
+ heap_buffer = uv__malloc(heap_buffer_length);
+ if (heap_buffer == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */
+
+ /* Copy uv_write_t information to the buffer. */
+ coalesced_write_req = (uv__coalesced_write_t*) heap_buffer;
+ coalesced_write_req->req = *user_req; /* copy (a) */
+ coalesced_write_req->req.coalesced = 1;
+ coalesced_write_req->user_req = user_req; /* copy (b) */
+ heap_buffer_offset = sizeof *coalesced_write_req; /* offset (a) + (b) */
+
+ /* Copy data buffers to the heap buffer. */
+ data_start = &heap_buffer[heap_buffer_offset];
+ for (i = 0; i < nbufs; i++) {
+ memcpy(&heap_buffer[heap_buffer_offset],
+ bufs[i].base,
+ bufs[i].len); /* copy (c) */
+ heap_buffer_offset += bufs[i].len; /* offset (c) */
+ }
+ assert(heap_buffer_offset == heap_buffer_length);
+
+ /* Set out arguments and return. */
+ *req_out = &coalesced_write_req->req;
+ *write_buf_out = uv_buf_init(data_start, (unsigned int) data_length);
+ return 0;
+}
- if (nbufs != 1 && (nbufs != 0 || !send_handle)) {
- return ERROR_NOT_SUPPORTED;
- }
- /* Only TCP handles are supported for sharing. */
- if (send_handle && ((send_handle->type != UV_TCP) ||
- (!(send_handle->flags & UV_HANDLE_BOUND) &&
- !(send_handle->flags & UV_HANDLE_CONNECTION)))) {
- return ERROR_NOT_SUPPORTED;
- }
+static int uv__pipe_write_data(uv_loop_t* loop,
+ uv_write_t* req,
+ uv_pipe_t* handle,
+ const uv_buf_t bufs[],
+ size_t nbufs,
+ uv_write_cb cb,
+ int copy_always) {
+ int err;
+ int result;
+ uv_buf_t write_buf;
assert(handle->handle != INVALID_HANDLE_VALUE);
UV_REQ_INIT(req, UV_WRITE);
req->handle = (uv_stream_t*) handle;
+ req->send_handle = NULL;
req->cb = cb;
- req->ipc_header = 0;
+ /* Private fields. */
+ req->coalesced = 0;
req->event_handle = NULL;
req->wait_handle = INVALID_HANDLE_VALUE;
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-
- if (handle->ipc) {
- assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
- ipc_frame.header.flags = 0;
-
- /* Use the IPC framing protocol. */
- if (send_handle) {
- tcp_send_handle = (uv_tcp_t*)send_handle;
-
- if (handle->pipe.conn.ipc_pid == 0) {
- handle->pipe.conn.ipc_pid = uv_current_pid();
- }
-
- err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid,
- &ipc_frame.socket_info_ex.socket_info);
- if (err) {
- return err;
- }
-
- ipc_frame.socket_info_ex.delayed_error = tcp_send_handle->delayed_error;
-
- ipc_frame.header.flags |= UV_IPC_TCP_SERVER;
-
- if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) {
- ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION;
- }
- }
-
- if (nbufs == 1) {
- ipc_frame.header.flags |= UV_IPC_RAW_DATA;
- ipc_frame.header.raw_data_length = bufs[0].len;
- }
-
- /*
- * Use the provided req if we're only doing a single write.
- * If we're doing multiple writes, use ipc_header_write_req to do
- * the first write, and then use the provided req for the second write.
- */
- if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) {
- ipc_header_req = req;
- } else {
- /*
- * Try to use the preallocated write req if it's available.
- * Otherwise allocate a new one.
- */
- if (handle->pipe.conn.ipc_header_write_req.type != UV_WRITE) {
- ipc_header_req = (uv_write_t*)&handle->pipe.conn.ipc_header_write_req;
- } else {
- ipc_header_req = (uv_write_t*)uv__malloc(sizeof(uv_write_t));
- if (!ipc_header_req) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
- }
- }
-
- UV_REQ_INIT(ipc_header_req, UV_WRITE);
- ipc_header_req->handle = (uv_stream_t*) handle;
- ipc_header_req->cb = NULL;
- ipc_header_req->ipc_header = 1;
- }
-
- /* Write the header or the whole frame. */
- memset(&ipc_header_req->u.io.overlapped, 0,
- sizeof(ipc_header_req->u.io.overlapped));
-
- /* Using overlapped IO, but wait for completion before returning.
- This write is blocking because ipc_frame is on stack. */
- ipc_header_req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL);
- if (!ipc_header_req->u.io.overlapped.hEvent) {
- uv_fatal_error(GetLastError(), "CreateEvent");
- }
-
- result = WriteFile(handle->handle,
- &ipc_frame,
- ipc_frame.header.flags & UV_IPC_TCP_SERVER ?
- sizeof(ipc_frame) : sizeof(ipc_frame.header),
- NULL,
- &ipc_header_req->u.io.overlapped);
- if (!result && GetLastError() != ERROR_IO_PENDING) {
- err = GetLastError();
- CloseHandle(ipc_header_req->u.io.overlapped.hEvent);
+ req->write_buffer = uv_null_buf_;
+
+ if (nbufs == 0) {
+ /* Write empty buffer. */
+ write_buf = uv_null_buf_;
+ } else if (nbufs == 1 && !copy_always) {
+ /* Write directly from bufs[0]. */
+ write_buf = bufs[0];
+ } else {
+ /* Coalesce all `bufs` into one big buffer. This also creates a new
+ * write-request structure that replaces the old one. */
+ err = uv__build_coalesced_write_req(req, bufs, nbufs, &req, &write_buf);
+ if (err != 0)
return err;
- }
-
- if (!result) {
- /* Request not completed immediately. Wait for it.*/
- if (WaitForSingleObject(ipc_header_req->u.io.overlapped.hEvent, INFINITE) !=
- WAIT_OBJECT_0) {
- err = GetLastError();
- CloseHandle(ipc_header_req->u.io.overlapped.hEvent);
- return err;
- }
- }
- ipc_header_req->u.io.queued_bytes = 0;
- CloseHandle(ipc_header_req->u.io.overlapped.hEvent);
- ipc_header_req->u.io.overlapped.hEvent = NULL;
-
- REGISTER_HANDLE_REQ(loop, handle, ipc_header_req);
- handle->reqs_pending++;
- handle->stream.conn.write_reqs_pending++;
-
- /* If we don't have any raw data to write - we're done. */
- if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) {
- return 0;
- }
}
if ((handle->flags &
(UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) ==
(UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) {
DWORD bytes;
- result = WriteFile(handle->handle,
- bufs[0].base,
- bufs[0].len,
- &bytes,
- NULL);
+ result =
+ WriteFile(handle->handle, write_buf.base, write_buf.len, &bytes, NULL);
if (!result) {
err = GetLastError();
@@ -1389,14 +1364,14 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
POST_COMPLETION_FOR_REQ(loop, req);
return 0;
} else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
- req->write_buffer = bufs[0];
+ req->write_buffer = write_buf;
uv_insert_non_overlapped_write_req(handle, req);
if (handle->stream.conn.write_reqs_pending == 0) {
uv_queue_non_overlapped_write(handle);
}
/* Request queued by the kernel. */
- req->u.io.queued_bytes = bufs[0].len;
+ req->u.io.queued_bytes = write_buf.len;
handle->write_queue_size += req->u.io.queued_bytes;
} else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) {
/* Using overlapped IO, but wait for completion before returning */
@@ -1406,8 +1381,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
}
result = WriteFile(handle->handle,
- bufs[0].base,
- bufs[0].len,
+ write_buf.base,
+ write_buf.len,
NULL,
&req->u.io.overlapped);
@@ -1422,13 +1397,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
req->u.io.queued_bytes = 0;
} else {
/* Request queued by the kernel. */
- req->u.io.queued_bytes = bufs[0].len;
+ req->u.io.queued_bytes = write_buf.len;
handle->write_queue_size += req->u.io.queued_bytes;
if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) !=
WAIT_OBJECT_0) {
err = GetLastError();
CloseHandle(req->u.io.overlapped.hEvent);
- return uv_translate_sys_error(err);
+ return err;
}
}
CloseHandle(req->u.io.overlapped.hEvent);
@@ -1439,8 +1414,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
return 0;
} else {
result = WriteFile(handle->handle,
- bufs[0].base,
- bufs[0].len,
+ write_buf.base,
+ write_buf.len,
NULL,
&req->u.io.overlapped);
@@ -1453,7 +1428,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
req->u.io.queued_bytes = 0;
} else {
/* Request queued by the kernel. */
- req->u.io.queued_bytes = bufs[0].len;
+ req->u.io.queued_bytes = write_buf.len;
handle->write_queue_size += req->u.io.queued_bytes;
}
@@ -1478,35 +1453,143 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
}
-int uv_pipe_write(uv_loop_t* loop,
- uv_write_t* req,
- uv_pipe_t* handle,
- const uv_buf_t bufs[],
- unsigned int nbufs,
- uv_write_cb cb) {
- return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, NULL, cb);
+static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t* handle) {
+ DWORD* pid = &handle->pipe.conn.ipc_remote_pid;
+
+ /* If the both ends of the IPC pipe are owned by the same process,
+ * the remote end pid may not yet be set. If so, do it here.
+ * TODO: this is weird; it'd probably better to use a handshake. */
+ if (*pid == 0)
+ *pid = GetCurrentProcessId();
+
+ return *pid;
+}
+
+
+int uv__pipe_write_ipc(uv_loop_t* loop,
+ uv_write_t* req,
+ uv_pipe_t* handle,
+ const uv_buf_t data_bufs[],
+ size_t data_buf_count,
+ uv_stream_t* send_handle,
+ uv_write_cb cb) {
+ uv_buf_t stack_bufs[6];
+ uv_buf_t* bufs;
+ size_t buf_count, buf_index;
+ uv__ipc_frame_header_t frame_header;
+ uv__ipc_socket_xfer_type_t xfer_type = UV__IPC_SOCKET_XFER_NONE;
+ uv__ipc_socket_xfer_info_t xfer_info;
+ uint64_t data_length;
+ size_t i;
+ int err;
+
+ /* Compute the combined size of data buffers. */
+ data_length = 0;
+ for (i = 0; i < data_buf_count; i++)
+ data_length += data_bufs[i].len;
+ if (data_length > UINT32_MAX)
+ return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
+
+ /* Prepare the frame's socket xfer payload. */
+ if (send_handle != NULL) {
+ uv_tcp_t* send_tcp_handle = (uv_tcp_t*) send_handle;
+
+ /* Verify that `send_handle` it is indeed a tcp handle. */
+ if (send_tcp_handle->type != UV_TCP)
+ return ERROR_NOT_SUPPORTED;
+
+ /* Export the tcp handle. */
+ err = uv__tcp_xfer_export(send_tcp_handle,
+ uv__pipe_get_ipc_remote_pid(handle),
+ &xfer_type,
+ &xfer_info);
+ if (err != 0)
+ return err;
+ }
+
+ /* Compute the number of uv_buf_t's required. */
+ buf_count = 1 + data_buf_count; /* Frame header and data buffers. */
+ if (send_handle != NULL)
+ buf_count += 1; /* One extra for the socket xfer information. */
+
+ /* Use the on-stack buffer array if it is big enough; otherwise allocate
+ * space for it on the heap. */
+ if (buf_count < ARRAY_SIZE(stack_bufs)) {
+ /* Use on-stack buffer array. */
+ bufs = stack_bufs;
+ } else {
+ /* Use heap-allocated buffer array. */
+ bufs = uv__calloc(buf_count, sizeof(uv_buf_t));
+ if (bufs == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */
+ }
+ buf_index = 0;
+
+ /* Initialize frame header and add it to the buffers list. */
+ memset(&frame_header, 0, sizeof frame_header);
+ bufs[buf_index++] = uv_buf_init((char*) &frame_header, sizeof frame_header);
+
+ if (send_handle != NULL) {
+ /* Add frame header flags. */
+ switch (xfer_type) {
+ case UV__IPC_SOCKET_XFER_TCP_CONNECTION:
+ frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER |
+ UV__IPC_FRAME_XFER_IS_TCP_CONNECTION;
+ break;
+ case UV__IPC_SOCKET_XFER_TCP_SERVER:
+ frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER;
+ break;
+ default:
+ assert(0); /* Unreachable. */
+ }
+ /* Add xfer info buffer. */
+ bufs[buf_index++] = uv_buf_init((char*) &xfer_info, sizeof xfer_info);
+ }
+
+ if (data_length > 0) {
+ /* Update frame header. */
+ frame_header.flags |= UV__IPC_FRAME_HAS_DATA;
+ frame_header.data_length = (uint32_t) data_length;
+ /* Add data buffers to buffers list. */
+ for (i = 0; i < data_buf_count; i++)
+ bufs[buf_index++] = data_bufs[i];
+ }
+
+ /* Write buffers. We set the `always_copy` flag, so it is not a problem that
+ * some of the written data lives on the stack. */
+ err = uv__pipe_write_data(loop, req, handle, bufs, buf_count, cb, 1);
+
+ /* If we had to heap-allocate the bufs array, free it now. */
+ if (bufs != stack_bufs) {
+ uv__free(bufs);
+ }
+
+ return err;
}
-int uv_pipe_write2(uv_loop_t* loop,
+int uv__pipe_write(uv_loop_t* loop,
uv_write_t* req,
uv_pipe_t* handle,
const uv_buf_t bufs[],
- unsigned int nbufs,
+ size_t nbufs,
uv_stream_t* send_handle,
uv_write_cb cb) {
- if (!handle->ipc) {
- return WSAEINVAL;
+ if (handle->ipc) {
+ /* IPC pipe write: use framing protocol. */
+ return uv__pipe_write_ipc(loop, req, handle, bufs, nbufs, send_handle, cb);
+ } else {
+ /* Non-IPC pipe write: put data on the wire directly. */
+ assert(send_handle == NULL);
+ return uv__pipe_write_data(loop, req, handle, bufs, nbufs, cb, 0);
}
-
- return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, send_handle, cb);
}
static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
uv_buf_t buf) {
- /* If there is an eof timer running, we don't need it any more, */
- /* so discard it. */
+ /* If there is an eof timer running, we don't need it any more, so discard
+ * it. */
eof_timer_destroy(handle);
handle->flags &= ~UV_HANDLE_READABLE;
@@ -1518,8 +1601,8 @@ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
uv_buf_t buf) {
- /* If there is an eof timer running, we don't need it any more, */
- /* so discard it. */
+ /* If there is an eof timer running, we don't need it any more, so discard
+ * it. */
eof_timer_destroy(handle);
uv_read_stop((uv_stream_t*) handle);
@@ -1530,10 +1613,7 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
int error, uv_buf_t buf) {
- if (error == ERROR_OPERATION_ABORTED) {
- /* do nothing (equivalent to EINTR) */
- }
- else if (error == ERROR_BROKEN_PIPE) {
+ if (error == ERROR_BROKEN_PIPE) {
uv_pipe_read_eof(loop, handle, buf);
} else {
uv_pipe_read_error(loop, handle, error, buf);
@@ -1541,152 +1621,228 @@ static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
}
-void uv__pipe_insert_pending_socket(uv_pipe_t* handle,
- uv__ipc_socket_info_ex* info,
- int tcp_connection) {
- uv__ipc_queue_item_t* item;
+static void uv__pipe_queue_ipc_xfer_info(
+ uv_pipe_t* handle,
+ uv__ipc_socket_xfer_type_t xfer_type,
+ uv__ipc_socket_xfer_info_t* xfer_info) {
+ uv__ipc_xfer_queue_item_t* item;
- item = (uv__ipc_queue_item_t*) uv__malloc(sizeof(*item));
+ item = (uv__ipc_xfer_queue_item_t*) uv__malloc(sizeof(*item));
if (item == NULL)
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
- memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex));
- item->tcp_connection = tcp_connection;
- QUEUE_INSERT_TAIL(&handle->pipe.conn.pending_ipc_info.queue, &item->member);
- handle->pipe.conn.pending_ipc_info.queue_len++;
+ item->xfer_type = xfer_type;
+ item->xfer_info = *xfer_info;
+
+ QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member);
+ handle->pipe.conn.ipc_xfer_queue_length++;
+}
+
+
+/* Read an exact number of bytes from a pipe. If an error or end-of-file is
+ * encountered before the requested number of bytes are read, an error is
+ * returned. */
+static int uv__pipe_read_exactly(HANDLE h, void* buffer, DWORD count) {
+ DWORD bytes_read, bytes_read_now;
+
+ bytes_read = 0;
+ while (bytes_read < count) {
+ if (!ReadFile(h,
+ (char*) buffer + bytes_read,
+ count - bytes_read,
+ &bytes_read_now,
+ NULL)) {
+ return GetLastError();
+ }
+
+ bytes_read += bytes_read_now;
+ }
+
+ assert(bytes_read == count);
+ return 0;
}
-void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
- uv_req_t* req) {
- DWORD bytes, avail;
+static DWORD uv__pipe_read_data(uv_loop_t* loop,
+ uv_pipe_t* handle,
+ DWORD suggested_bytes,
+ DWORD max_bytes) {
+ DWORD bytes_read;
uv_buf_t buf;
- uv_ipc_frame_uv_stream ipc_frame;
+ /* Ask the user for a buffer to read data into. */
+ buf = uv_buf_init(NULL, 0);
+ handle->alloc_cb((uv_handle_t*) handle, suggested_bytes, &buf);
+ if (buf.base == NULL || buf.len == 0) {
+ handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
+ return 0; /* Break out of read loop. */
+ }
+
+ /* Ensure we read at most the smaller of:
+ * (a) the length of the user-allocated buffer.
+ * (b) the maximum data length as specified by the `max_bytes` argument.
+ */
+ if (max_bytes > buf.len)
+ max_bytes = buf.len;
+
+ /* Read into the user buffer. */
+ if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) {
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
+ return 0; /* Break out of read loop. */
+ }
+
+ /* Call the read callback. */
+ handle->read_cb((uv_stream_t*) handle, bytes_read, &buf);
+
+ return bytes_read;
+}
+
+
+static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
+ uint32_t* data_remaining = &handle->pipe.conn.ipc_data_frame.payload_remaining;
+ int err;
+
+ if (*data_remaining > 0) {
+ /* Read frame data payload. */
+ DWORD bytes_read =
+ uv__pipe_read_data(loop, handle, *data_remaining, *data_remaining);
+ *data_remaining -= bytes_read;
+ return bytes_read;
+
+ } else {
+ /* Start of a new IPC frame. */
+ uv__ipc_frame_header_t frame_header;
+ uint32_t xfer_flags;
+ uv__ipc_socket_xfer_type_t xfer_type;
+ uv__ipc_socket_xfer_info_t xfer_info;
+
+ /* Read the IPC frame header. */
+ err = uv__pipe_read_exactly(
+ handle->handle, &frame_header, sizeof frame_header);
+ if (err)
+ goto error;
+
+ /* Validate that flags are valid. */
+ if ((frame_header.flags & ~UV__IPC_FRAME_VALID_FLAGS) != 0)
+ goto invalid;
+ /* Validate that reserved2 is zero. */
+ if (frame_header.reserved2 != 0)
+ goto invalid;
+
+ /* Parse xfer flags. */
+ xfer_flags = frame_header.flags & UV__IPC_FRAME_XFER_FLAGS;
+ if (xfer_flags & UV__IPC_FRAME_HAS_SOCKET_XFER) {
+ /* Socket coming -- determine the type. */
+ xfer_type = xfer_flags & UV__IPC_FRAME_XFER_IS_TCP_CONNECTION
+ ? UV__IPC_SOCKET_XFER_TCP_CONNECTION
+ : UV__IPC_SOCKET_XFER_TCP_SERVER;
+ } else if (xfer_flags == 0) {
+ /* No socket. */
+ xfer_type = UV__IPC_SOCKET_XFER_NONE;
+ } else {
+ /* Invalid flags. */
+ goto invalid;
+ }
+
+ /* Parse data frame information. */
+ if (frame_header.flags & UV__IPC_FRAME_HAS_DATA) {
+ *data_remaining = frame_header.data_length;
+ } else if (frame_header.data_length != 0) {
+ /* Data length greater than zero but data flag not set -- invalid. */
+ goto invalid;
+ }
+
+ /* If no socket xfer info follows, return here. Data will be read in a
+ * subsequent invocation of uv__pipe_read_ipc(). */
+ if (xfer_type == UV__IPC_SOCKET_XFER_NONE)
+ return sizeof frame_header; /* Number of bytes read. */
+
+ /* Read transferred socket information. */
+ err = uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info);
+ if (err)
+ goto error;
+
+ /* Store the pending socket info. */
+ uv__pipe_queue_ipc_xfer_info(handle, xfer_type, &xfer_info);
+
+ /* Return number of bytes read. */
+ return sizeof frame_header + sizeof xfer_info;
+ }
+
+invalid:
+ /* Invalid frame. */
+ err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */
+
+error:
+ uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
+ return 0; /* Break out of read loop. */
+}
+
+
+void uv_process_pipe_read_req(uv_loop_t* loop,
+ uv_pipe_t* handle,
+ uv_req_t* req) {
assert(handle->type == UV_NAMED_PIPE);
- handle->flags &= ~UV_HANDLE_READ_PENDING;
+ handle->flags &= ~(UV_HANDLE_READ_PENDING | UV_HANDLE_CANCELLATION_PENDING);
+ DECREASE_PENDING_REQ_COUNT(handle);
eof_timer_stop(handle);
- if (!REQ_SUCCESS(req)) {
- /* An error occurred doing the 0-read. */
- if (handle->flags & UV_HANDLE_READING) {
- uv_pipe_read_error_or_eof(loop,
- handle,
- GET_REQ_ERROR(req),
- uv_null_buf_);
- }
- } else {
- /* Do non-blocking reads until the buffer is empty */
- while (handle->flags & UV_HANDLE_READING) {
- if (!PeekNamedPipe(handle->handle,
- NULL,
- 0,
- NULL,
- &avail,
- NULL)) {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
- break;
- }
+ /* At this point, we're done with bookkeeping. If the user has stopped
+ * reading the pipe in the meantime, there is nothing left to do, since there
+ * is no callback that we can call. */
+ if (!(handle->flags & UV_HANDLE_READING))
+ return;
- if (avail == 0) {
- /* There is nothing to read after all. */
- break;
- }
+ if (!REQ_SUCCESS(req)) {
+ /* An error occurred doing the zero-read. */
+ DWORD err = GET_REQ_ERROR(req);
- if (handle->ipc) {
- /* Use the IPC framing protocol to read the incoming data. */
- if (handle->pipe.conn.remaining_ipc_rawdata_bytes == 0) {
- /* We're reading a new frame. First, read the header. */
- assert(avail >= sizeof(ipc_frame.header));
-
- if (!ReadFile(handle->handle,
- &ipc_frame.header,
- sizeof(ipc_frame.header),
- &bytes,
- NULL)) {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(),
- uv_null_buf_);
- break;
- }
-
- assert(bytes == sizeof(ipc_frame.header));
- assert(ipc_frame.header.flags <= (UV_IPC_TCP_SERVER | UV_IPC_RAW_DATA |
- UV_IPC_TCP_CONNECTION));
-
- if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) {
- assert(avail - sizeof(ipc_frame.header) >=
- sizeof(ipc_frame.socket_info_ex));
-
- /* Read the TCP socket info. */
- if (!ReadFile(handle->handle,
- &ipc_frame.socket_info_ex,
- sizeof(ipc_frame) - sizeof(ipc_frame.header),
- &bytes,
- NULL)) {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(),
- uv_null_buf_);
- break;
- }
-
- assert(bytes == sizeof(ipc_frame) - sizeof(ipc_frame.header));
-
- /* Store the pending socket info. */
- uv__pipe_insert_pending_socket(
- handle,
- &ipc_frame.socket_info_ex,
- ipc_frame.header.flags & UV_IPC_TCP_CONNECTION);
- }
-
- if (ipc_frame.header.flags & UV_IPC_RAW_DATA) {
- handle->pipe.conn.remaining_ipc_rawdata_bytes =
- ipc_frame.header.raw_data_length;
- continue;
- }
- } else {
- avail = min(avail, (DWORD)handle->pipe.conn.remaining_ipc_rawdata_bytes);
- }
- }
+ /* If the read was cancelled by uv__pipe_interrupt_read(), the request may
+ * indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to
+ * the user; we'll start a new zero-read at the end of this function. */
+ if (err != ERROR_OPERATION_ABORTED)
+ uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
- buf = uv_buf_init(NULL, 0);
- handle->alloc_cb((uv_handle_t*) handle, avail, &buf);
- if (buf.base == NULL || buf.len == 0) {
- handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
+ } else {
+ /* The zero-read completed without error, indicating there is data
+ * available in the kernel buffer. */
+ DWORD avail;
+
+ /* Get the number of bytes available. */
+ avail = 0;
+ if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL))
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
+
+ /* Read until we've either read all the bytes available, or the 'reading'
+ * flag is cleared. */
+ while (avail > 0 && handle->flags & UV_HANDLE_READING) {
+ /* Depending on the type of pipe, read either IPC frames or raw data. */
+ DWORD bytes_read =
+ handle->ipc ? uv__pipe_read_ipc(loop, handle)
+ : uv__pipe_read_data(loop, handle, avail, (DWORD) -1);
+
+ /* If no bytes were read, treat this as an indication that an error
+ * occurred, and break out of the read loop. */
+ if (bytes_read == 0)
break;
- }
- assert(buf.base != NULL);
-
- if (ReadFile(handle->handle,
- buf.base,
- min(buf.len, avail),
- &bytes,
- NULL)) {
- /* Successful read */
- if (handle->ipc) {
- assert(handle->pipe.conn.remaining_ipc_rawdata_bytes >= bytes);
- handle->pipe.conn.remaining_ipc_rawdata_bytes =
- handle->pipe.conn.remaining_ipc_rawdata_bytes - bytes;
- }
- handle->read_cb((uv_stream_t*)handle, bytes, &buf);
- /* Read again only if bytes == buf.len */
- if (bytes <= buf.len) {
- break;
- }
- } else {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
+ /* It is possible that more bytes were read than we thought were
+ * available. To prevent `avail` from underflowing, break out of the loop
+ * if this is the case. */
+ if (bytes_read > avail)
break;
- }
- }
- /* Post another 0-read if still reading and not closing. */
- if ((handle->flags & UV_HANDLE_READING) &&
- !(handle->flags & UV_HANDLE_READ_PENDING)) {
- uv_pipe_queue_read(loop, handle);
+ /* Recompute the number of bytes available. */
+ avail -= bytes_read;
}
}
- DECREASE_PENDING_REQ_COUNT(handle);
+ /* Start another zero-read request if necessary. */
+ if ((handle->flags & UV_HANDLE_READING) &&
+ !(handle->flags & UV_HANDLE_READ_PENDING)) {
+ uv_pipe_queue_read(loop, handle);
+ }
}
@@ -1712,17 +1868,19 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
}
}
- if (req->ipc_header) {
- if (req == &handle->pipe.conn.ipc_header_write_req) {
- req->type = UV_UNKNOWN_REQ;
- } else {
- uv__free(req);
- }
- } else {
- if (req->cb) {
- err = GET_REQ_ERROR(req);
- req->cb(req, uv_translate_sys_error(err));
- }
+ err = GET_REQ_ERROR(req);
+
+ /* If this was a coalesced write, extract pointer to the user_provided
+ * uv_write_t structure so we can pass the expected pointer to the callback,
+ * then free the heap-allocated write req. */
+ if (req->coalesced) {
+ uv__coalesced_write_t* coalesced_write =
+ container_of(req, uv__coalesced_write_t, req);
+ req = coalesced_write->user_req;
+ uv__free(coalesced_write);
+ }
+ if (req->cb) {
+ req->cb(req, uv_translate_sys_error(err));
}
handle->stream.conn.write_reqs_pending--;
@@ -1748,7 +1906,7 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
assert(handle->type == UV_NAMED_PIPE);
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
/* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */
assert(req->pipeHandle == INVALID_HANDLE_VALUE);
DECREASE_PENDING_REQ_COUNT(handle);
@@ -1768,7 +1926,7 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
CloseHandle(req->pipeHandle);
req->pipeHandle = INVALID_HANDLE_VALUE;
}
- if (!(handle->flags & UV__HANDLE_CLOSING)) {
+ if (!(handle->flags & UV_HANDLE_CLOSING)) {
uv_pipe_queue_accept(loop, handle, req, FALSE);
}
}
@@ -1806,19 +1964,19 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (handle->flags & UV_HANDLE_READABLE) {
- /* Initialize and optionally start the eof timer. Only do this if the */
- /* pipe is readable and we haven't seen EOF come in ourselves. */
+ /* Initialize and optionally start the eof timer. Only do this if the pipe
+ * is readable and we haven't seen EOF come in ourselves. */
eof_timer_init(handle);
- /* If reading start the timer right now. */
- /* Otherwise uv_pipe_queue_read will start it. */
+ /* If reading start the timer right now. Otherwise uv_pipe_queue_read will
+ * start it. */
if (handle->flags & UV_HANDLE_READ_PENDING) {
eof_timer_start(handle);
}
} else {
- /* This pipe is not readable. We can just close it to let the other end */
- /* know that we're done writing. */
+ /* This pipe is not readable. We can just close it to let the other end
+ * know that we're done writing. */
close_pipe(handle);
}
@@ -1869,17 +2027,16 @@ static void eof_timer_cb(uv_timer_t* timer) {
assert(pipe->type == UV_NAMED_PIPE);
- /* This should always be true, since we start the timer only */
- /* in uv_pipe_queue_read after successfully calling ReadFile, */
- /* or in uv_process_pipe_shutdown_req if a read is pending, */
- /* and we always immediately stop the timer in */
- /* uv_process_pipe_read_req. */
+ /* This should always be true, since we start the timer only in
+ * uv_pipe_queue_read after successfully calling ReadFile, or in
+ * uv_process_pipe_shutdown_req if a read is pending, and we always
+ * immediately stop the timer in uv_process_pipe_read_req. */
assert(pipe->flags & UV_HANDLE_READ_PENDING);
- /* If there are many packets coming off the iocp then the timer callback */
- /* may be called before the read request is coming off the queue. */
- /* Therefore we check here if the read request has completed but will */
- /* be processed later. */
+ /* If there are many packets coming off the iocp then the timer callback may
+ * be called before the read request is coming off the queue. Therefore we
+ * check here if the read request has completed but will be processed later.
+ */
if ((pipe->flags & UV_HANDLE_READ_PENDING) &&
HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) {
return;
@@ -1888,12 +2045,12 @@ static void eof_timer_cb(uv_timer_t* timer) {
/* Force both ends off the pipe. */
close_pipe(pipe);
- /* Stop reading, so the pending read that is going to fail will */
- /* not be reported to the user. */
+ /* Stop reading, so the pending read that is going to fail will not be
+ * reported to the user. */
uv_read_stop((uv_stream_t*) pipe);
- /* Report the eof and update flags. This will get reported even if the */
- /* user stopped reading in the meantime. TODO: is that okay? */
+ /* Report the eof and update flags. This will get reported even if the user
+ * stopped reading in the meantime. TODO: is that okay? */
uv_pipe_read_eof(loop, pipe, uv_null_buf_);
}
@@ -1980,8 +2137,8 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
if (pipe->ipc) {
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
- pipe->pipe.conn.ipc_pid = uv_os_getppid();
- assert(pipe->pipe.conn.ipc_pid != -1);
+ pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
+ assert(pipe->pipe.conn.ipc_remote_pid != (DWORD) -1);
}
return 0;
}
@@ -2006,7 +2163,15 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
return UV_EINVAL;
}
- uv__pipe_pause_read((uv_pipe_t*)handle); /* cast away const warning */
+ /* NtQueryInformationFile will block if another thread is performing a
+ * blocking operation on the queried handle. If the pipe handle is
+ * synchronous, there may be a worker thread currently calling ReadFile() on
+ * the pipe handle, which could cause a deadlock. To avoid this, interrupt
+ * the read. */
+ if (handle->flags & UV_HANDLE_CONNECTION &&
+ handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
+ uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */
+ }
nt_status = pNtQueryInformationFile(handle->handle,
&io_status,
@@ -2097,7 +2262,6 @@ error:
uv__free(name_info);
cleanup:
- uv__pipe_unpause_read((uv_pipe_t*)handle); /* cast away const warning */
return err;
}
@@ -2105,7 +2269,7 @@ cleanup:
int uv_pipe_pending_count(uv_pipe_t* handle) {
if (!handle->ipc)
return 0;
- return handle->pipe.conn.pending_ipc_info.queue_len;
+ return handle->pipe.conn.ipc_xfer_queue_length;
}
@@ -2138,14 +2302,14 @@ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
if (!handle->ipc)
return UV_UNKNOWN_HANDLE;
- if (handle->pipe.conn.pending_ipc_info.queue_len == 0)
+ if (handle->pipe.conn.ipc_xfer_queue_length == 0)
return UV_UNKNOWN_HANDLE;
else
return UV_TCP;
}
int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
- SID_IDENTIFIER_AUTHORITY sid_world = SECURITY_WORLD_SID_AUTHORITY;
+ SID_IDENTIFIER_AUTHORITY sid_world = { SECURITY_WORLD_SID_AUTHORITY };
PACL old_dacl, new_dacl;
PSECURITY_DESCRIPTOR sd;
EXPLICIT_ACCESS ea;
@@ -2180,7 +2344,7 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
error = GetLastError();
goto clean_sid;
}
-
+
memset(&ea, 0, sizeof(EXPLICIT_ACCESS));
if (mode & UV_READABLE)
ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
diff --git a/Utilities/cmlibuv/src/win/poll.c b/Utilities/cmlibuv/src/win/poll.c
index a648ba7..3c66786 100644
--- a/Utilities/cmlibuv/src/win/poll.c
+++ b/Utilities/cmlibuv/src/win/poll.c
@@ -75,7 +75,7 @@ static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) {
static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
uv_req_t* req;
AFD_POLL_INFO* afd_poll_info;
- DWORD result;
+ int result;
/* Find a yet unsubmitted req to submit. */
if (handle->submitted_events_1 == 0) {
@@ -91,16 +91,16 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
handle->mask_events_1 = handle->events;
handle->mask_events_2 = 0;
} else {
- /* Just wait until there's an unsubmitted req. */
- /* This will happen almost immediately as one of the 2 outstanding */
- /* requests is about to return. When this happens, */
- /* uv__fast_poll_process_poll_req will be called, and the pending */
- /* events, if needed, will be processed in a subsequent request. */
+ /* Just wait until there's an unsubmitted req. This will happen almost
+ * immediately as one of the 2 outstanding requests is about to return.
+ * When this happens, uv__fast_poll_process_poll_req will be called, and
+ * the pending events, if needed, will be processed in a subsequent
+ * request. */
return;
}
- /* Setting Exclusive to TRUE makes the other poll request return if there */
- /* is any. */
+ /* Setting Exclusive to TRUE makes the other poll request return if there is
+ * any. */
afd_poll_info->Exclusive = TRUE;
afd_poll_info->NumberOfHandles = 1;
afd_poll_info->Timeout.QuadPart = INT64_MAX;
@@ -136,7 +136,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
AFD_POLL_INFO afd_poll_info;
- DWORD result;
+ int result;
afd_poll_info.Exclusive = TRUE;
afd_poll_info.NumberOfHandles = 1;
@@ -218,7 +218,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
if ((handle->events & ~(handle->submitted_events_1 |
handle->submitted_events_2)) != 0) {
uv__fast_poll_submit_poll_req(loop, handle);
- } else if ((handle->flags & UV__HANDLE_CLOSING) &&
+ } else if ((handle->flags & UV_HANDLE_CLOSING) &&
handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
uv_want_endgame(loop, (uv_handle_t*) handle);
@@ -228,7 +228,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
assert(handle->type == UV_POLL);
- assert(!(handle->flags & UV__HANDLE_CLOSING));
+ assert(!(handle->flags & UV_HANDLE_CLOSING));
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
handle->events = events;
@@ -257,8 +257,8 @@ static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
uv_want_endgame(loop, (uv_handle_t*) handle);
return 0;
} else {
- /* Cancel outstanding poll requests by executing another, unique poll */
- /* request that forces the outstanding ones to return. */
+ /* Cancel outstanding poll requests by executing another, unique poll
+ * request that forces the outstanding ones to return. */
return uv__fast_poll_cancel_poll_req(loop, handle);
}
}
@@ -316,9 +316,8 @@ static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
return INVALID_SOCKET;
}
- /* If we didn't (try) to create a peer socket yet, try to make one. Don't */
- /* try again if the peer socket creation failed earlier for the same */
- /* protocol. */
+ /* If we didn't (try) to create a peer socket yet, try to make one. Don't try
+ * again if the peer socket creation failed earlier for the same protocol. */
peer_socket = loop->poll_peer_sockets[index];
if (peer_socket == 0) {
peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
@@ -357,8 +356,8 @@ static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
efds.fd_count = 0;
}
- /* Make the select() time out after 3 minutes. If select() hangs because */
- /* the user closed the socket, we will at least not hang indefinitely. */
+ /* Make the select() time out after 3 minutes. If select() hangs because the
+ * user closed the socket, we will at least not hang indefinitely. */
timeout.tv_sec = 3 * 60;
timeout.tv_usec = 0;
@@ -462,7 +461,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
if ((handle->events & ~(handle->submitted_events_1 |
handle->submitted_events_2)) != 0) {
uv__slow_poll_submit_poll_req(loop, handle);
- } else if ((handle->flags & UV__HANDLE_CLOSING) &&
+ } else if ((handle->flags & UV_HANDLE_CLOSING) &&
handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
uv_want_endgame(loop, (uv_handle_t*) handle);
@@ -472,7 +471,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
assert(handle->type == UV_POLL);
- assert(!(handle->flags & UV__HANDLE_CLOSING));
+ assert(!(handle->flags & UV_HANDLE_CLOSING));
assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
handle->events = events;
@@ -522,10 +521,10 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
return uv_translate_sys_error(WSAGetLastError());
- /* Try to obtain a base handle for the socket. This increases this chances */
- /* that we find an AFD handle and are able to use the fast poll mechanism. */
- /* This will always fail on windows XP/2k3, since they don't support the */
- /* SIO_BASE_HANDLE ioctl. */
+/* Try to obtain a base handle for the socket. This increases this chances that
+ * we find an AFD handle and are able to use the fast poll mechanism. This will
+ * always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE
+ * ioctl. */
#ifndef NDEBUG
base_socket = INVALID_SOCKET;
#endif
@@ -557,9 +556,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
return uv_translate_sys_error(WSAGetLastError());
}
- /* Get the peer socket that is needed to enable fast poll. If the returned */
- /* value is NULL, the protocol is not implemented by MSAFD and we'll have */
- /* to use slow mode. */
+ /* Get the peer socket that is needed to enable fast poll. If the returned
+ * value is NULL, the protocol is not implemented by MSAFD and we'll have to
+ * use slow mode. */
peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
if (peer_socket != INVALID_SOCKET) {
@@ -634,7 +633,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
- assert(handle->flags & UV__HANDLE_CLOSING);
+ assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
assert(handle->submitted_events_1 == 0);
diff --git a/Utilities/cmlibuv/src/win/process-stdio.c b/Utilities/cmlibuv/src/win/process-stdio.c
index 032e309..355d618 100644
--- a/Utilities/cmlibuv/src/win/process-stdio.c
+++ b/Utilities/cmlibuv/src/win/process-stdio.c
@@ -103,12 +103,12 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
DWORD client_access = 0;
HANDLE child_pipe = INVALID_HANDLE_VALUE;
int err;
+ int overlap;
if (flags & UV_READABLE_PIPE) {
- /* The server needs inbound access too, otherwise CreateNamedPipe() */
- /* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */
- /* probe the state of the write buffer when we're trying to shutdown */
- /* the pipe. */
+ /* The server needs inbound access too, otherwise CreateNamedPipe() won't
+ * give us the FILE_READ_ATTRIBUTES permission. We need that to probe the
+ * state of the write buffer when we're trying to shutdown the pipe. */
server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
}
@@ -131,12 +131,13 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
+ overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);
child_pipe = CreateFileA(pipe_name,
client_access,
0,
&sa,
OPEN_EXISTING,
- server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0,
+ overlap ? FILE_FLAG_OVERLAPPED : 0,
NULL);
if (child_pipe == INVALID_HANDLE_VALUE) {
err = GetLastError();
@@ -159,8 +160,8 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
}
#endif
- /* Do a blocking ConnectNamedPipe. This should not block because we have */
- /* both ends of the pipe created. */
+ /* Do a blocking ConnectNamedPipe. This should not block because we have both
+ * ends of the pipe created. */
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
if (GetLastError() != ERROR_PIPE_CONNECTED) {
err = GetLastError();
@@ -194,11 +195,11 @@ static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
HANDLE current_process;
- /* _get_osfhandle will sometimes return -2 in case of an error. This seems */
- /* to happen when fd <= 2 and the process' corresponding stdio handle is */
- /* set to NULL. Unfortunately DuplicateHandle will happily duplicate */
- /* (HANDLE) -2, so this situation goes unnoticed until someone tries to */
- /* use the duplicate. Therefore we filter out known-invalid handles here. */
+ /* _get_osfhandle will sometimes return -2 in case of an error. This seems to
+ * happen when fd <= 2 and the process' corresponding stdio handle is set to
+ * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so
+ * this situation goes unnoticed until someone tries to use the duplicate.
+ * Therefore we filter out known-invalid handles here. */
if (handle == INVALID_HANDLE_VALUE ||
handle == NULL ||
handle == (HANDLE) -2) {
@@ -284,8 +285,8 @@ int uv__stdio_create(uv_loop_t* loop,
return ERROR_OUTOFMEMORY;
}
- /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
- /* clean up on failure. */
+ /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean
+ * up on failure. */
CHILD_STDIO_COUNT(buffer) = count;
for (i = 0; i < count; i++) {
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
@@ -303,12 +304,12 @@ int uv__stdio_create(uv_loop_t* loop,
switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
UV_INHERIT_STREAM)) {
case UV_IGNORE:
- /* Starting a process with no stdin/stout/stderr can confuse it. */
- /* So no matter what the user specified, we make sure the first */
- /* three FDs are always open in their typical modes, e.g. stdin */
- /* be readable and stdout/err should be writable. For FDs > 2, don't */
- /* do anything - all handles in the stdio buffer are initialized with */
- /* INVALID_HANDLE_VALUE, which should be okay. */
+ /* Starting a process with no stdin/stout/stderr can confuse it. So no
+ * matter what the user specified, we make sure the first three FDs are
+ * always open in their typical modes, e. g. stdin be readable and
+ * stdout/err should be writable. For FDs > 2, don't do anything - all
+ * handles in the stdio buffer are initialized with.
+ * INVALID_HANDLE_VALUE, which should be okay. */
if (i <= 2) {
DWORD access = (i == 0) ? FILE_GENERIC_READ :
FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
@@ -323,14 +324,14 @@ int uv__stdio_create(uv_loop_t* loop,
break;
case UV_CREATE_PIPE: {
- /* Create a pair of two connected pipe ends; one end is turned into */
- /* an uv_pipe_t for use by the parent. The other one is given to */
- /* the child. */
+ /* Create a pair of two connected pipe ends; one end is turned into an
+ * uv_pipe_t for use by the parent. The other one is given to the
+ * child. */
uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
HANDLE child_pipe = INVALID_HANDLE_VALUE;
- /* Create a new, connected pipe pair. stdio[i].stream should point */
- /* to an uninitialized, but not connected pipe handle. */
+ /* Create a new, connected pipe pair. stdio[i]. stream should point to
+ * an uninitialized, but not connected pipe handle. */
assert(fdopt.data.stream->type == UV_NAMED_PIPE);
assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
@@ -354,8 +355,8 @@ int uv__stdio_create(uv_loop_t* loop,
/* Make an inheritable duplicate of the handle. */
err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle);
if (err) {
- /* If fdopt.data.fd is not valid and fd fd <= 2, then ignore the */
- /* error. */
+ /* If fdopt. data. fd is not valid and fd <= 2, then ignore the
+ * error. */
if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) {
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
@@ -418,8 +419,8 @@ int uv__stdio_create(uv_loop_t* loop,
if (stream_handle == NULL ||
stream_handle == INVALID_HANDLE_VALUE) {
- /* The handle is already closed, or not yet created, or the */
- /* stream type is not supported. */
+ /* The handle is already closed, or not yet created, or the stream
+ * type is not supported. */
err = ERROR_NOT_SUPPORTED;
goto error;
}
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index 25cfe87..24037b3 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -360,8 +360,8 @@ static WCHAR* search_path(const WCHAR *file,
return NULL;
}
- /* Find the start of the filename so we can split the directory from the */
- /* name. */
+ /* Find the start of the filename so we can split the directory from the
+ * name. */
for (file_name_start = (WCHAR*)file + file_len;
file_name_start > file
&& file_name_start[-1] != L'\\'
@@ -556,8 +556,8 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {
arg_count++;
}
- /* Adjust for potential quotes. Also assume the worst-case scenario */
- /* that every character needs escaping, so we need twice as much space. */
+ /* Adjust for potential quotes. Also assume the worst-case scenario that
+ * every character needs escaping, so we need twice as much space. */
dst_len = dst_len * 2 + arg_count * 2;
/* Allocate buffer for the final command line. */
@@ -739,7 +739,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
}
}
*ptr_copy = NULL;
- assert(env_len == ptr - dst_copy);
+ assert(env_len == (size_t) (ptr - dst_copy));
/* sort our (UTF-16) copy */
qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);
@@ -799,7 +799,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
var_size = GetEnvironmentVariableW(required_vars[i].wide,
ptr,
(int) (env_len - (ptr - dst)));
- if (var_size != len-1) { /* race condition? */
+ if (var_size != (DWORD) (len - 1)) { /* TODO: handle race condition? */
uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
}
}
@@ -815,7 +815,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
}
/* Terminate with an extra NULL. */
- assert(env_len == (ptr - dst));
+ assert(env_len == (size_t) (ptr - dst));
*ptr = L'\0';
uv__free(dst_copy);
@@ -831,8 +831,13 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
*/
static WCHAR* find_path(WCHAR *env) {
for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
- if (wcsncmp(env, L"PATH=", 5) == 0)
+ if ((env[0] == L'P' || env[0] == L'p') &&
+ (env[1] == L'A' || env[1] == L'a') &&
+ (env[2] == L'T' || env[2] == L't') &&
+ (env[3] == L'H' || env[3] == L'h') &&
+ (env[4] == L'=')) {
return &env[5];
+ }
}
return NULL;
@@ -865,9 +870,9 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
assert(handle->exit_cb_pending);
handle->exit_cb_pending = 0;
- /* If we're closing, don't call the exit callback. Just schedule a close */
- /* callback now. */
- if (handle->flags & UV__HANDLE_CLOSING) {
+ /* If we're closing, don't call the exit callback. Just schedule a close
+ * callback now. */
+ if (handle->flags & UV_HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*) handle);
return;
}
@@ -878,14 +883,14 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
handle->wait_handle = INVALID_HANDLE_VALUE;
}
- /* Set the handle to inactive: no callbacks will be made after the exit */
- /* callback.*/
+ /* Set the handle to inactive: no callbacks will be made after the exit
+ * callback. */
uv__handle_stop(handle);
if (GetExitCodeProcess(handle->process_handle, &status)) {
exit_code = status;
} else {
- /* Unable to to obtain the exit code. This should never happen. */
+ /* Unable to obtain the exit code. This should never happen. */
exit_code = uv_translate_sys_error(GetLastError());
}
@@ -900,8 +905,8 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
uv__handle_closing(handle);
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
- /* This blocks until either the wait was cancelled, or the callback has */
- /* completed. */
+ /* This blocks until either the wait was cancelled, or the callback has
+ * completed. */
BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
if (!r) {
/* This should never happen, and if it happens, we can't recover... */
@@ -919,7 +924,7 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
assert(!handle->exit_cb_pending);
- assert(handle->flags & UV__HANDLE_CLOSING);
+ assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
/* Clean-up the process handle. */
@@ -965,6 +970,8 @@ int uv_spawn(uv_loop_t* loop,
UV_PROCESS_SETGID |
UV_PROCESS_SETUID |
UV_PROCESS_WINDOWS_HIDE |
+ UV_PROCESS_WINDOWS_HIDE_CONSOLE |
+ UV_PROCESS_WINDOWS_HIDE_GUI |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
err = uv_utf8_to_utf16_alloc(options->file, &application);
@@ -1066,7 +1073,8 @@ int uv_spawn(uv_loop_t* loop,
process_flags = CREATE_UNICODE_ENVIRONMENT;
- if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
+ if ((options->flags & UV_PROCESS_WINDOWS_HIDE_CONSOLE) ||
+ (options->flags & UV_PROCESS_WINDOWS_HIDE)) {
/* Avoid creating console window if stdio is not inherited. */
for (i = 0; i < options->stdio_count; i++) {
if (options->stdio[i].flags & UV_INHERIT_FD)
@@ -1074,7 +1082,9 @@ int uv_spawn(uv_loop_t* loop,
if (i == options->stdio_count - 1)
process_flags |= CREATE_NO_WINDOW;
}
-
+ }
+ if ((options->flags & UV_PROCESS_WINDOWS_HIDE_GUI) ||
+ (options->flags & UV_PROCESS_WINDOWS_HIDE)) {
/* Use SW_HIDE to avoid any potential process window. */
startup.wShowWindow = SW_HIDE;
} else {
@@ -1160,14 +1170,13 @@ int uv_spawn(uv_loop_t* loop,
}
}
- /* Spawn succeeded */
- /* Beyond this point, failure is reported asynchronously. */
+ /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
process->process_handle = info.hProcess;
process->pid = info.dwProcessId;
- /* If the process isn't spawned as detached, assign to the global job */
- /* object so windows will kill it when the parent process dies. */
+ /* If the process isn't spawned as detached, assign to the global job object
+ * so windows will kill it when the parent process dies. */
if (!(options->flags & UV_PROCESS_DETACHED)) {
uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
@@ -1194,7 +1203,8 @@ int uv_spawn(uv_loop_t* loop,
if (fdopt->flags & UV_CREATE_PIPE &&
fdopt->data.stream->type == UV_NAMED_PIPE &&
((uv_pipe_t*) fdopt->data.stream)->ipc) {
- ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId;
+ ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid =
+ info.dwProcessId;
}
}
@@ -1210,8 +1220,8 @@ int uv_spawn(uv_loop_t* loop,
assert(!err);
- /* Make the handle active. It will remain active until the exit callback */
- /* is made or the handle is closed, whichever happens first. */
+ /* Make the handle active. It will remain active until the exit callback is
+ * made or the handle is closed, whichever happens first. */
uv__handle_start(process);
/* Cleanup, whether we succeeded or failed. */
@@ -1242,16 +1252,16 @@ static int uv__kill(HANDLE process_handle, int signum) {
case SIGTERM:
case SIGKILL:
case SIGINT: {
- /* Unconditionally terminate the process. On Windows, killed processes */
- /* normally return 1. */
+ /* Unconditionally terminate the process. On Windows, killed processes
+ * normally return 1. */
DWORD status;
int err;
if (TerminateProcess(process_handle, 1))
return 0;
- /* If the process already exited before TerminateProcess was called, */
- /* TerminateProcess will fail with ERROR_ACCESS_DENIED. */
+ /* If the process already exited before TerminateProcess was called,.
+ * TerminateProcess will fail with ERROR_ACCESS_DENIED. */
err = GetLastError();
if (err == ERROR_ACCESS_DENIED &&
GetExitCodeProcess(process_handle, &status) &&
diff --git a/Utilities/cmlibuv/src/win/req.c b/Utilities/cmlibuv/src/win/req.c
deleted file mode 100644
index 111cc5e..0000000
--- a/Utilities/cmlibuv/src/win/req.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c
index a174da1..276dc60 100644
--- a/Utilities/cmlibuv/src/win/signal.c
+++ b/Utilities/cmlibuv/src/win/signal.c
@@ -47,13 +47,13 @@ void uv_signals_init(void) {
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
- /* Compare signums first so all watchers with the same signnum end up */
- /* adjacent. */
+ /* Compare signums first so all watchers with the same signnum end up
+ * adjacent. */
if (w1->signum < w2->signum) return -1;
if (w1->signum > w2->signum) return 1;
- /* Sort by loop pointer, so we can easily look up the first item after */
- /* { .signum = x, .loop = NULL } */
+ /* Sort by loop pointer, so we can easily look up the first item after
+ * { .signum = x, .loop = NULL }. */
if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1;
if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1;
@@ -90,7 +90,7 @@ int uv__signal_dispatch(int signum) {
unsigned long previous = InterlockedExchange(
(volatile LONG*) &handle->pending_signum, signum);
- if (handle->flags & UV__SIGNAL_ONE_SHOT_DISPATCHED)
+ if (handle->flags & UV_SIGNAL_ONE_SHOT_DISPATCHED)
continue;
if (!previous) {
@@ -98,8 +98,8 @@ int uv__signal_dispatch(int signum) {
}
dispatched = 1;
- if (handle->flags & UV__SIGNAL_ONE_SHOT)
- handle->flags |= UV__SIGNAL_ONE_SHOT_DISPATCHED;
+ if (handle->flags & UV_SIGNAL_ONE_SHOT)
+ handle->flags |= UV_SIGNAL_ONE_SHOT_DISPATCHED;
}
LeaveCriticalSection(&uv__signal_lock);
@@ -118,10 +118,10 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
case CTRL_CLOSE_EVENT:
if (uv__signal_dispatch(SIGHUP)) {
- /* Windows will terminate the process after the control handler */
- /* returns. After that it will just terminate our process. Therefore */
- /* block the signal handler so the main loop has some time to pick */
- /* up the signal and do something for a few seconds. */
+ /* Windows will terminate the process after the control handler
+ * returns. After that it will just terminate our process. Therefore
+ * block the signal handler so the main loop has some time to pick up
+ * the signal and do something for a few seconds. */
Sleep(INFINITE);
return TRUE;
}
@@ -129,8 +129,8 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
- /* These signals are only sent to services. Services have their own */
- /* notification mechanism, so there's no point in handling these. */
+ /* These signals are only sent to services. Services have their own
+ * notification mechanism, so there's no point in handling these. */
default:
/* We don't handle these. */
@@ -190,13 +190,13 @@ int uv__signal_start(uv_signal_t* handle,
int signum,
int oneshot) {
/* Test for invalid signal values. */
- if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG))
+ if (signum <= 0 || signum >= NSIG)
return UV_EINVAL;
- /* Short circuit: if the signal watcher is already watching {signum} don't */
- /* go through the process of deregistering and registering the handler. */
- /* Additionally, this avoids pending signals getting lost in the (small) */
- /* time frame that handle->signum == 0. */
+ /* Short circuit: if the signal watcher is already watching {signum} don't go
+ * through the process of deregistering and registering the handler.
+ * Additionally, this avoids pending signals getting lost in the (small) time
+ * frame that handle->signum == 0. */
if (signum == handle->signum) {
handle->signal_cb = signal_cb;
return 0;
@@ -213,7 +213,7 @@ int uv__signal_start(uv_signal_t* handle,
handle->signum = signum;
if (oneshot)
- handle->flags |= UV__SIGNAL_ONE_SHOT;
+ handle->flags |= UV_SIGNAL_ONE_SHOT;
RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
@@ -237,16 +237,16 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
(volatile LONG*) &handle->pending_signum, 0);
assert(dispatched_signum != 0);
- /* Check if the pending signal equals the signum that we are watching for. */
- /* These can get out of sync when the handler is stopped and restarted */
- /* while the signal_req is pending. */
+ /* Check if the pending signal equals the signum that we are watching for.
+ * These can get out of sync when the handler is stopped and restarted while
+ * the signal_req is pending. */
if (dispatched_signum == handle->signum)
handle->signal_cb(handle, dispatched_signum);
- if (handle->flags & UV__SIGNAL_ONE_SHOT)
+ if (handle->flags & UV_SIGNAL_ONE_SHOT)
uv_signal_stop(handle);
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
/* When it is closing, it must be stopped at this point. */
assert(handle->signum == 0);
uv_want_endgame(loop, (uv_handle_t*) handle);
@@ -265,7 +265,7 @@ void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) {
void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) {
- assert(handle->flags & UV__HANDLE_CLOSING);
+ assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
assert(handle->signum == 0);
diff --git a/Utilities/cmlibuv/src/win/stream.c b/Utilities/cmlibuv/src/win/stream.c
index 13cbfdc..7656627 100644
--- a/Utilities/cmlibuv/src/win/stream.c
+++ b/Utilities/cmlibuv/src/win/stream.c
@@ -105,12 +105,10 @@ int uv_read_stop(uv_stream_t* handle) {
err = 0;
if (handle->type == UV_TTY) {
err = uv_tty_read_stop((uv_tty_t*) handle);
+ } else if (handle->type == UV_NAMED_PIPE) {
+ uv__pipe_read_stop((uv_pipe_t*) handle);
} else {
- if (handle->type == UV_NAMED_PIPE) {
- uv__pipe_stop_read((uv_pipe_t*) handle);
- } else {
- handle->flags &= ~UV_HANDLE_READING;
- }
+ handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(handle->loop, handle);
}
@@ -136,7 +134,8 @@ int uv_write(uv_write_t* req,
err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);
break;
case UV_NAMED_PIPE:
- err = uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, nbufs, cb);
+ err = uv__pipe_write(
+ loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb);
break;
case UV_TTY:
err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);
@@ -158,25 +157,18 @@ int uv_write2(uv_write_t* req,
uv_loop_t* loop = handle->loop;
int err;
- if (!(handle->flags & UV_HANDLE_WRITABLE)) {
- return UV_EPIPE;
+ if (send_handle == NULL) {
+ return uv_write(req, handle, bufs, nbufs, cb);
}
- err = ERROR_INVALID_PARAMETER;
- switch (handle->type) {
- case UV_NAMED_PIPE:
- err = uv_pipe_write2(loop,
- req,
- (uv_pipe_t*) handle,
- bufs,
- nbufs,
- send_handle,
- cb);
- break;
- default:
- assert(0);
+ if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) {
+ return UV_EINVAL;
+ } else if (!(handle->flags & UV_HANDLE_WRITABLE)) {
+ return UV_EPIPE;
}
+ err = uv__pipe_write(
+ loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb);
return uv_translate_sys_error(err);
}
@@ -184,7 +176,7 @@ int uv_write2(uv_write_t* req,
int uv_try_write(uv_stream_t* stream,
const uv_buf_t bufs[],
unsigned int nbufs) {
- if (stream->flags & UV__HANDLE_CLOSING)
+ if (stream->flags & UV_HANDLE_CLOSING)
return UV_EBADF;
if (!(stream->flags & UV_HANDLE_WRITABLE))
return UV_EPIPE;
diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c
index 39c1ff0..3ce5548 100644
--- a/Utilities/cmlibuv/src/win/tcp.c
+++ b/Utilities/cmlibuv/src/win/tcp.c
@@ -99,8 +99,8 @@ static int uv_tcp_set_socket(uv_loop_t* loop,
if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0))
return GetLastError();
- /* Associate it with the I/O completion port. */
- /* Use uv_handle_t pointer as completion key. */
+ /* Associate it with the I/O completion port. Use uv_handle_t pointer as
+ * completion key. */
if (CreateIoCompletionPort((HANDLE)socket,
loop->iocp,
(ULONG_PTR)socket,
@@ -118,15 +118,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop,
non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;
}
- if (pSetFileCompletionNotificationModes &&
- !(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
- if (pSetFileCompletionNotificationModes((HANDLE) socket,
- FILE_SKIP_SET_EVENT_ON_HANDLE |
- FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
- handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
- } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
+ if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
+ UCHAR sfcnm_flags =
+ FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
+ if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags))
return GetLastError();
- }
+ handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
}
if (handle->flags & UV_HANDLE_TCP_NODELAY) {
@@ -220,7 +217,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
err = 0;
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
err = ERROR_OPERATION_ABORTED;
} else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) {
err = WSAGetLastError();
@@ -236,7 +233,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
return;
}
- if (handle->flags & UV__HANDLE_CLOSING &&
+ if (handle->flags & UV_HANDLE_CLOSING &&
handle->reqs_pending == 0) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
@@ -326,9 +323,9 @@ static int uv_tcp_try_bind(uv_tcp_t* handle,
on = (flags & UV_TCP_IPV6ONLY) != 0;
- /* TODO: how to handle errors? This may fail if there is no ipv4 stack */
- /* available, or when run on XP/2003 which have no support for dualstack */
- /* sockets. For now we're silently ignoring the error. */
+ /* TODO: how to handle errors? This may fail if there is no ipv4 stack
+ * available, or when run on XP/2003 which have no support for dualstack
+ * sockets. For now we're silently ignoring the error. */
setsockopt(handle->socket,
IPPROTO_IPV6,
IPV6_V6ONLY,
@@ -626,9 +623,9 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
uv_tcp_queue_accept(handle, req);
}
- /* Initialize other unused requests too, because uv_tcp_endgame */
- /* doesn't know how how many requests were initialized, so it will */
- /* try to clean up {uv_simultaneous_server_accepts} requests. */
+ /* Initialize other unused requests too, because uv_tcp_endgame doesn't
+ * know how many requests were initialized, so it will try to clean up
+ * {uv_simultaneous_server_accepts} requests. */
for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
req = &handle->tcp.serv.accept_reqs[i];
UV_REQ_INIT(req, UV_ACCEPT);
@@ -683,7 +680,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
req->next_pending = NULL;
req->accept_socket = INVALID_SOCKET;
- if (!(server->flags & UV__HANDLE_CLOSING)) {
+ if (!(server->flags & UV_HANDLE_CLOSING)) {
/* Check if we're in a middle of changing the number of pending accepts. */
if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {
uv_tcp_queue_accept(server, req);
@@ -721,8 +718,8 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
handle->alloc_cb = alloc_cb;
INCREASE_ACTIVE_COUNT(loop, handle);
- /* If reading was stopped and then started again, there could still be a */
- /* read request pending. */
+ /* If reading was stopped and then started again, there could still be a read
+ * request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING)) {
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
!handle->read_req.event_handle) {
@@ -948,6 +945,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
uv_req_t* req) {
DWORD bytes, flags, err;
uv_buf_t buf;
+ int count;
assert(handle->type == UV_TCP);
@@ -965,8 +963,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
err = GET_REQ_SOCK_ERROR(req);
if (err == WSAECONNABORTED) {
- /*
- * Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
+ /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
*/
err = WSAECONNRESET;
}
@@ -1003,7 +1000,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
}
/* Do nonblocking reads until the buffer is empty */
- while (handle->flags & UV_HANDLE_READING) {
+ count = 32;
+ while ((handle->flags & UV_HANDLE_READING) && (count-- > 0)) {
buf = uv_buf_init(NULL, 0);
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
if (buf.base == NULL || buf.len == 0) {
@@ -1046,8 +1044,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
DECREASE_ACTIVE_COUNT(loop, handle);
if (err == WSAECONNABORTED) {
- /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */
- /* Unix. */
+ /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with
+ * Unix. */
err = WSAECONNRESET;
}
@@ -1119,10 +1117,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
assert(handle->type == UV_TCP);
- /* If handle->accepted_socket is not a valid socket, then */
- /* uv_queue_accept must have failed. This is a serious error. We stop */
- /* accepting connections and report this error to the connection */
- /* callback. */
+ /* If handle->accepted_socket is not a valid socket, then uv_queue_accept
+ * must have failed. This is a serious error. We stop accepting connections
+ * and report this error to the connection callback. */
if (req->accept_socket == INVALID_SOCKET) {
if (handle->flags & UV_HANDLE_LISTENING) {
handle->flags &= ~UV_HANDLE_LISTENING;
@@ -1147,9 +1144,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);
}
} else {
- /* Error related to accepted socket is ignored because the server */
- /* socket may still be healthy. If the server socket is broken */
- /* uv_queue_accept will detect it. */
+ /* Error related to accepted socket is ignored because the server socket
+ * may still be healthy. If the server socket is broken uv_queue_accept
+ * will detect it. */
closesocket(req->accept_socket);
req->accept_socket = INVALID_SOCKET;
if (handle->flags & UV_HANDLE_LISTENING) {
@@ -1171,7 +1168,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
err = 0;
if (REQ_SUCCESS(req)) {
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
/* use UV_ECANCELED for consistency with Unix */
err = ERROR_OPERATION_ABORTED;
} else if (setsockopt(handle->socket,
@@ -1194,40 +1191,76 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
}
-int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
- int tcp_connection) {
+int uv__tcp_xfer_export(uv_tcp_t* handle,
+ int target_pid,
+ uv__ipc_socket_xfer_type_t* xfer_type,
+ uv__ipc_socket_xfer_info_t* xfer_info) {
+ if (handle->flags & UV_HANDLE_CONNECTION) {
+ *xfer_type = UV__IPC_SOCKET_XFER_TCP_CONNECTION;
+ } else {
+ *xfer_type = UV__IPC_SOCKET_XFER_TCP_SERVER;
+ /* We're about to share the socket with another process. Because this is a
+ * listening socket, we assume that the other process will be accepting
+ * connections on it. Thus, before sharing the socket with another process,
+ * we call listen here in the parent process. */
+ if (!(handle->flags & UV_HANDLE_LISTENING)) {
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ return ERROR_NOT_SUPPORTED;
+ }
+ if (handle->delayed_error == 0 &&
+ listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
+ handle->delayed_error = WSAGetLastError();
+ }
+ }
+ }
+
+ if (WSADuplicateSocketW(handle->socket, target_pid, &xfer_info->socket_info))
+ return WSAGetLastError();
+ xfer_info->delayed_error = handle->delayed_error;
+
+ /* Mark the local copy of the handle as 'shared' so we behave in a way that's
+ * friendly to the process(es) that we share the socket with. */
+ handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
+
+ return 0;
+}
+
+
+int uv__tcp_xfer_import(uv_tcp_t* tcp,
+ uv__ipc_socket_xfer_type_t xfer_type,
+ uv__ipc_socket_xfer_info_t* xfer_info) {
int err;
- SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO,
- FROM_PROTOCOL_INFO,
- FROM_PROTOCOL_INFO,
- &socket_info_ex->socket_info,
- 0,
- WSA_FLAG_OVERLAPPED);
+ SOCKET socket;
+
+ assert(xfer_type == UV__IPC_SOCKET_XFER_TCP_SERVER ||
+ xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION);
+
+ socket = WSASocketW(FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO,
+ &xfer_info->socket_info,
+ 0,
+ WSA_FLAG_OVERLAPPED);
if (socket == INVALID_SOCKET) {
return WSAGetLastError();
}
- err = uv_tcp_set_socket(tcp->loop,
- tcp,
- socket,
- socket_info_ex->socket_info.iAddressFamily,
- 1);
+ err = uv_tcp_set_socket(
+ tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1);
if (err) {
closesocket(socket);
return err;
}
- if (tcp_connection) {
+ tcp->delayed_error = xfer_info->delayed_error;
+ tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET;
+
+ if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) {
uv_connection_init((uv_stream_t*)tcp);
tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
}
- tcp->flags |= UV_HANDLE_BOUND;
- tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
-
- tcp->delayed_error = socket_info_ex->delayed_error;
-
tcp->loop->active_tcp_streams++;
return 0;
}
@@ -1273,39 +1306,6 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
}
-int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
- LPWSAPROTOCOL_INFOW protocol_info) {
- if (!(handle->flags & UV_HANDLE_CONNECTION)) {
- /*
- * We're about to share the socket with another process. Because
- * this is a listening socket, we assume that the other process will
- * be accepting connections on it. So, before sharing the socket
- * with another process, we call listen here in the parent process.
- */
-
- if (!(handle->flags & UV_HANDLE_LISTENING)) {
- if (!(handle->flags & UV_HANDLE_BOUND)) {
- return ERROR_INVALID_PARAMETER;
- }
-
- if (!(handle->delayed_error)) {
- if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
- handle->delayed_error = WSAGetLastError();
- }
- }
- }
- }
-
- if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) {
- return WSAGetLastError();
- }
-
- handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
-
- return 0;
-}
-
-
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
if (handle->flags & UV_HANDLE_CONNECTION) {
return UV_EINVAL;
@@ -1346,8 +1346,8 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
uv_tcp_non_ifs_lsp_ipv4;
- /* If there are non-ifs LSPs then try to obtain a base handle for the */
- /* socket. This will always fail on Windows XP/3k. */
+ /* If there are non-ifs LSPs then try to obtain a base handle for the socket.
+ * This will always fail on Windows XP/3k. */
if (non_ifs_lsp) {
DWORD bytes;
if (WSAIoctl(socket,
@@ -1379,38 +1379,37 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
int close_socket = 1;
if (tcp->flags & UV_HANDLE_READ_PENDING) {
- /* In order for winsock to do a graceful close there must not be any */
- /* any pending reads, or the socket must be shut down for writing */
+ /* In order for winsock to do a graceful close there must not be any any
+ * pending reads, or the socket must be shut down for writing */
if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) {
/* Just do shutdown on non-shared sockets, which ensures graceful close. */
shutdown(tcp->socket, SD_SEND);
} else if (uv_tcp_try_cancel_io(tcp) == 0) {
- /* In case of a shared socket, we try to cancel all outstanding I/O, */
- /* If that works, don't close the socket yet - wait for the read req to */
- /* return and close the socket in uv_tcp_endgame. */
+ /* In case of a shared socket, we try to cancel all outstanding I/O,. If
+ * that works, don't close the socket yet - wait for the read req to
+ * return and close the socket in uv_tcp_endgame. */
close_socket = 0;
} else {
- /* When cancelling isn't possible - which could happen when an LSP is */
- /* present on an old Windows version, we will have to close the socket */
- /* with a read pending. That is not nice because trailing sent bytes */
- /* may not make it to the other side. */
+ /* When cancelling isn't possible - which could happen when an LSP is
+ * present on an old Windows version, we will have to close the socket
+ * with a read pending. That is not nice because trailing sent bytes may
+ * not make it to the other side. */
}
} else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
tcp->tcp.serv.accept_reqs != NULL) {
- /* Under normal circumstances closesocket() will ensure that all pending */
- /* accept reqs are canceled. However, when the socket is shared the */
- /* presence of another reference to the socket in another process will */
- /* keep the accept reqs going, so we have to ensure that these are */
- /* canceled. */
+ /* Under normal circumstances closesocket() will ensure that all pending
+ * accept reqs are canceled. However, when the socket is shared the
+ * presence of another reference to the socket in another process will keep
+ * the accept reqs going, so we have to ensure that these are canceled. */
if (uv_tcp_try_cancel_io(tcp) != 0) {
- /* When cancellation is not possible, there is another option: we can */
- /* close the incoming sockets, which will also cancel the accept */
- /* operations. However this is not cool because we might inadvertently */
- /* close a socket that just accepted a new connection, which will */
- /* cause the connection to be aborted. */
+ /* When cancellation is not possible, there is another option: we can
+ * close the incoming sockets, which will also cancel the accept
+ * operations. However this is not cool because we might inadvertently
+ * close a socket that just accepted a new connection, which will cause
+ * the connection to be aborted. */
unsigned int i;
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];
diff --git a/Utilities/cmlibuv/src/win/thread.c b/Utilities/cmlibuv/src/win/thread.c
index 9eaad77..fd4b7c9 100644
--- a/Utilities/cmlibuv/src/win/thread.c
+++ b/Utilities/cmlibuv/src/win/thread.c
@@ -23,29 +23,15 @@
#include <limits.h>
#include <stdlib.h>
+#if defined(__MINGW64_VERSION_MAJOR)
+/* MemoryBarrier expands to __mm_mfence in some cases (x86+sse2), which may
+ * require this header in some versions of mingw64. */
+#include <intrin.h>
+#endif
+
#include "uv.h"
#include "internal.h"
-
-#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL)
-
-static int uv_cond_fallback_init(uv_cond_t* cond);
-static void uv_cond_fallback_destroy(uv_cond_t* cond);
-static void uv_cond_fallback_signal(uv_cond_t* cond);
-static void uv_cond_fallback_broadcast(uv_cond_t* cond);
-static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex);
-static int uv_cond_fallback_timedwait(uv_cond_t* cond,
- uv_mutex_t* mutex, uint64_t timeout);
-
-static int uv_cond_condvar_init(uv_cond_t* cond);
-static void uv_cond_condvar_destroy(uv_cond_t* cond);
-static void uv_cond_condvar_signal(uv_cond_t* cond);
-static void uv_cond_condvar_broadcast(uv_cond_t* cond);
-static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex);
-static int uv_cond_condvar_timedwait(uv_cond_t* cond,
- uv_mutex_t* mutex, uint64_t timeout);
-
-
static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
DWORD result;
HANDLE existing_event, created_event;
@@ -69,8 +55,8 @@ static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
guard->ran = 1;
} else {
- /* We lost the race. Destroy the event we created and wait for the */
- /* existing one to become signaled. */
+ /* We lost the race. Destroy the event we created and wait for the existing
+ * one to become signaled. */
CloseHandle(created_event);
result = WaitForSingleObject(existing_event, INFINITE);
assert(result == WAIT_OBJECT_0);
@@ -138,7 +124,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
ctx->arg = arg;
/* Create the thread in suspended state so we have a chance to pass
- * its own creation handle to it */
+ * its own creation handle to it */
thread = (HANDLE) _beginthreadex(NULL,
0,
uv__thread_start,
@@ -377,220 +363,35 @@ int uv_sem_trywait(uv_sem_t* sem) {
}
-/* This condition variable implementation is based on the SetEvent solution
- * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
- * We could not use the SignalObjectAndWait solution (section 3.4) because
- * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
- * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
- */
-
-static int uv_cond_fallback_init(uv_cond_t* cond) {
- int err;
-
- /* Initialize the count to 0. */
- cond->fallback.waiters_count = 0;
-
- InitializeCriticalSection(&cond->fallback.waiters_count_lock);
-
- /* Create an auto-reset event. */
- cond->fallback.signal_event = CreateEvent(NULL, /* no security */
- FALSE, /* auto-reset event */
- FALSE, /* non-signaled initially */
- NULL); /* unnamed */
- if (!cond->fallback.signal_event) {
- err = GetLastError();
- goto error2;
- }
-
- /* Create a manual-reset event. */
- cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */
- TRUE, /* manual-reset */
- FALSE, /* non-signaled */
- NULL); /* unnamed */
- if (!cond->fallback.broadcast_event) {
- err = GetLastError();
- goto error;
- }
-
- return 0;
-
-error:
- CloseHandle(cond->fallback.signal_event);
-error2:
- DeleteCriticalSection(&cond->fallback.waiters_count_lock);
- return uv_translate_sys_error(err);
-}
-
-
-static int uv_cond_condvar_init(uv_cond_t* cond) {
- pInitializeConditionVariable(&cond->cond_var);
- return 0;
-}
-
-
int uv_cond_init(uv_cond_t* cond) {
- uv__once_init();
-
- if (HAVE_CONDVAR_API())
- return uv_cond_condvar_init(cond);
- else
- return uv_cond_fallback_init(cond);
-}
-
-
-static void uv_cond_fallback_destroy(uv_cond_t* cond) {
- if (!CloseHandle(cond->fallback.broadcast_event))
- abort();
- if (!CloseHandle(cond->fallback.signal_event))
- abort();
- DeleteCriticalSection(&cond->fallback.waiters_count_lock);
-}
-
-
-static void uv_cond_condvar_destroy(uv_cond_t* cond) {
- /* nothing to do */
+ InitializeConditionVariable(&cond->cond_var);
+ return 0;
}
void uv_cond_destroy(uv_cond_t* cond) {
- if (HAVE_CONDVAR_API())
- uv_cond_condvar_destroy(cond);
- else
- uv_cond_fallback_destroy(cond);
-}
-
-
-static void uv_cond_fallback_signal(uv_cond_t* cond) {
- int have_waiters;
-
- /* Avoid race conditions. */
- EnterCriticalSection(&cond->fallback.waiters_count_lock);
- have_waiters = cond->fallback.waiters_count > 0;
- LeaveCriticalSection(&cond->fallback.waiters_count_lock);
-
- if (have_waiters)
- SetEvent(cond->fallback.signal_event);
-}
-
-
-static void uv_cond_condvar_signal(uv_cond_t* cond) {
- pWakeConditionVariable(&cond->cond_var);
+ /* nothing to do */
+ (void) &cond;
}
void uv_cond_signal(uv_cond_t* cond) {
- if (HAVE_CONDVAR_API())
- uv_cond_condvar_signal(cond);
- else
- uv_cond_fallback_signal(cond);
-}
-
-
-static void uv_cond_fallback_broadcast(uv_cond_t* cond) {
- int have_waiters;
-
- /* Avoid race conditions. */
- EnterCriticalSection(&cond->fallback.waiters_count_lock);
- have_waiters = cond->fallback.waiters_count > 0;
- LeaveCriticalSection(&cond->fallback.waiters_count_lock);
-
- if (have_waiters)
- SetEvent(cond->fallback.broadcast_event);
-}
-
-
-static void uv_cond_condvar_broadcast(uv_cond_t* cond) {
- pWakeAllConditionVariable(&cond->cond_var);
+ WakeConditionVariable(&cond->cond_var);
}
void uv_cond_broadcast(uv_cond_t* cond) {
- if (HAVE_CONDVAR_API())
- uv_cond_condvar_broadcast(cond);
- else
- uv_cond_fallback_broadcast(cond);
-}
-
-
-static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex,
- DWORD dwMilliseconds) {
- DWORD result;
- int last_waiter;
- HANDLE handles[2] = {
- cond->fallback.signal_event,
- cond->fallback.broadcast_event
- };
-
- /* Avoid race conditions. */
- EnterCriticalSection(&cond->fallback.waiters_count_lock);
- cond->fallback.waiters_count++;
- LeaveCriticalSection(&cond->fallback.waiters_count_lock);
-
- /* It's ok to release the <mutex> here since Win32 manual-reset events */
- /* maintain state when used with <SetEvent>. This avoids the "lost wakeup" */
- /* bug. */
- uv_mutex_unlock(mutex);
-
- /* Wait for either event to become signaled due to <uv_cond_signal> being */
- /* called or <uv_cond_broadcast> being called. */
- result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);
-
- EnterCriticalSection(&cond->fallback.waiters_count_lock);
- cond->fallback.waiters_count--;
- last_waiter = result == WAIT_OBJECT_0 + 1
- && cond->fallback.waiters_count == 0;
- LeaveCriticalSection(&cond->fallback.waiters_count_lock);
-
- /* Some thread called <pthread_cond_broadcast>. */
- if (last_waiter) {
- /* We're the last waiter to be notified or to stop waiting, so reset the */
- /* the manual-reset event. */
- ResetEvent(cond->fallback.broadcast_event);
- }
-
- /* Reacquire the <mutex>. */
- uv_mutex_lock(mutex);
-
- if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1)
- return 0;
-
- if (result == WAIT_TIMEOUT)
- return UV_ETIMEDOUT;
-
- abort();
- return -1; /* Satisfy the compiler. */
-}
-
-
-static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
- if (uv_cond_wait_helper(cond, mutex, INFINITE))
- abort();
-}
-
-
-static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
- if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
- abort();
+ WakeAllConditionVariable(&cond->cond_var);
}
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
- if (HAVE_CONDVAR_API())
- uv_cond_condvar_wait(cond, mutex);
- else
- uv_cond_fallback_wait(cond, mutex);
-}
-
-
-static int uv_cond_fallback_timedwait(uv_cond_t* cond,
- uv_mutex_t* mutex, uint64_t timeout) {
- return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6));
+ if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
+ abort();
}
-
-static int uv_cond_condvar_timedwait(uv_cond_t* cond,
- uv_mutex_t* mutex, uint64_t timeout) {
- if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
+int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
+ if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
return 0;
if (GetLastError() != ERROR_TIMEOUT)
abort();
@@ -598,15 +399,6 @@ static int uv_cond_condvar_timedwait(uv_cond_t* cond,
}
-int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
- uint64_t timeout) {
- if (HAVE_CONDVAR_API())
- return uv_cond_condvar_timedwait(cond, mutex, timeout);
- else
- return uv_cond_fallback_timedwait(cond, mutex, timeout);
-}
-
-
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
int err;
diff --git a/Utilities/cmlibuv/src/win/timer.c b/Utilities/cmlibuv/src/win/timer.c
deleted file mode 100644
index 7e006fe..0000000
--- a/Utilities/cmlibuv/src/win/timer.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <limits.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "tree.h"
-#include "handle-inl.h"
-
-
-/* The number of milliseconds in one second. */
-#define UV__MILLISEC 1000
-
-
-void uv_update_time(uv_loop_t* loop) {
- uint64_t new_time = uv__hrtime(UV__MILLISEC);
- assert(new_time >= loop->time);
- loop->time = new_time;
-}
-
-
-static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) {
- if (a->due < b->due)
- return -1;
- if (a->due > b->due)
- return 1;
- /*
- * compare start_id when both has the same due. start_id is
- * allocated with loop->timer_counter in uv_timer_start().
- */
- if (a->start_id < b->start_id)
- return -1;
- if (a->start_id > b->start_id)
- return 1;
- return 0;
-}
-
-
-RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare)
-
-
-int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
- uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER);
- handle->timer_cb = NULL;
- handle->repeat = 0;
-
- return 0;
-}
-
-
-void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) {
- if (handle->flags & UV__HANDLE_CLOSING) {
- assert(!(handle->flags & UV_HANDLE_CLOSED));
- uv__handle_close(handle);
- }
-}
-
-
-static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) {
- uint64_t clamped_timeout;
-
- clamped_timeout = loop_time + timeout;
- if (clamped_timeout < timeout)
- clamped_timeout = (uint64_t) -1;
-
- return clamped_timeout;
-}
-
-
-int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout,
- uint64_t repeat) {
- uv_loop_t* loop = handle->loop;
- uv_timer_t* old;
-
- if (timer_cb == NULL)
- return UV_EINVAL;
-
- if (uv__is_active(handle))
- uv_timer_stop(handle);
-
- handle->timer_cb = timer_cb;
- handle->due = get_clamped_due_time(loop->time, timeout);
- handle->repeat = repeat;
- uv__handle_start(handle);
-
- /* start_id is the second index to be compared in uv__timer_cmp() */
- handle->start_id = handle->loop->timer_counter++;
-
- old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle);
- assert(old == NULL);
-
- return 0;
-}
-
-
-int uv_timer_stop(uv_timer_t* handle) {
- uv_loop_t* loop = handle->loop;
-
- if (!uv__is_active(handle))
- return 0;
-
- RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);
- uv__handle_stop(handle);
-
- return 0;
-}
-
-
-int uv_timer_again(uv_timer_t* handle) {
- /* If timer_cb is NULL that means that the timer was never started. */
- if (!handle->timer_cb) {
- return UV_EINVAL;
- }
-
- if (handle->repeat) {
- uv_timer_stop(handle);
- uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);
- }
-
- return 0;
-}
-
-
-void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {
- assert(handle->type == UV_TIMER);
- handle->repeat = repeat;
-}
-
-
-uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
- assert(handle->type == UV_TIMER);
- return handle->repeat;
-}
-
-
-DWORD uv__next_timeout(const uv_loop_t* loop) {
- uv_timer_t* timer;
- int64_t delta;
-
- /* Check if there are any running timers
- * Need to cast away const first, since RB_MIN doesn't know what we are
- * going to do with this return value, it can't be marked const
- */
- timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers);
- if (timer) {
- delta = timer->due - loop->time;
- if (delta >= UINT_MAX - 1) {
- /* A timeout value of UINT_MAX means infinite, so that's no good. */
- return UINT_MAX - 1;
- } else if (delta < 0) {
- /* Negative timeout values are not allowed */
- return 0;
- } else {
- return (DWORD)delta;
- }
- } else {
- /* No timers */
- return INFINITE;
- }
-}
-
-
-void uv_process_timers(uv_loop_t* loop) {
- uv_timer_t* timer;
-
- /* Call timer callbacks */
- for (timer = RB_MIN(uv_timer_tree_s, &loop->timers);
- timer != NULL && timer->due <= loop->time;
- timer = RB_MIN(uv_timer_tree_s, &loop->timers)) {
-
- uv_timer_stop(timer);
- uv_timer_again(timer);
- timer->timer_cb((uv_timer_t*) timer);
- }
-}
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index ecf7bc9..f38e9a8 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -25,7 +25,7 @@
#include <stdlib.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "stdint-msvc2008.h"
+# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
@@ -164,7 +164,7 @@ void uv_console_init(void) {
OPEN_EXISTING,
0,
0);
- if (uv__tty_console_handle != NULL) {
+ if (uv__tty_console_handle != INVALID_HANDLE_VALUE) {
QueueUserWorkItem(uv__tty_console_resize_message_loop_thread,
NULL,
WT_EXECUTELONGFUNCTION);
@@ -172,9 +172,12 @@ void uv_console_init(void) {
}
-int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
+int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
+ BOOL readable;
+ DWORD NumberOfEvents;
HANDLE handle;
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
+ (void)unused;
uv__once_init();
handle = (HANDLE) uv__get_osfhandle(fd);
@@ -199,14 +202,15 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
fd = -1;
}
+ readable = GetNumberOfConsoleInputEvents(handle, &NumberOfEvents);
if (!readable) {
/* Obtain the screen buffer info with the output handle. */
if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) {
return uv_translate_sys_error(GetLastError());
}
- /* Obtain the the tty_output_lock because the virtual window state is */
- /* shared between all uv_tty_t handles. */
+ /* Obtain the tty_output_lock because the virtual window state is shared
+ * between all uv_tty_t handles. */
uv_sem_wait(&uv_tty_output_lock);
if (uv__vterm_state == UV_UNCHECKED)
@@ -356,6 +360,8 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
}
} else {
was_reading = 0;
+ alloc_cb = NULL;
+ read_cb = NULL;
}
uv_sem_wait(&uv_tty_output_lock);
@@ -382,12 +388,6 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
}
-int uv_is_tty(uv_file file) {
- DWORD result;
- return GetConsoleMode((HANDLE) _get_osfhandle(file), &result) != 0;
-}
-
-
int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
CONSOLE_SCREEN_BUFFER_INFO info;
@@ -484,8 +484,8 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
bytes = MAX_INPUT_BUFFER_LENGTH;
}
- /* At last, unicode! */
- /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */
+ /* At last, unicode! One utf-16 codeunit never takes more than 3 utf-8
+ * codeunits to encode. */
chars = bytes / 3;
status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS);
@@ -620,10 +620,10 @@ static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl,
}
switch (code) {
- /* These mappings are the same as Cygwin's. Unmodified and alt-modified */
- /* keypad keys comply with linux console, modifiers comply with xterm */
- /* modifier usage. F1..f12 and shift-f1..f10 comply with linux console, */
- /* f6..f12 with and without modifiers comply with rxvt. */
+ /* These mappings are the same as Cygwin's. Unmodified and alt-modified
+ * keypad keys comply with linux console, modifiers comply with xterm
+ * modifier usage. F1. f12 and shift-f1. f10 comply with linux console, f6.
+ * f12 with and without modifiers comply with rxvt. */
VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~")
VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~")
VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B")
@@ -706,8 +706,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
goto out;
}
- /* Windows sends a lot of events that we're not interested in, so buf */
- /* will be allocated on demand, when there's actually something to emit. */
+ /* Windows sends a lot of events that we're not interested in, so buf will be
+ * allocated on demand, when there's actually something to emit. */
buf = uv_null_buf_;
buf_used = 0;
@@ -733,16 +733,17 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
continue;
}
- /* Ignore keyup events, unless the left alt key was held and a valid */
- /* unicode character was emitted. */
- if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) ||
- KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) {
+ /* Ignore keyup events, unless the left alt key was held and a valid
+ * unicode character was emitted. */
+ if (!KEV.bKeyDown &&
+ KEV.wVirtualKeyCode != VK_MENU &&
+ KEV.uChar.UnicodeChar != 0) {
continue;
}
- /* Ignore keypresses to numpad number keys if the left alt is held */
- /* because the user is composing a character, or windows simulating */
- /* this. */
+ /* Ignore keypresses to numpad number keys if the left alt is held
+ * because the user is composing a character, or windows simulating this.
+ */
if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) &&
!(KEV.dwControlKeyState & ENHANCED_KEY) &&
(KEV.wVirtualKeyCode == VK_INSERT ||
@@ -779,8 +780,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
continue;
}
- /* Prefix with \u033 if alt was held, but alt was not used as part */
- /* a compose sequence. */
+ /* Prefix with \u033 if alt was held, but alt was not used as part a
+ * compose sequence. */
if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
&& !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED |
RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) {
@@ -793,8 +794,9 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
if (KEV.uChar.UnicodeChar >= 0xDC00 &&
KEV.uChar.UnicodeChar < 0xE000) {
/* UTF-16 surrogate pair */
- WCHAR utf16_buffer[2] = { handle->tty.rd.last_utf16_high_surrogate,
- KEV.uChar.UnicodeChar};
+ WCHAR utf16_buffer[2];
+ utf16_buffer[0] = handle->tty.rd.last_utf16_high_surrogate;
+ utf16_buffer[1] = KEV.uChar.UnicodeChar;
char_len = WideCharToMultiByte(CP_UTF8,
0,
utf16_buffer,
@@ -818,8 +820,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
/* Whatever happened, the last character wasn't a high surrogate. */
handle->tty.rd.last_utf16_high_surrogate = 0;
- /* If the utf16 character(s) couldn't be converted something must */
- /* be wrong. */
+ /* If the utf16 character(s) couldn't be converted something must be
+ * wrong. */
if (!char_len) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
@@ -943,21 +945,15 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
handle->read_cb((uv_stream_t*) handle,
uv_translate_sys_error(GET_REQ_ERROR(req)),
&buf);
- } else {
- /* The read was cancelled, or whatever we don't care */
- handle->read_cb((uv_stream_t*) handle, 0, &buf);
}
-
} else {
- if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) {
- /* Read successful */
- /* TODO: read unicode, convert to utf-8 */
+ if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING) &&
+ req->u.io.overlapped.InternalHigh != 0) {
+ /* Read successful. TODO: read unicode, convert to utf-8 */
DWORD bytes = req->u.io.overlapped.InternalHigh;
handle->read_cb((uv_stream_t*) handle, bytes, &buf);
- } else {
- handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING;
- handle->read_cb((uv_stream_t*) handle, 0, &buf);
}
+ handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING;
}
/* Wait for more input events. */
@@ -975,9 +971,9 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
assert(handle->type == UV_TTY);
assert(handle->flags & UV_HANDLE_TTY_READABLE);
- /* If the read_line_buffer member is zero, it must have been an raw read. */
- /* Otherwise it was a line-buffered read. */
- /* FIXME: This is quite obscure. Use a flag or something. */
+ /* If the read_line_buffer member is zero, it must have been an raw read.
+ * Otherwise it was a line-buffered read. FIXME: This is quite obscure. Use a
+ * flag or something. */
if (handle->tty.rd.read_line_buffer.len == 0) {
uv_process_tty_read_raw_req(loop, handle, req);
} else {
@@ -999,14 +995,14 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
handle->read_cb = read_cb;
handle->alloc_cb = alloc_cb;
- /* If reading was stopped and then started again, there could still be a */
- /* read request pending. */
+ /* If reading was stopped and then started again, there could still be a read
+ * request pending. */
if (handle->flags & UV_HANDLE_READ_PENDING) {
return 0;
}
- /* Maybe the user stopped reading half-way while processing key events. */
- /* Short-circuit if this could be the case. */
+ /* Maybe the user stopped reading half-way while processing key events.
+ * Short-circuit if this could be the case. */
if (handle->tty.rd.last_key_len > 0) {
SET_REQ_SUCCESS(&handle->read_req);
uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
@@ -1033,9 +1029,10 @@ int uv_tty_read_stop(uv_tty_t* handle) {
return 0;
if (handle->flags & UV_HANDLE_TTY_RAW) {
- /* Cancel raw read */
- /* Write some bullshit event to force the console wait to return. */
+ /* Cancel raw read. Write some bullshit event to force the console wait to
+ * return. */
memset(&record, 0, sizeof record);
+ record.EventType = FOCUS_EVENT;
if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {
return GetLastError();
}
@@ -1116,8 +1113,8 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
uv_tty_virtual_offset = info->dwCursorPosition.Y;
} else if (uv_tty_virtual_offset < info->dwCursorPosition.Y -
uv_tty_virtual_height + 1) {
- /* If suddenly find the cursor outside of the virtual window, it must */
- /* have somehow scrolled. Update the virtual window offset. */
+ /* If suddenly find the cursor outside of the virtual window, it must have
+ * somehow scrolled. Update the virtual window offset. */
uv_tty_virtual_offset = info->dwCursorPosition.Y -
uv_tty_virtual_height + 1;
}
@@ -1304,8 +1301,8 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
x2 = 0;
x2r = 1;
} else {
- /* Clear to end of row. We pretend the console is 65536 characters wide, */
- /* uv_tty_make_real_coord will clip it to the actual console width. */
+ /* Clear to end of row. We pretend the console is 65536 characters wide,
+ * uv_tty_make_real_coord will clip it to the actual console width. */
x2 = 0xffff;
x2r = 0;
}
@@ -1613,8 +1610,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
DWORD* error) {
- /* We can only write 8k characters at a time. Windows can't handle */
- /* much more characters in a single console write anyway. */
+ /* We can only write 8k characters at a time. Windows can't handle much more
+ * characters in a single console write anyway. */
WCHAR utf16_buf[MAX_CONSOLE_CHAR];
WCHAR* utf16_buffer;
DWORD utf16_buf_used = 0;
@@ -1650,9 +1647,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
unsigned char previous_eol = handle->tty.wr.previous_eol;
unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state;
- /* Store the error here. If we encounter an error, stop trying to do i/o */
- /* but keep parsing the buffer so we leave the parser in a consistent */
- /* state. */
+ /* Store the error here. If we encounter an error, stop trying to do i/o but
+ * keep parsing the buffer so we leave the parser in a consistent state. */
*error = ERROR_SUCCESS;
utf16_buffer = utf16_buf;
@@ -1700,9 +1696,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
for (j = 0; j < buf.len; j++) {
unsigned char c = buf.base[j];
- /* Run the character through the utf8 decoder We happily accept non */
- /* shortest form encodings and invalid code points - there's no real */
- /* harm that can be done. */
+ /* Run the character through the utf8 decoder We happily accept non
+ * shortest form encodings and invalid code points - there's no real harm
+ * that can be done. */
if (utf8_bytes_left == 0) {
/* Read utf-8 start byte */
DWORD first_zero_bit;
@@ -1742,8 +1738,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
/* Start byte where continuation was expected. */
utf8_bytes_left = 0;
utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
- /* Patch buf offset so this character will be parsed again as a */
- /* start byte. */
+ /* Patch buf offset so this character will be parsed again as a start
+ * byte. */
j--;
}
@@ -1776,8 +1772,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
case '_':
case 'P':
case ']':
- /* Not supported, but we'll have to parse until we see a stop */
- /* code, e.g. ESC \ or BEL. */
+ /* Not supported, but we'll have to parse until we see a stop code,
+ * e. g. ESC \ or BEL. */
ansi_parser_state = ANSI_ST_CONTROL;
continue;
@@ -1859,8 +1855,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
continue;
} else {
- /* If ANSI_IN_ARG is not set, add another argument and */
- /* default it to 0. */
+ /* If ANSI_IN_ARG is not set, add another argument and default it
+ * to 0. */
+
/* Check for too many arguments */
if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {
ansi_parser_state |= ANSI_IGNORE;
@@ -1874,9 +1871,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
} else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) &&
handle->tty.wr.ansi_csi_argc == 0) {
- /* Ignores '?' if it is the first character after CSI[ */
- /* This is an extension character from the VT100 codeset */
- /* that is supported and used by most ANSI terminals today. */
+ /* Ignores '?' if it is the first character after CSI[. This is an
+ * extension character from the VT100 codeset that is supported and
+ * used by most ANSI terminals today. */
continue;
} else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' &&
@@ -2006,8 +2003,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
continue;
} else {
- /* We don't support commands that use private mode characters or */
- /* intermediaries. Ignore the rest of the sequence. */
+ /* We don't support commands that use private mode characters or
+ * intermediaries. Ignore the rest of the sequence. */
ansi_parser_state |= ANSI_IGNORE;
continue;
}
@@ -2020,8 +2017,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
}
} else if (ansi_parser_state & ANSI_ST_CONTROL) {
- /* Unsupported control code */
- /* Ignore everything until we see BEL or ESC \ */
+ /* Unsupported control code.
+ * Ignore everything until we see `BEL` or `ESC \`. */
if (ansi_parser_state & ANSI_IN_STRING) {
if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) {
if (utf8_codepoint == '"') {
@@ -2055,9 +2052,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
abort();
}
- /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */
- /* windows console doesn't really support UTF-16, so just emit the */
- /* replacement character. */
+ /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the windows
+ * console doesn't really support UTF-16, so just emit the replacement
+ * character. */
if (utf8_codepoint > 0xffff) {
utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
}
@@ -2071,10 +2068,10 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
utf16_buf[utf16_buf_used++] = L'\r';
utf16_buf[utf16_buf_used++] = L'\n';
} else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) {
- /* \n was followed by \r; do not print the \r, since */
- /* the source was either \r\n\r (so the second \r is */
- /* redundant) or was \n\r (so the \n was processed */
- /* by the last case and an \r automatically inserted). */
+ /* \n was followed by \r; do not print the \r, since the source was
+ * either \r\n\r (so the second \r is redundant) or was \n\r (so the
+ * \n was processed by the last case and an \r automatically
+ * inserted). */
} else {
/* \r without \n; print \r as-is. */
ENSURE_BUFFER_SPACE(1);
@@ -2182,14 +2179,14 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
void uv_tty_close(uv_tty_t* handle) {
assert(handle->u.fd == -1 || handle->u.fd > 2);
+ if (handle->flags & UV_HANDLE_READING)
+ uv_tty_read_stop(handle);
+
if (handle->u.fd == -1)
CloseHandle(handle->handle);
else
close(handle->u.fd);
- if (handle->flags & UV_HANDLE_READING)
- uv_tty_read_stop(handle);
-
handle->u.fd = -1;
handle->handle = INVALID_HANDLE_VALUE;
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
@@ -2209,7 +2206,7 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
/* TTY shutdown is really just a no-op */
if (handle->stream.conn.shutdown_req->cb) {
- if (handle->flags & UV__HANDLE_CLOSING) {
+ if (handle->flags & UV_HANDLE_CLOSING) {
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED);
} else {
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0);
@@ -2222,10 +2219,10 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
return;
}
- if (handle->flags & UV__HANDLE_CLOSING &&
+ if (handle->flags & UV_HANDLE_CLOSING &&
handle->reqs_pending == 0) {
- /* The wait handle used for raw reading should be unregistered when the */
- /* wait callback runs. */
+ /* The wait handle used for raw reading should be unregistered when the
+ * wait callback runs. */
assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
handle->tty.rd.read_raw_wait == NULL);
diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c
index cd1d0e0..37df849 100644
--- a/Utilities/cmlibuv/src/win/udp.c
+++ b/Utilities/cmlibuv/src/win/udp.c
@@ -74,8 +74,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
return GetLastError();
}
- /* Associate it with the I/O completion port. */
- /* Use uv_handle_t pointer as completion key. */
+ /* Associate it with the I/O completion port. Use uv_handle_t pointer as
+ * completion key. */
if (CreateIoCompletionPort((HANDLE)socket,
loop->iocp,
(ULONG_PTR)socket,
@@ -83,31 +83,28 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
return GetLastError();
}
- if (pSetFileCompletionNotificationModes) {
- /* All known Windows that support SetFileCompletionNotificationModes */
- /* have a bug that makes it impossible to use this function in */
- /* conjunction with datagram sockets. We can work around that but only */
- /* if the user is using the default UDP driver (AFD) and has no other */
- /* LSPs stacked on top. Here we check whether that is the case. */
- opt_len = (int) sizeof info;
- if (getsockopt(socket,
- SOL_SOCKET,
- SO_PROTOCOL_INFOW,
- (char*) &info,
- &opt_len) == SOCKET_ERROR) {
- return GetLastError();
- }
+ /* All known Windows that support SetFileCompletionNotificationModes have a
+ * bug that makes it impossible to use this function in conjunction with
+ * datagram sockets. We can work around that but only if the user is using
+ * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here
+ * we check whether that is the case. */
+ opt_len = (int) sizeof info;
+ if (getsockopt(
+ socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) ==
+ SOCKET_ERROR) {
+ return GetLastError();
+ }
- if (info.ProtocolChain.ChainLen == 1) {
- if (pSetFileCompletionNotificationModes((HANDLE)socket,
- FILE_SKIP_SET_EVENT_ON_HANDLE |
- FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
- handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
- handle->func_wsarecv = uv_wsarecv_workaround;
- handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
- } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
- return GetLastError();
- }
+ if (info.ProtocolChain.ChainLen == 1) {
+ if (SetFileCompletionNotificationModes(
+ (HANDLE) socket,
+ FILE_SKIP_SET_EVENT_ON_HANDLE |
+ FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
+ handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
+ handle->func_wsarecv = uv_wsarecv_workaround;
+ handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
+ } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
+ return GetLastError();
}
}
@@ -191,7 +188,7 @@ void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
- if (handle->flags & UV__HANDLE_CLOSING &&
+ if (handle->flags & UV_HANDLE_CLOSING &&
handle->reqs_pending == 0) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
uv__handle_close(handle);
@@ -245,12 +242,12 @@ static int uv_udp_maybe_bind(uv_udp_t* handle,
handle->flags |= UV_HANDLE_IPV6;
if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
- /* On windows IPV6ONLY is on by default. */
- /* If the user doesn't specify it libuv turns it off. */
+ /* On windows IPV6ONLY is on by default. If the user doesn't specify it
+ * libuv turns it off. */
- /* TODO: how to handle errors? This may fail if there is no ipv4 stack */
- /* available, or when run on XP/2003 which have no support for dualstack */
- /* sockets. For now we're silently ignoring the error. */
+ /* TODO: how to handle errors? This may fail if there is no ipv4 stack
+ * available, or when run on XP/2003 which have no support for dualstack
+ * sockets. For now we're silently ignoring the error. */
setsockopt(handle->socket,
IPPROTO_IPV6,
IPV6_V6ONLY,
@@ -369,7 +366,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
int err;
if (handle->flags & UV_HANDLE_READING) {
- return WSAEALREADY;
+ return UV_EALREADY;
}
err = uv_udp_maybe_bind(handle,
@@ -377,7 +374,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
sizeof(uv_addr_ip4_any_),
0);
if (err)
- return err;
+ return uv_translate_sys_error(err);
handle->flags |= UV_HANDLE_READING;
INCREASE_ACTIVE_COUNT(loop, handle);
@@ -386,8 +383,8 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
handle->recv_cb = recv_cb;
handle->alloc_cb = alloc_cb;
- /* If reading was stopped and then started again, there could still be a */
- /* recv request pending. */
+ /* If reading was stopped and then started again, there could still be a recv
+ * request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING))
uv_udp_queue_recv(loop, handle);
@@ -467,19 +464,19 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
if (!REQ_SUCCESS(req)) {
DWORD err = GET_REQ_SOCK_ERROR(req);
if (err == WSAEMSGSIZE) {
- /* Not a real error, it just indicates that the received packet */
- /* was bigger than the receive buffer. */
+ /* Not a real error, it just indicates that the received packet was
+ * bigger than the receive buffer. */
} else if (err == WSAECONNRESET || err == WSAENETRESET) {
- /* A previous sendto operation failed; ignore this error. If */
- /* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */
- /* MSG_PEEK flag to clear out the error queue. For nonzero reads, */
- /* immediately queue a new receive. */
+ /* A previous sendto operation failed; ignore this error. If zero-reading
+ * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to
+ * clear out the error queue. For nonzero reads, immediately queue a new
+ * receive. */
if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
goto done;
}
} else {
- /* A real error occurred. Report the error to the user only if we're */
- /* currently reading. */
+ /* A real error occurred. Report the error to the user only if we're
+ * currently reading. */
if (handle->flags & UV_HANDLE_READING) {
uv_udp_recv_stop(handle);
buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
@@ -503,8 +500,8 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
struct sockaddr_storage from;
int from_len;
- /* Do a nonblocking receive */
- /* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
+ /* Do a nonblocking receive.
+ * TODO: try to read multiple datagrams at once. FIONREAD maybe? */
buf = uv_buf_init(NULL, 0);
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
if (buf.base == NULL || buf.len == 0) {
@@ -741,7 +738,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
return UV_EINVAL;
}
- if (!(handle->flags & UV_HANDLE_BOUND))
+ if (handle->socket == INVALID_SOCKET)
return UV_EBADF;
if (addr_st.ss_family == AF_INET) {
@@ -772,7 +769,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
BOOL optval = (BOOL) value;
- if (!(handle->flags & UV_HANDLE_BOUND))
+ if (handle->socket == INVALID_SOCKET)
return UV_EBADF;
if (setsockopt(handle->socket,
@@ -818,7 +815,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
return UV_EINVAL; \
} \
\
- if (!(handle->flags & UV_HANDLE_BOUND)) \
+ if (handle->socket == INVALID_SOCKET) \
return UV_EBADF; \
\
if (!(handle->flags & UV_HANDLE_IPV6)) { \
diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c
index 49b5bc7..9237891 100644
--- a/Utilities/cmlibuv/src/win/util.c
+++ b/Utilities/cmlibuv/src/win/util.c
@@ -74,10 +74,6 @@
static char *process_title;
static CRITICAL_SECTION process_title_lock;
-/* Cached copy of the process id, written once. */
-static DWORD current_pid = 0;
-
-
/* Interval (in seconds) of the high-resolution clock. */
static double hrtime_interval_ = 0;
@@ -149,8 +145,8 @@ int uv_exepath(char* buffer, size_t* size_ptr) {
uv__free(utf16_buffer);
- /* utf8_len *does* include the terminating null at this point, but the */
- /* returned size shouldn't. */
+ /* utf8_len *does* include the terminating null at this point, but the
+ * returned size shouldn't. */
*size_ptr = utf8_len - 1;
return 0;
@@ -173,16 +169,16 @@ int uv_cwd(char* buffer, size_t* size) {
if (utf16_len == 0) {
return uv_translate_sys_error(GetLastError());
} else if (utf16_len > MAX_PATH) {
- /* This should be impossible; however the CRT has a code path to deal */
- /* with this scenario, so I added a check anyway. */
+ /* This should be impossible; however the CRT has a code path to deal with
+ * this scenario, so I added a check anyway. */
return UV_EIO;
}
/* utf16_len contains the length, *not* including the terminating null. */
utf16_buffer[utf16_len] = L'\0';
- /* The returned directory should not have a trailing slash, unless it */
- /* points at a drive root, like c:\. Remove it if needed.*/
+ /* The returned directory should not have a trailing slash, unless it points
+ * at a drive root, like c:\. Remove it if needed. */
if (utf16_buffer[utf16_len - 1] == L'\\' &&
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
utf16_len--;
@@ -239,9 +235,9 @@ int uv_chdir(const char* dir) {
utf16_buffer,
MAX_PATH) == 0) {
DWORD error = GetLastError();
- /* The maximum length of the current working directory is 260 chars, */
- /* including terminating null. If it doesn't fit, the path name must be */
- /* too long. */
+ /* The maximum length of the current working directory is 260 chars,
+ * including terminating null. If it doesn't fit, the path name must be too
+ * long. */
if (error == ERROR_INSUFFICIENT_BUFFER) {
return UV_ENAMETOOLONG;
} else {
@@ -253,9 +249,9 @@ int uv_chdir(const char* dir) {
return uv_translate_sys_error(GetLastError());
}
- /* Windows stores the drive-local path in an "hidden" environment variable, */
- /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */
- /* update this, so we'll have to do it. */
+ /* Windows stores the drive-local path in an "hidden" environment variable,
+ * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update
+ * this, so we'll have to do it. */
utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
if (utf16_len == 0) {
return uv_translate_sys_error(GetLastError());
@@ -263,8 +259,8 @@ int uv_chdir(const char* dir) {
return UV_EIO;
}
- /* The returned directory should not have a trailing slash, unless it */
- /* points at a drive root, like c:\. Remove it if needed. */
+ /* The returned directory should not have a trailing slash, unless it points
+ * at a drive root, like c:\. Remove it if needed. */
if (utf16_buffer[utf16_len - 1] == L'\\' &&
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
utf16_len--;
@@ -272,8 +268,8 @@ int uv_chdir(const char* dir) {
}
if (utf16_len < 2 || utf16_buffer[1] != L':') {
- /* Doesn't look like a drive letter could be there - probably an UNC */
- /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */
+ /* Doesn't look like a drive letter could be there - probably an UNC path.
+ * TODO: Need to handle win32 namespaces like \\?\C:\ ? */
drive_letter = 0;
} else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
drive_letter = utf16_buffer[0];
@@ -359,14 +355,6 @@ uv_pid_t uv_os_getppid(void) {
}
-int uv_current_pid(void) {
- if (current_pid == 0) {
- current_pid = GetCurrentProcessId();
- }
- return current_pid;
-}
-
-
char** uv_setup_args(int argc, char** argv) {
return argv;
}
@@ -828,6 +816,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
int is_vista_or_greater;
ULONG flags;
+ *addresses_ptr = NULL;
+ *count_ptr = 0;
+
is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0);
if (is_vista_or_greater) {
flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
@@ -842,17 +833,17 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
}
- /* Fetch the size of the adapters reported by windows, and then get the */
- /* list itself. */
+ /* Fetch the size of the adapters reported by windows, and then get the list
+ * itself. */
win_address_buf_size = 0;
win_address_buf = NULL;
for (;;) {
ULONG r;
- /* If win_address_buf is 0, then GetAdaptersAddresses will fail with */
- /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */
- /* win_address_buf_size. */
+ /* If win_address_buf is 0, then GetAdaptersAddresses will fail with.
+ * ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in
+ * win_address_buf_size. */
r = GetAdaptersAddresses(AF_UNSPEC,
flags,
NULL,
@@ -866,8 +857,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
switch (r) {
case ERROR_BUFFER_OVERFLOW:
- /* This happens when win_address_buf is NULL or too small to hold */
- /* all adapters. */
+ /* This happens when win_address_buf is NULL or too small to hold all
+ * adapters. */
win_address_buf = uv__malloc(win_address_buf_size);
if (win_address_buf == NULL)
return UV_ENOMEM;
@@ -901,15 +892,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
return UV_ENOBUFS;
default:
- /* Other (unspecified) errors can happen, but we don't have any */
- /* special meaning for them. */
+ /* Other (unspecified) errors can happen, but we don't have any special
+ * meaning for them. */
assert(r != ERROR_SUCCESS);
return uv_translate_sys_error(r);
}
}
- /* Count the number of enabled interfaces and compute how much space is */
- /* needed to store their info. */
+ /* Count the number of enabled interfaces and compute how much space is
+ * needed to store their info. */
count = 0;
uv_address_buf_size = 0;
@@ -919,9 +910,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
int name_size;
- /* Interfaces that are not 'up' should not be reported. Also skip */
- /* interfaces that have no associated unicast address, as to avoid */
- /* allocating space for the name for this interface. */
+ /* Interfaces that are not 'up' should not be reported. Also skip
+ * interfaces that have no associated unicast address, as to avoid
+ * allocating space for the name for this interface. */
if (adapter->OperStatus != IfOperStatusUp ||
adapter->FirstUnicastAddress == NULL)
continue;
@@ -941,8 +932,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
}
uv_address_buf_size += name_size;
- /* Count the number of addresses associated with this interface, and */
- /* compute the size. */
+ /* Count the number of addresses associated with this interface, and
+ * compute the size. */
for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
adapter->FirstUnicastAddress;
unicast_address != NULL;
@@ -959,8 +950,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
return UV_ENOMEM;
}
- /* Compute the start of the uv_interface_address_t array, and the place in */
- /* the buffer where the interface names will be stored. */
+ /* Compute the start of the uv_interface_address_t array, and the place in
+ * the buffer where the interface names will be stored. */
uv_address = uv_address_buf;
name_buf = (char*) (uv_address_buf + count);
@@ -1199,8 +1190,8 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
return UV_EIO;
}
- /* The returned directory should not have a trailing slash, unless it */
- /* points at a drive root, like c:\. Remove it if needed.*/
+ /* The returned directory should not have a trailing slash, unless it points
+ * at a drive root, like c:\. Remove it if needed. */
if (path[len - 1] == L'\\' &&
!(len == 3 && path[1] == L':')) {
len--;
@@ -1542,3 +1533,214 @@ int uv_os_gethostname(char* buffer, size_t* size) {
*size = len;
return 0;
}
+
+
+static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {
+ int r;
+
+ if (pid == 0)
+ *handle = GetCurrentProcess();
+ else
+ *handle = OpenProcess(access, FALSE, pid);
+
+ if (*handle == NULL) {
+ r = GetLastError();
+
+ if (r == ERROR_INVALID_PARAMETER)
+ return UV_ESRCH;
+ else
+ return uv_translate_sys_error(r);
+ }
+
+ return 0;
+}
+
+
+int uv_os_getpriority(uv_pid_t pid, int* priority) {
+ HANDLE handle;
+ int r;
+
+ if (priority == NULL)
+ return UV_EINVAL;
+
+ r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
+
+ if (r != 0)
+ return r;
+
+ r = GetPriorityClass(handle);
+
+ if (r == 0) {
+ r = uv_translate_sys_error(GetLastError());
+ } else {
+ /* Map Windows priority classes to Unix nice values. */
+ if (r == REALTIME_PRIORITY_CLASS)
+ *priority = UV_PRIORITY_HIGHEST;
+ else if (r == HIGH_PRIORITY_CLASS)
+ *priority = UV_PRIORITY_HIGH;
+ else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
+ *priority = UV_PRIORITY_ABOVE_NORMAL;
+ else if (r == NORMAL_PRIORITY_CLASS)
+ *priority = UV_PRIORITY_NORMAL;
+ else if (r == BELOW_NORMAL_PRIORITY_CLASS)
+ *priority = UV_PRIORITY_BELOW_NORMAL;
+ else /* IDLE_PRIORITY_CLASS */
+ *priority = UV_PRIORITY_LOW;
+
+ r = 0;
+ }
+
+ CloseHandle(handle);
+ return r;
+}
+
+
+int uv_os_setpriority(uv_pid_t pid, int priority) {
+ HANDLE handle;
+ int priority_class;
+ int r;
+
+ /* Map Unix nice values to Windows priority classes. */
+ if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
+ return UV_EINVAL;
+ else if (priority < UV_PRIORITY_HIGH)
+ priority_class = REALTIME_PRIORITY_CLASS;
+ else if (priority < UV_PRIORITY_ABOVE_NORMAL)
+ priority_class = HIGH_PRIORITY_CLASS;
+ else if (priority < UV_PRIORITY_NORMAL)
+ priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
+ else if (priority < UV_PRIORITY_BELOW_NORMAL)
+ priority_class = NORMAL_PRIORITY_CLASS;
+ else if (priority < UV_PRIORITY_LOW)
+ priority_class = BELOW_NORMAL_PRIORITY_CLASS;
+ else
+ priority_class = IDLE_PRIORITY_CLASS;
+
+ r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
+
+ if (r != 0)
+ return r;
+
+ if (SetPriorityClass(handle, priority_class) == 0)
+ r = uv_translate_sys_error(GetLastError());
+
+ CloseHandle(handle);
+ return r;
+}
+
+
+int uv_os_uname(uv_utsname_t* buffer) {
+ /* Implementation loosely based on
+ https://github.com/gagern/gnulib/blob/master/lib/uname.c */
+ OSVERSIONINFOW os_info;
+ SYSTEM_INFO system_info;
+ int processor_level;
+ int r;
+
+ if (buffer == NULL)
+ return UV_EINVAL;
+
+ uv__once_init();
+ os_info.dwOSVersionInfoSize = sizeof(os_info);
+ os_info.szCSDVersion[0] = L'\0';
+
+ /* Try calling RtlGetVersion(), and fall back to the deprecated GetVersionEx()
+ if RtlGetVersion() is not available. */
+ if (pRtlGetVersion) {
+ pRtlGetVersion(&os_info);
+ } else {
+ /* Silence GetVersionEx() deprecation warning. */
+ #pragma warning(suppress : 4996)
+ if (GetVersionExW(&os_info) == 0) {
+ r = uv_translate_sys_error(GetLastError());
+ goto error;
+ }
+ }
+
+ /* Populate the version field. */
+ if (WideCharToMultiByte(CP_UTF8,
+ 0,
+ os_info.szCSDVersion,
+ -1,
+ buffer->version,
+ sizeof(buffer->version),
+ NULL,
+ NULL) == 0) {
+ r = uv_translate_sys_error(GetLastError());
+ goto error;
+ }
+
+ /* Populate the sysname field. */
+#ifdef __MINGW32__
+ r = snprintf(buffer->sysname,
+ sizeof(buffer->sysname),
+ "MINGW32_NT-%u.%u",
+ (unsigned int) os_info.dwMajorVersion,
+ (unsigned int) os_info.dwMinorVersion);
+ assert(r < sizeof(buffer->sysname));
+#else
+ uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname));
+#endif
+
+ /* Populate the release field. */
+ r = snprintf(buffer->release,
+ sizeof(buffer->release),
+ "%d.%d.%d",
+ (unsigned int) os_info.dwMajorVersion,
+ (unsigned int) os_info.dwMinorVersion,
+ (unsigned int) os_info.dwBuildNumber);
+ assert(r < sizeof(buffer->release));
+
+ /* Populate the machine field. */
+ GetSystemInfo(&system_info);
+
+ switch (system_info.wProcessorArchitecture) {
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ uv__strscpy(buffer->machine, "x86_64", sizeof(buffer->machine));
+ break;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ uv__strscpy(buffer->machine, "ia64", sizeof(buffer->machine));
+ break;
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ uv__strscpy(buffer->machine, "i386", sizeof(buffer->machine));
+
+ if (system_info.wProcessorLevel > 3) {
+ processor_level = system_info.wProcessorLevel < 6 ?
+ system_info.wProcessorLevel : 6;
+ buffer->machine[1] = '0' + processor_level;
+ }
+
+ break;
+ case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
+ uv__strscpy(buffer->machine, "i686", sizeof(buffer->machine));
+ break;
+ case PROCESSOR_ARCHITECTURE_MIPS:
+ uv__strscpy(buffer->machine, "mips", sizeof(buffer->machine));
+ break;
+ case PROCESSOR_ARCHITECTURE_ALPHA:
+ case PROCESSOR_ARCHITECTURE_ALPHA64:
+ uv__strscpy(buffer->machine, "alpha", sizeof(buffer->machine));
+ break;
+ case PROCESSOR_ARCHITECTURE_PPC:
+ uv__strscpy(buffer->machine, "powerpc", sizeof(buffer->machine));
+ break;
+ case PROCESSOR_ARCHITECTURE_SHX:
+ uv__strscpy(buffer->machine, "sh", sizeof(buffer->machine));
+ break;
+ case PROCESSOR_ARCHITECTURE_ARM:
+ uv__strscpy(buffer->machine, "arm", sizeof(buffer->machine));
+ break;
+ default:
+ uv__strscpy(buffer->machine, "unknown", sizeof(buffer->machine));
+ break;
+ }
+
+ return 0;
+
+error:
+ buffer->sysname[0] = '\0';
+ buffer->release[0] = '\0';
+ buffer->version[0] = '\0';
+ buffer->machine[0] = '\0';
+ return r;
+}
diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c
index c330786..fbbbcee 100644
--- a/Utilities/cmlibuv/src/win/winapi.c
+++ b/Utilities/cmlibuv/src/win/winapi.c
@@ -26,6 +26,7 @@
/* Ntdll function pointers */
+sRtlGetVersion pRtlGetVersion;
sRtlNtStatusToDosError pRtlNtStatusToDosError;
sNtDeviceIoControlFile pNtDeviceIoControlFile;
sNtQueryInformationFile pNtQueryInformationFile;
@@ -34,20 +35,8 @@ sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
sNtQueryDirectoryFile pNtQueryDirectoryFile;
sNtQuerySystemInformation pNtQuerySystemInformation;
-
/* Kernel32 function pointers */
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
-sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
-sCreateSymbolicLinkW pCreateSymbolicLinkW;
-sCancelIoEx pCancelIoEx;
-sInitializeConditionVariable pInitializeConditionVariable;
-sSleepConditionVariableCS pSleepConditionVariableCS;
-sSleepConditionVariableSRW pSleepConditionVariableSRW;
-sWakeAllConditionVariable pWakeAllConditionVariable;
-sWakeConditionVariable pWakeConditionVariable;
-sCancelSynchronousIo pCancelSynchronousIo;
-sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
-
/* Powrprof.dll function pointer */
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
@@ -55,22 +44,21 @@ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
/* User32.dll function pointer */
sSetWinEventHook pSetWinEventHook;
-/* iphlpapi.dll function pointer */
-sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid = NULL;
-sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW = NULL;
void uv_winapi_init(void) {
HMODULE ntdll_module;
- HMODULE kernel32_module;
HMODULE powrprof_module;
HMODULE user32_module;
- HMODULE iphlpapi_module;
+ HMODULE kernel32_module;
ntdll_module = GetModuleHandleA("ntdll.dll");
if (ntdll_module == NULL) {
uv_fatal_error(GetLastError(), "GetModuleHandleA");
}
+ pRtlGetVersion = (sRtlGetVersion) GetProcAddress(ntdll_module,
+ "RtlGetVersion");
+
pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(
ntdll_module,
"RtlNtStatusToDosError");
@@ -127,37 +115,6 @@ void uv_winapi_init(void) {
kernel32_module,
"GetQueuedCompletionStatusEx");
- pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes)
- GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes");
-
- pCreateSymbolicLinkW = (sCreateSymbolicLinkW)
- GetProcAddress(kernel32_module, "CreateSymbolicLinkW");
-
- pCancelIoEx = (sCancelIoEx)
- GetProcAddress(kernel32_module, "CancelIoEx");
-
- pInitializeConditionVariable = (sInitializeConditionVariable)
- GetProcAddress(kernel32_module, "InitializeConditionVariable");
-
- pSleepConditionVariableCS = (sSleepConditionVariableCS)
- GetProcAddress(kernel32_module, "SleepConditionVariableCS");
-
- pSleepConditionVariableSRW = (sSleepConditionVariableSRW)
- GetProcAddress(kernel32_module, "SleepConditionVariableSRW");
-
- pWakeAllConditionVariable = (sWakeAllConditionVariable)
- GetProcAddress(kernel32_module, "WakeAllConditionVariable");
-
- pWakeConditionVariable = (sWakeConditionVariable)
- GetProcAddress(kernel32_module, "WakeConditionVariable");
-
- pCancelSynchronousIo = (sCancelSynchronousIo)
- GetProcAddress(kernel32_module, "CancelSynchronousIo");
-
- pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW)
- GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW");
-
-
powrprof_module = LoadLibraryA("powrprof.dll");
if (powrprof_module != NULL) {
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
@@ -170,11 +127,4 @@ void uv_winapi_init(void) {
GetProcAddress(user32_module, "SetWinEventHook");
}
- iphlpapi_module = LoadLibraryA("iphlpapi.dll");
- if (iphlpapi_module != NULL) {
- pConvertInterfaceIndexToLuid = (sConvertInterfaceIndexToLuid)
- GetProcAddress(iphlpapi_module, "ConvertInterfaceIndexToLuid");
- pConvertInterfaceLuidToNameW = (sConvertInterfaceLuidToNameW)
- GetProcAddress(iphlpapi_module, "ConvertInterfaceLuidToNameW");
- }
}
diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h
index ae384b7..1e49b57 100644
--- a/Utilities/cmlibuv/src/win/winapi.h
+++ b/Utilities/cmlibuv/src/win/winapi.h
@@ -4076,8 +4076,8 @@
# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L)
#endif
-/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the */
-/* DDK got it wrong! */
+/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the DDK
+ * got it wrong! */
#ifdef NTSTATUS_FROM_WIN32
# undef NTSTATUS_FROM_WIN32
#endif
@@ -4109,6 +4109,9 @@
#endif
/* from winternl.h */
+#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32_)
+#define __UNICODE_STRING_DEFINED
+#endif
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
@@ -4524,6 +4527,9 @@ typedef VOID (NTAPI *PIO_APC_ROUTINE)
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved);
+typedef NTSTATUS (NTAPI *sRtlGetVersion)
+ (PRTL_OSVERSIONINFOW lpVersionInformation);
+
typedef ULONG (NTAPI *sRtlNtStatusToDosError)
(NTSTATUS Status);
@@ -4659,48 +4665,6 @@ typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
DWORD dwMilliseconds,
BOOL fAlertable);
-typedef BOOL (WINAPI* sSetFileCompletionNotificationModes)
- (HANDLE FileHandle,
- UCHAR Flags);
-
-typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW)
- (LPCWSTR lpSymlinkFileName,
- LPCWSTR lpTargetFileName,
- DWORD dwFlags);
-
-typedef BOOL (WINAPI* sCancelIoEx)
- (HANDLE hFile,
- LPOVERLAPPED lpOverlapped);
-
-typedef VOID (WINAPI* sInitializeConditionVariable)
- (PCONDITION_VARIABLE ConditionVariable);
-
-typedef BOOL (WINAPI* sSleepConditionVariableCS)
- (PCONDITION_VARIABLE ConditionVariable,
- PCRITICAL_SECTION CriticalSection,
- DWORD dwMilliseconds);
-
-typedef BOOL (WINAPI* sSleepConditionVariableSRW)
- (PCONDITION_VARIABLE ConditionVariable,
- PSRWLOCK SRWLock,
- DWORD dwMilliseconds,
- ULONG Flags);
-
-typedef VOID (WINAPI* sWakeAllConditionVariable)
- (PCONDITION_VARIABLE ConditionVariable);
-
-typedef VOID (WINAPI* sWakeConditionVariable)
- (PCONDITION_VARIABLE ConditionVariable);
-
-typedef BOOL (WINAPI* sCancelSynchronousIo)
- (HANDLE hThread);
-
-typedef DWORD (WINAPI* sGetFinalPathNameByHandleW)
- (HANDLE hFile,
- LPWSTR lpszFilePath,
- DWORD cchFilePath,
- DWORD dwFlags);
-
/* from powerbase.h */
#ifndef DEVICE_NOTIFY_CALLBACK
# define DEVICE_NOTIFY_CALLBACK 2
@@ -4755,6 +4719,7 @@ typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook)
/* Ntdll function pointers */
+extern sRtlGetVersion pRtlGetVersion;
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
extern sNtQueryInformationFile pNtQueryInformationFile;
@@ -4763,20 +4728,8 @@ extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
extern sNtQuerySystemInformation pNtQuerySystemInformation;
-
/* Kernel32 function pointers */
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
-extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
-extern sCreateSymbolicLinkW pCreateSymbolicLinkW;
-extern sCancelIoEx pCancelIoEx;
-extern sInitializeConditionVariable pInitializeConditionVariable;
-extern sSleepConditionVariableCS pSleepConditionVariableCS;
-extern sSleepConditionVariableSRW pSleepConditionVariableSRW;
-extern sWakeAllConditionVariable pWakeAllConditionVariable;
-extern sWakeConditionVariable pWakeConditionVariable;
-extern sCancelSynchronousIo pCancelSynchronousIo;
-extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
-
/* Powrprof.dll function pointer */
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
@@ -4784,19 +4737,4 @@ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotifi
/* User32.dll function pointer */
extern sSetWinEventHook pSetWinEventHook;
-/* iphlpapi.dll function pointer */
-union _NET_LUID_LH;
-typedef DWORD (WINAPI *sConvertInterfaceIndexToLuid)(
- ULONG InterfaceIndex,
- union _NET_LUID_LH *InterfaceLuid);
-
-typedef DWORD (WINAPI *sConvertInterfaceLuidToNameW)(
- const union _NET_LUID_LH *InterfaceLuid,
- PWSTR InterfaceName,
- size_t Length);
-
-extern sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid;
-extern sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW;
-
-
#endif /* UV_WIN_WINAPI_H_ */
diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c
index 8418895..5e7da2a 100644
--- a/Utilities/cmlibuv/src/win/winsock.c
+++ b/Utilities/cmlibuv/src/win/winsock.c
@@ -256,8 +256,8 @@ int uv_ntstatus_to_winsock_error(NTSTATUS status) {
default:
if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) &&
(status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) {
- /* It's a windows error that has been previously mapped to an */
- /* ntstatus code. */
+ /* It's a windows error that has been previously mapped to an ntstatus
+ * code. */
return (DWORD) (status & 0xffff);
} else {
/* The default fallback for unmappable ntstatus codes. */
@@ -519,8 +519,8 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
sizeof *info_out);
if (overlapped == NULL) {
- /* If this is a blocking operation, wait for the event to become */
- /* signaled, and then grab the real status from the io status block. */
+ /* If this is a blocking operation, wait for the event to become signaled,
+ * and then grab the real status from the io status block. */
if (status == STATUS_PENDING) {
DWORD r = WaitForSingleObject(event, INFINITE);