diff options
author | Brad King <brad.king@kitware.com> | 2020-09-24 19:15:38 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2020-09-24 19:16:28 (GMT) |
commit | c98ec731f90eb0180c89108b7d2e42263b66d1ed (patch) | |
tree | 2d67994bbea44ba6712e6dcb637438f6dbfb0ac6 /Utilities/cmlibuv/src/win | |
parent | 0436f70f80de4a56313b9da0668ac6674078b2d1 (diff) | |
parent | 7a0506bafe387bfff441c0159b9a3d58f68db177 (diff) | |
download | CMake-c98ec731f90eb0180c89108b7d2e42263b66d1ed.zip CMake-c98ec731f90eb0180c89108b7d2e42263b66d1ed.tar.gz CMake-c98ec731f90eb0180c89108b7d2e42263b66d1ed.tar.bz2 |
Merge topic 'update-libuv'
7a0506bafe libuv: Suppress conversion warning on Windows
2269ad6a0a libuv: Add fs_copy stub to cmake-bootstrap.c
e21325c2c6 Merge branch 'upstream-libuv' into update-libuv
c1463f959f libuv 2020-09-22 (ed5b42d5)
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !5259
Diffstat (limited to 'Utilities/cmlibuv/src/win')
-rw-r--r-- | Utilities/cmlibuv/src/win/core.c | 91 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/detect-wakeup.c | 21 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/fs-fd-hash-inl.h | 24 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/fs.c | 93 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/internal.h | 2 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/pipe.c | 12 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/tcp.c | 62 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/tty.c | 15 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/udp.c | 16 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/util.c | 34 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/win/winapi.h | 12 |
11 files changed, 300 insertions, 82 deletions
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c index 9974a11..e53a0f8 100644 --- a/Utilities/cmlibuv/src/win/core.c +++ b/Utilities/cmlibuv/src/win/core.c @@ -222,6 +222,7 @@ static void uv_init(void) { int uv_loop_init(uv_loop_t* loop) { + uv__loop_internal_fields_t* lfields; struct heap* timer_heap; int err; @@ -233,6 +234,15 @@ int uv_loop_init(uv_loop_t* loop) { if (loop->iocp == NULL) return uv_translate_sys_error(GetLastError()); + lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields)); + if (lfields == NULL) + return UV_ENOMEM; + loop->internal_fields = lfields; + + err = uv_mutex_init(&lfields->loop_metrics.lock); + if (err) + goto fail_metrics_mutex_init; + /* To prevent uninitialized memory access, loop->time must be initialized * to zero before calling uv_update_time for the first time. */ @@ -297,6 +307,11 @@ fail_mutex_init: loop->timer_heap = NULL; fail_timers_alloc: + uv_mutex_destroy(&lfields->loop_metrics.lock); + +fail_metrics_mutex_init: + uv__free(lfields); + loop->internal_fields = NULL; CloseHandle(loop->iocp); loop->iocp = INVALID_HANDLE_VALUE; @@ -317,6 +332,7 @@ void uv__once_init(void) { void uv__loop_close(uv_loop_t* loop) { + uv__loop_internal_fields_t* lfields; size_t i; uv__loops_remove(loop); @@ -347,11 +363,24 @@ void uv__loop_close(uv_loop_t* loop) { uv__free(loop->timer_heap); loop->timer_heap = NULL; + lfields = uv__get_internal_fields(loop); + uv_mutex_destroy(&lfields->loop_metrics.lock); + uv__free(lfields); + loop->internal_fields = NULL; + CloseHandle(loop->iocp); } int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { + uv__loop_internal_fields_t* lfields; + + lfields = uv__get_internal_fields(loop); + if (option == UV_METRICS_IDLE_TIME) { + lfields->flags |= UV_METRICS_IDLE_TIME; + return 0; + } + return UV_ENOSYS; } @@ -393,16 +422,44 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { uv_req_t* req; int repeat; uint64_t timeout_time; + uint64_t user_timeout; + int reset_timeout; timeout_time = loop->time + timeout; + if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { + reset_timeout = 1; + user_timeout = timeout; + timeout = 0; + } else { + reset_timeout = 0; + } + for (repeat = 0; ; repeat++) { + /* Only need to set the provider_entry_time if timeout != 0. The function + * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. + */ + if (timeout != 0) + uv__metrics_set_provider_entry_time(loop); + GetQueuedCompletionStatus(loop->iocp, &bytes, &key, &overlapped, timeout); + if (reset_timeout != 0) { + timeout = user_timeout; + reset_timeout = 0; + } + + /* Placed here because on success the loop will break whether there is an + * empty package or not, or if GetQueuedCompletionStatus returned early then + * the timeout will be updated and the loop will run again. In either case + * the idle time will need to be updated. + */ + uv__metrics_update_idle_time(loop); + if (overlapped) { /* Package was dequeued */ req = uv_overlapped_to_req(overlapped); @@ -445,10 +502,26 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { ULONG i; int repeat; uint64_t timeout_time; + uint64_t user_timeout; + int reset_timeout; timeout_time = loop->time + timeout; + if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { + reset_timeout = 1; + user_timeout = timeout; + timeout = 0; + } else { + reset_timeout = 0; + } + for (repeat = 0; ; repeat++) { + /* Only need to set the provider_entry_time if timeout != 0. The function + * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. + */ + if (timeout != 0) + uv__metrics_set_provider_entry_time(loop); + success = pGetQueuedCompletionStatusEx(loop->iocp, overlappeds, ARRAY_SIZE(overlappeds), @@ -456,6 +529,18 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { timeout, FALSE); + if (reset_timeout != 0) { + timeout = user_timeout; + reset_timeout = 0; + } + + /* Placed here because on success the loop will break whether there is an + * empty package or not, or if GetQueuedCompletionStatus returned early then + * the timeout will be updated and the loop will run again. In either case + * the idle time will need to be updated. + */ + uv__metrics_update_idle_time(loop); + if (success) { for (i = 0; i < count; i++) { /* Package was dequeued, but see if it is not a empty package @@ -534,6 +619,12 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { else uv__poll_wine(loop, timeout); + /* Run one final update on the provider_idle_time in case uv__poll* + * returned because the timeout expired, but no events were received. This + * call will be ignored if the provider_entry_time was either never set (if + * the timeout == 0) or was already updated b/c an event was received. + */ + uv__metrics_update_idle_time(loop); uv_check_invoke(loop); uv_process_endgames(loop); diff --git a/Utilities/cmlibuv/src/win/detect-wakeup.c b/Utilities/cmlibuv/src/win/detect-wakeup.c index 72dfb7a..ab19361 100644 --- a/Utilities/cmlibuv/src/win/detect-wakeup.c +++ b/Utilities/cmlibuv/src/win/detect-wakeup.c @@ -1,3 +1,24 @@ +/* Copyright libuv project 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 "uv.h" #include "internal.h" #include "winapi.h" diff --git a/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h b/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h index 7a203d2..0b532af 100644 --- a/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h +++ b/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h @@ -1,3 +1,24 @@ +/* Copyright libuv project 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. + */ + #ifndef UV_WIN_FS_FD_HASH_INL_H_ #define UV_WIN_FS_FD_HASH_INL_H_ @@ -53,7 +74,8 @@ static struct uv__fd_hash_bucket_s uv__fd_hash[UV__FD_HASH_SIZE]; INLINE static void uv__fd_hash_init(void) { - int i, err; + size_t i; + int err; err = uv_mutex_init(&uv__fd_hash_mutex); if (err) { diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c index 9577bc0..d6ff7ed 100644 --- a/Utilities/cmlibuv/src/win/fs.c +++ b/Utilities/cmlibuv/src/win/fs.c @@ -70,10 +70,7 @@ #define SET_REQ_RESULT(req, result_value) \ do { \ req->result = (result_value); \ - if (req->result == -1) { \ - req->sys_errno_ = _doserrno; \ - req->result = uv_translate_sys_error(req->sys_errno_); \ - } \ + assert(req->result != -1); \ } while (0) #define SET_REQ_WIN32_ERROR(req, sys_errno) \ @@ -730,14 +727,14 @@ void fs__close(uv_fs_t* req) { assert(errno == EBADF); SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE); } else { - req->result = 0; + SET_REQ_RESULT(req, 0); } } LONG fs__filemap_ex_filter(LONG excode, PEXCEPTION_POINTERS pep, int* perror) { - if (excode != EXCEPTION_IN_PAGE_ERROR) { + if (excode != (LONG)EXCEPTION_IN_PAGE_ERROR) { return EXCEPTION_CONTINUE_SEARCH; } @@ -816,10 +813,10 @@ void fs__read_filemap(uv_fs_t* req, struct uv__fd_info_s* fd_info) { for (index = 0; index < req->fs.info.nbufs && done_read < read_size; ++index) { - int err = 0; size_t this_read_size = MIN(req->fs.info.bufs[index].len, read_size - done_read); #ifdef _MSC_VER + int err = 0; __try { #endif memcpy(req->fs.info.bufs[index].base, @@ -938,7 +935,7 @@ void fs__write_filemap(uv_fs_t* req, HANDLE file, (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR); size_t write_size, done_write; unsigned int index; - LARGE_INTEGER zero, pos, end_pos; + LARGE_INTEGER pos, end_pos; size_t view_offset; LARGE_INTEGER view_base; void* view; @@ -963,7 +960,6 @@ void fs__write_filemap(uv_fs_t* req, HANDLE file, return; } - zero.QuadPart = 0; if (force_append) { pos = fd_info->size; } else if (req->fs.info.offset == -1) { @@ -1014,8 +1010,8 @@ void fs__write_filemap(uv_fs_t* req, HANDLE file, done_write = 0; for (index = 0; index < req->fs.info.nbufs; ++index) { - int err = 0; #ifdef _MSC_VER + int err = 0; __try { #endif memcpy((char*)view + view_offset + done_write, @@ -1128,7 +1124,10 @@ void fs__write(uv_fs_t* req) { void fs__rmdir(uv_fs_t* req) { int result = _wrmdir(req->file.pathw); - SET_REQ_RESULT(req, result); + if (result == -1) + SET_REQ_WIN32_ERROR(req, _doserrno); + else + SET_REQ_RESULT(req, 0); } @@ -1221,12 +1220,12 @@ void fs__unlink(uv_fs_t* req) { void fs__mkdir(uv_fs_t* req) { /* TODO: use req->mode. */ - req->result = _wmkdir(req->file.pathw); - if (req->result == -1) { - req->sys_errno_ = _doserrno; - req->result = req->sys_errno_ == ERROR_INVALID_NAME - ? UV_EINVAL - : uv_translate_sys_error(req->sys_errno_); + if (CreateDirectoryW(req->file.pathw, NULL)) { + SET_REQ_RESULT(req, 0); + } else { + SET_REQ_WIN32_ERROR(req, GetLastError()); + if (req->sys_errno_ == ERROR_INVALID_NAME) + req->result = UV_EINVAL; } } @@ -1242,19 +1241,21 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) { unsigned int tries, i; size_t len; uint64_t v; - + char* path; + + path = (char*)req->path; len = wcslen(req->file.pathw); ep = req->file.pathw + len; if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) { SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); - return; + goto clobber; } tries = TMP_MAX; do { if (uv__random_rtlgenrandom((void *)&v, sizeof(v)) < 0) { SET_REQ_UV_ERROR(req, UV_EIO, ERROR_IO_DEVICE); - break; + goto clobber; } cp = ep - num_x; @@ -1265,25 +1266,29 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) { if (func(req)) { if (req->result >= 0) { - len = strlen(req->path); - wcstombs((char*) req->path + len - num_x, ep - num_x, num_x); + len = strlen(path); + wcstombs(path + len - num_x, ep - num_x, num_x); } - break; + return; } } while (--tries); - if (tries == 0) { - SET_REQ_RESULT(req, -1); - } + SET_REQ_WIN32_ERROR(req, GetLastError()); + +clobber: + path[0] = '\0'; } static int fs__mkdtemp_func(uv_fs_t* req) { - if (_wmkdir(req->file.pathw) == 0) { + DWORD error; + if (CreateDirectoryW(req->file.pathw, NULL)) { SET_REQ_RESULT(req, 0); return 1; - } else if (errno != EEXIST) { - SET_REQ_RESULT(req, -1); + } + error = GetLastError(); + if (error != ERROR_ALREADY_EXISTS) { + SET_REQ_WIN32_ERROR(req, error); return 1; } @@ -1404,7 +1409,7 @@ void fs__scandir(uv_fs_t* req) { /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER. * This should be reported back as UV_ENOTDIR. */ - if (status == STATUS_INVALID_PARAMETER) + if (status == (NTSTATUS)STATUS_INVALID_PARAMETER) goto not_a_directory_error; while (NT_SUCCESS(status)) { @@ -1895,7 +1900,7 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { } req->ptr = &req->statbuf; - req->result = 0; + SET_REQ_RESULT(req, 0); } @@ -1930,7 +1935,7 @@ static void fs__fstat(uv_fs_t* req) { } req->ptr = &req->statbuf; - req->result = 0; + SET_REQ_RESULT(req, 0); } @@ -2157,7 +2162,10 @@ static void fs__access(uv_fs_t* req) { static void fs__chmod(uv_fs_t* req) { int result = _wchmod(req->file.pathw, req->fs.info.mode); - SET_REQ_RESULT(req, result); + if (result == -1) + SET_REQ_WIN32_ERROR(req, _doserrno); + else + SET_REQ_RESULT(req, 0); } @@ -2315,7 +2323,7 @@ INLINE static void fs__utime_impl(uv_fs_t* req, int do_lutime) { return; } - req->result = 0; + SET_REQ_RESULT(req, 0); } static void fs__utime(uv_fs_t* req) { @@ -2340,7 +2348,7 @@ static void fs__futime(uv_fs_t* req) { return; } - req->result = 0; + SET_REQ_RESULT(req, 0); } static void fs__lutime(uv_fs_t* req) { @@ -2350,11 +2358,10 @@ static void fs__lutime(uv_fs_t* req) { static void fs__link(uv_fs_t* req) { DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL); - if (r == 0) { + if (r == 0) SET_REQ_WIN32_ERROR(req, GetLastError()); - } else { - req->result = 0; - } + else + SET_REQ_RESULT(req, 0); } @@ -2674,17 +2681,17 @@ static void fs__realpath(uv_fs_t* req) { static void fs__chown(uv_fs_t* req) { - req->result = 0; + SET_REQ_RESULT(req, 0); } static void fs__fchown(uv_fs_t* req) { - req->result = 0; + SET_REQ_RESULT(req, 0); } static void fs__lchown(uv_fs_t* req) { - req->result = 0; + SET_REQ_RESULT(req, 0); } @@ -2829,7 +2836,7 @@ static void uv__fs_done(struct uv__work* w, int status) { if (status == UV_ECANCELED) { assert(req->result == 0); - req->result = UV_ECANCELED; + SET_REQ_UV_ERROR(req, UV_ECANCELED, 0); } req->cb(req); diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h index 463ef33..3f56777 100644 --- a/Utilities/cmlibuv/src/win/internal.h +++ b/Utilities/cmlibuv/src/win/internal.h @@ -270,7 +270,7 @@ 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); +uint64_t uv__hrtime(unsigned int scale); __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/pipe.c b/Utilities/cmlibuv/src/win/pipe.c index fc0112a..f81245e 100644 --- a/Utilities/cmlibuv/src/win/pipe.c +++ b/Utilities/cmlibuv/src/win/pipe.c @@ -244,9 +244,8 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, return 0; error: - if (pipeHandle != INVALID_HANDLE_VALUE) { + if (pipeHandle != INVALID_HANDLE_VALUE) CloseHandle(pipeHandle); - } return err; } @@ -554,7 +553,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { /* Convert name to UTF16. */ nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); - handle->name = (WCHAR*)uv__malloc(nameSize); + handle->name = uv__malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } @@ -621,9 +620,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { while (WaitNamedPipeW(handle->name, 30000)) { /* The pipe is now available, try to connect. */ pipeHandle = open_named_pipe(handle->name, &duplex_flags); - if (pipeHandle != INVALID_HANDLE_VALUE) { + if (pipeHandle != INVALID_HANDLE_VALUE) break; - } SwitchToThread(); } @@ -655,7 +653,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, /* Convert name to UTF16. */ nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); - handle->name = (WCHAR*)uv__malloc(nameSize); + handle->name = uv__malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } @@ -2147,7 +2145,7 @@ 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_remote_pid = uv_os_getppid(); - assert(pipe->pipe.conn.ipc_remote_pid != (DWORD) -1); + assert(pipe->pipe.conn.ipc_remote_pid != (DWORD)(uv_pid_t) -1); } return 0; } diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c index 941c801..0dcaa97 100644 --- a/Utilities/cmlibuv/src/win/tcp.c +++ b/Utilities/cmlibuv/src/win/tcp.c @@ -523,16 +523,15 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { &req->u.io.overlapped, NULL); + handle->flags |= UV_HANDLE_READ_PENDING; + handle->reqs_pending++; + if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; req->u.io.overlapped.InternalHigh = bytes; - handle->reqs_pending++; uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; if (handle->flags & UV_HANDLE_EMULATE_IOCP && req->wait_handle == INVALID_HANDLE_VALUE && !RegisterWaitForSingleObject(&req->wait_handle, @@ -545,7 +544,6 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; } } @@ -750,6 +748,40 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, return 0; } +static int uv__is_loopback(const struct sockaddr_storage* storage) { + const struct sockaddr_in* in4; + const struct sockaddr_in6* in6; + int i; + + if (storage->ss_family == AF_INET) { + in4 = (const struct sockaddr_in*) storage; + return in4->sin_addr.S_un.S_un_b.s_b1 == 127; + } + if (storage->ss_family == AF_INET6) { + in6 = (const struct sockaddr_in6*) storage; + for (i = 0; i < 7; ++i) { + if (in6->sin6_addr.u.Word[i] != 0) + return 0; + } + return in6->sin6_addr.u.Word[7] == htons(1); + } + return 0; +} + +// Check if Windows version is 10.0.16299 or later +static int uv__is_fast_loopback_fail_supported() { + OSVERSIONINFOW os_info; + if (!pRtlGetVersion) + return 0; + pRtlGetVersion(&os_info); + if (os_info.dwMajorVersion < 10) + return 0; + if (os_info.dwMajorVersion > 10) + return 1; + if (os_info.dwMinorVersion > 0) + return 1; + return os_info.dwBuildNumber >= 16299; +} static int uv_tcp_try_connect(uv_connect_t* req, uv_tcp_t* handle, @@ -757,6 +789,7 @@ static int uv_tcp_try_connect(uv_connect_t* req, unsigned int addrlen, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; + TCP_INITIAL_RTO_PARAMETERS retransmit_ioctl; const struct sockaddr* bind_addr; struct sockaddr_storage converted; BOOL success; @@ -792,6 +825,25 @@ static int uv_tcp_try_connect(uv_connect_t* req, } } + /* This makes connect() fail instantly if the target port on the localhost + * is not reachable, instead of waiting for 2s. We do not care if this fails. + * This only works on Windows version 10.0.16299 and later. + */ + if (uv__is_fast_loopback_fail_supported() && uv__is_loopback(&converted)) { + memset(&retransmit_ioctl, 0, sizeof(retransmit_ioctl)); + retransmit_ioctl.Rtt = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS; + retransmit_ioctl.MaxSynRetransmissions = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS; + WSAIoctl(handle->socket, + SIO_TCP_INITIAL_RTO, + &retransmit_ioctl, + sizeof(retransmit_ioctl), + NULL, + 0, + &bytes, + NULL, + NULL); + } + UV_REQ_INIT(req, UV_CONNECT); req->handle = (uv_stream_t*) handle; req->cb = cb; diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c index 488d9b2..1b9d4f8 100644 --- a/Utilities/cmlibuv/src/win/tty.c +++ b/Utilities/cmlibuv/src/win/tty.c @@ -517,6 +517,7 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS); if (status == TRAP_REQUESTED) { SET_REQ_SUCCESS(req); + InterlockedExchange(&uv__read_console_status, COMPLETED); req->u.io.overlapped.InternalHigh = 0; POST_COMPLETION_FOR_REQ(loop, req); return 0; @@ -2121,13 +2122,6 @@ 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. */ - if (utf8_codepoint > 0xffff) { - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - } - if (utf8_codepoint == 0x0a || utf8_codepoint == 0x0d) { /* EOL conversion - emit \r\n when we see \n. */ @@ -2154,6 +2148,12 @@ static int uv_tty_write_bufs(uv_tty_t* handle, ENSURE_BUFFER_SPACE(1); utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint; previous_eol = 0; + } else { + ENSURE_BUFFER_SPACE(2); + utf8_codepoint -= 0x10000; + utf16_buf[utf16_buf_used++] = (WCHAR) (utf8_codepoint / 0x400 + 0xD800); + utf16_buf[utf16_buf_used++] = (WCHAR) (utf8_codepoint % 0x400 + 0xDC00); + previous_eol = 0; } } } @@ -2412,6 +2412,7 @@ static DWORD WINAPI uv__tty_console_resize_watcher_thread(void* param) { uv__tty_console_signal_resize(); ResetEvent(uv__tty_console_resized); } + return 0; } static void uv__tty_console_signal_resize(void) { diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c index 508ed37..68ca728 100644 --- a/Utilities/cmlibuv/src/win/udp.c +++ b/Utilities/cmlibuv/src/win/udp.c @@ -189,6 +189,11 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { } +int uv_udp_using_recvmmsg(const uv_udp_t* handle) { + return 0; +} + + static int uv_udp_maybe_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int addrlen, @@ -752,6 +757,9 @@ int uv__udp_set_source_membership6(uv_udp_t* handle, int optname; int err; + STATIC_ASSERT(sizeof(mreq.gsr_group) >= sizeof(*multicast_addr)); + STATIC_ASSERT(sizeof(mreq.gsr_source) >= sizeof(*source_addr)); + if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6)) return UV_EINVAL; @@ -774,8 +782,8 @@ int uv__udp_set_source_membership6(uv_udp_t* handle, mreq.gsr_interface = 0; } - memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group)); - memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source)); + memcpy(&mreq.gsr_group, multicast_addr, sizeof(*multicast_addr)); + memcpy(&mreq.gsr_source, source_addr, sizeof(*source_addr)); if (membership == UV_JOIN_GROUP) optname = MCAST_JOIN_SOURCE_GROUP; @@ -1065,7 +1073,7 @@ int uv__udp_connect(uv_udp_t* handle, err = connect(handle->socket, addr, addrlen); if (err) - return uv_translate_sys_error(err); + return uv_translate_sys_error(WSAGetLastError()); handle->flags |= UV_HANDLE_UDP_CONNECTED; @@ -1081,7 +1089,7 @@ int uv__udp_disconnect(uv_udp_t* handle) { err = connect(handle->socket, &addr, sizeof(addr)); if (err) - return uv_translate_sys_error(err); + return uv_translate_sys_error(WSAGetLastError()); handle->flags &= ~UV_HANDLE_UDP_CONNECTED; return 0; diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c index 9e1e7f7..aad8f1a 100644 --- a/Utilities/cmlibuv/src/win/util.c +++ b/Utilities/cmlibuv/src/win/util.c @@ -30,12 +30,14 @@ #include "uv.h" #include "internal.h" +/* clang-format off */ #include <winsock2.h> #include <winperf.h> #include <iphlpapi.h> #include <psapi.h> #include <tlhelp32.h> #include <windows.h> +/* clang-format on */ #include <userenv.h> #include <math.h> @@ -67,8 +69,8 @@ extern BOOLEAN NTAPI SystemFunction036(PVOID Buffer, ULONG BufferLength); static char *process_title; static CRITICAL_SECTION process_title_lock; -/* Interval (in seconds) of the high-resolution clock. */ -static double hrtime_interval_ = 0; +/* Frequency of the high-resolution clock. */ +static uint64_t hrtime_frequency_ = 0; /* @@ -84,9 +86,9 @@ void uv__util_init(void) { * and precompute its reciprocal. */ if (QueryPerformanceFrequency(&perf_frequency)) { - hrtime_interval_ = 1.0 / perf_frequency.QuadPart; + hrtime_frequency_ = perf_frequency.QuadPart; } else { - hrtime_interval_= 0; + uv_fatal_error(GetLastError(), "QueryPerformanceFrequency"); } } @@ -490,23 +492,25 @@ uint64_t uv_hrtime(void) { return uv__hrtime(UV__NANOSEC); } -uint64_t uv__hrtime(double scale) { +uint64_t uv__hrtime(unsigned int scale) { LARGE_INTEGER counter; + double scaled_freq; + double result; - /* If the performance interval is zero, there's no support. */ - if (hrtime_interval_ == 0) { - return 0; - } - + assert(hrtime_frequency_ != 0); + assert(scale != 0); if (!QueryPerformanceCounter(&counter)) { - return 0; + uv_fatal_error(GetLastError(), "QueryPerformanceCounter"); } + assert(counter.QuadPart != 0); /* Because we have no guarantee about the order of magnitude of the * performance counter interval, integer math could cause this computation * to overflow. Therefore we resort to floating point math. */ - return (uint64_t) ((double) counter.QuadPart * hrtime_interval_ * scale); + scaled_freq = (double) hrtime_frequency_ / scale; + result = (double) counter.QuadPart / scaled_freq; + return (uint64_t) result; } @@ -1804,7 +1808,9 @@ int uv_os_uname(uv_utsname_t* buffer) { pRtlGetVersion(&os_info); } else { /* Silence GetVersionEx() deprecation warning. */ + #ifdef _MSC_VER #pragma warning(suppress : 4996) + #endif if (GetVersionExW(&os_info) == 0) { r = uv_translate_sys_error(GetLastError()); goto error; @@ -1871,7 +1877,7 @@ int uv_os_uname(uv_utsname_t* buffer) { "MINGW32_NT-%u.%u", (unsigned int) os_info.dwMajorVersion, (unsigned int) os_info.dwMinorVersion); - assert(r < sizeof(buffer->sysname)); + assert((size_t)r < sizeof(buffer->sysname)); #else uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname)); #endif @@ -1883,7 +1889,7 @@ int uv_os_uname(uv_utsname_t* buffer) { (unsigned int) os_info.dwMajorVersion, (unsigned int) os_info.dwMinorVersion, (unsigned int) os_info.dwBuildNumber); - assert(r < sizeof(buffer->release)); + assert((size_t)r < sizeof(buffer->release)); /* Populate the machine field. */ GetSystemInfo(&system_info); diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h index 77f1878..9bc4559 100644 --- a/Utilities/cmlibuv/src/win/winapi.h +++ b/Utilities/cmlibuv/src/win/winapi.h @@ -4735,6 +4735,18 @@ typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook) DWORD idThread, UINT dwflags); +/* From mstcpip.h */ +typedef struct _TCP_INITIAL_RTO_PARAMETERS { + USHORT Rtt; + UCHAR MaxSynRetransmissions; +} TCP_INITIAL_RTO_PARAMETERS, *PTCP_INITIAL_RTO_PARAMETERS; + +#ifndef TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS +# define TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS ((UCHAR) -2) +#endif +#ifndef SIO_TCP_INITIAL_RTO +# define SIO_TCP_INITIAL_RTO _WSAIOW(IOC_VENDOR,17) +#endif /* Ntdll function pointers */ extern sRtlGetVersion pRtlGetVersion; |