Z-IO 1.0.0.0 → 1.0.1.0
raw patch · 52 files changed
+1539/−1014 lines, 52 filesdep ~Z-DataPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: Z-Data
API changes (from Hackage documentation)
Files
- ChangeLog.md +6/−0
- Z-IO.cabal +3/−2
- Z/IO/BIO.hs +1/−1
- Z/IO/BIO/Base.hs +1/−1
- Z/IO/UV/UVStream.hs +0/−14
- third_party/libuv/include/uv.h +26/−4
- third_party/libuv/include/uv/errno.h +12/−0
- third_party/libuv/include/uv/tree.h +1/−1
- third_party/libuv/include/uv/version.h +1/−1
- third_party/libuv/src/idna.c +36/−13
- third_party/libuv/src/inet.c +2/−1
- third_party/libuv/src/threadpool.c +0/−2
- third_party/libuv/src/timer.c +1/−0
- third_party/libuv/src/unix/async.c +1/−1
- third_party/libuv/src/unix/atomic-ops.h +4/−2
- third_party/libuv/src/unix/bsd-ifaddrs.c +3/−3
- third_party/libuv/src/unix/core.c +19/−9
- third_party/libuv/src/unix/darwin.c +8/−4
- third_party/libuv/src/unix/epoll.c +422/−0
- third_party/libuv/src/unix/fs.c +89/−17
- third_party/libuv/src/unix/fsevents.c +8/−15
- third_party/libuv/src/unix/getaddrinfo.c +0/−3
- third_party/libuv/src/unix/internal.h +23/−7
- third_party/libuv/src/unix/linux-core.c +45/−425
- third_party/libuv/src/unix/linux-inotify.c +1/−1
- third_party/libuv/src/unix/linux-syscalls.c +17/−20
- third_party/libuv/src/unix/linux-syscalls.h +2/−5
- third_party/libuv/src/unix/os390-syscalls.h +1/−1
- third_party/libuv/src/unix/pipe.c +54/−0
- third_party/libuv/src/unix/poll.c +12/−2
- third_party/libuv/src/unix/process.c +32/−95
- third_party/libuv/src/unix/proctitle.c +1/−3
- third_party/libuv/src/unix/signal.c +1/−1
- third_party/libuv/src/unix/stream.c +102/−117
- third_party/libuv/src/unix/tcp.c +51/−2
- third_party/libuv/src/unix/thread.c +6/−6
- third_party/libuv/src/unix/tty.c +18/−0
- third_party/libuv/src/unix/udp.c +29/−3
- third_party/libuv/src/uv-common.c +24/−1
- third_party/libuv/src/uv-common.h +7/−2
- third_party/libuv/src/win/atomicops-inl.h +6/−2
- third_party/libuv/src/win/error.c +1/−1
- third_party/libuv/src/win/fs.c +25/−26
- third_party/libuv/src/win/internal.h +2/−2
- third_party/libuv/src/win/pipe.c +213/−15
- third_party/libuv/src/win/poll.c +2/−1
- third_party/libuv/src/win/process-stdio.c +0/−96
- third_party/libuv/src/win/process.c +1/−1
- third_party/libuv/src/win/stream.c +13/−10
- third_party/libuv/src/win/tcp.c +192/−68
- third_party/libuv/src/win/udp.c +2/−2
- third_party/libuv/src/win/util.c +12/−5
ChangeLog.md view
@@ -1,5 +1,11 @@ # Revision history for Z-IO +## 1.0.1.0 -- 2020-07-24++Maintenance release:++* Update libuv to v1.42.0, rewrite `UV_Stream`'s `Output` instance to perform a `uv_try_write` first since now `uv_try_write` is sensible.+ ## 1.0.0.0 -- 2020-07-08 * Clean function names in `Z.IO.BIO` module, now no `BIO` or `Node` suffix anymore.
Z-IO.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: Z-IO-version: 1.0.0.0+version: 1.0.1.0 synopsis: Simple and high performance IO toolkit for Haskell description: Simple and high performance IO toolkit for Haskell, including@@ -126,7 +126,7 @@ , time >=1.9 && <2.0 , unix-time >=0.4.7 && <0.5 , unordered-containers ^>=0.2- , Z-Data >=1.0 && <1.1+ , Z-Data >=1.0 && <1.2 default-language: Haskell2010 default-extensions:@@ -273,6 +273,7 @@ third_party/libuv/src/unix/async.c third_party/libuv/src/unix/core.c third_party/libuv/src/unix/dl.c+ third_party/libuv/src/unix/epoll.c third_party/libuv/src/unix/fs.c third_party/libuv/src/unix/getaddrinfo.c third_party/libuv/src/unix/getnameinfo.c
Z/IO/BIO.hs view
@@ -21,7 +21,7 @@ * Packet parsers. We use @BIO inp out@ type to represent all the objects above, @BIO Void out@ to represent an 'IO' source,-and @BIO inp Void@ to represent an 'IO' sink, which can all be connected with '>|>' to build a larger 'BIO' node.+and @BIO inp Void@ to represent an 'IO' sink, which can all be connected with '.' to build a larger 'BIO' node. @ import Z.Data.CBytes (CBytes)
Z/IO/BIO/Base.hs view
@@ -103,7 +103,7 @@ -- * @type Sink inp = BIO inp Void@ described an IO sink, which takes input and perform some IO effects, -- such as writing to terminal or files. ----- You can connect these 'BIO' nodes with '>|>', which connect left node's output to right node's input,+-- You can connect these 'BIO' nodes with '.' which connect left node's output to right node's input, -- and return a new 'BIO' node with left node's input type and right node's output type. -- -- You can run a 'BIO' node in different ways:
Z/IO/UV/UVStream.hs view
@@ -154,19 +154,6 @@ writeOutput (UVStream hdl _ uvm closed) buf len = mask_ $ do c <- readIORef closed when c throwECLOSED- m <- withUVManager' uvm $ do- reqSlot <- getUVSlot uvm (hs_uv_write hdl buf len)- m <- getBlockMVar uvm reqSlot- _ <- tryTakeMVar m- return m- -- we can't cancel uv_write_t with current libuv,- -- otherwise disaster will happen if buffer got collected.- -- so we have to turn to uninterruptibleMask_'s help.- -- i.e. writing UVStream is an uninterruptible operation.- -- OS will guarantee writing TTY and socket will not- -- hang forever anyway.- throwUVIfMinus_ (uninterruptibleMask_ $ takeMVar m)- {- wait for https://github.com/libuv/libuv/pull/2874 -- attempt blocking write first r <- hs_uv_try_write hdl buf len if | r == len -> return ()@@ -186,7 +173,6 @@ -- OS will guarantee writing TTY and socket will not -- hang forever anyway. throwUVIfMinus_ (uninterruptibleMask_ $ takeMVar m)- -} --------------------------------------------------------------------------------
third_party/libuv/include/uv.h view
@@ -126,6 +126,7 @@ XX(ENOTEMPTY, "directory not empty") \ XX(ENOTSOCK, "socket operation on non-socket") \ XX(ENOTSUP, "operation not supported on socket") \+ XX(EOVERFLOW, "value too large for defined data type") \ XX(EPERM, "operation not permitted") \ XX(EPIPE, "broken pipe") \ XX(EPROTO, "protocol error") \@@ -148,6 +149,7 @@ XX(ENOTTY, "inappropriate ioctl for device") \ XX(EFTYPE, "inappropriate file type or format") \ XX(EILSEQ, "illegal byte sequence") \+ XX(ESOCKTNOSUPPORT, "socket type not supported") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \@@ -475,6 +477,12 @@ UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len); +UV_EXTERN int uv_pipe(uv_file fds[2], int read_flags, int write_flags);+UV_EXTERN int uv_socketpair(int type,+ int protocol,+ uv_os_sock_t socket_vector[2],+ int flags0,+ int flags1); #define UV_STREAM_FIELDS \ /* number of bytes queued for writing */ \@@ -520,6 +528,10 @@ UV_EXTERN int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs);+UV_EXTERN int uv_try_write2(uv_stream_t* handle,+ const uv_buf_t bufs[],+ unsigned int nbufs,+ uv_stream_t* send_handle); /* uv_write_t is a subclass of uv_req_t. */ struct uv_write_s {@@ -620,8 +632,15 @@ * in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL. */ UV_UDP_MMSG_FREE = 16,- /*+ * Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.+ * This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on+ * Linux. This stops the Linux kernel from suppressing some ICMP error+ * messages and enables full ICMP error reporting for faster failover.+ * This flag is no-op on platforms other than Linux.+ */+ UV_UDP_LINUX_RECVERR = 32,+ /* * Indicates that recvmmsg should be used, if available. */ UV_UDP_RECVMMSG = 256@@ -933,10 +952,13 @@ UV_WRITABLE_PIPE = 0x20, /*- * Open the child pipe handle in overlapped mode on Windows.- * On Unix it is silently ignored.+ * When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the+ * handle in non-blocking mode in the child. This may cause loss of data,+ * if the child is not designed to handle to encounter this mode,+ * but can also be significantly more efficient. */- UV_OVERLAPPED_PIPE = 0x40+ UV_NONBLOCK_PIPE = 0x40,+ UV_OVERLAPPED_PIPE = 0x40 /* old name, for compatibility */ } uv_stdio_flags; typedef struct uv_stdio_container_s {
third_party/libuv/include/uv/errno.h view
@@ -445,4 +445,16 @@ # define UV__EILSEQ (-4027) #endif +#if defined(EOVERFLOW) && !defined(_WIN32)+# define UV__EOVERFLOW UV__ERR(EOVERFLOW)+#else+# define UV__EOVERFLOW (-4026)+#endif++#if defined(ESOCKTNOSUPPORT) && !defined(_WIN32)+# define UV__ESOCKTNOSUPPORT UV__ERR(ESOCKTNOSUPPORT)+#else+# define UV__ESOCKTNOSUPPORT (-4025)+#endif+ #endif /* UV_ERRNO_H_ */
third_party/libuv/include/uv/tree.h view
@@ -251,7 +251,7 @@ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \ __left = __right = &__node; \ \- while (1) { \+ for (;;) { \ if (__comp < 0) { \ __tmp = SPLAY_LEFT((head)->sph_root, field); \ if (__tmp == NULL) \
third_party/libuv/include/uv/version.h view
@@ -31,7 +31,7 @@ */ #define UV_VERSION_MAJOR 1-#define UV_VERSION_MINOR 40+#define UV_VERSION_MINOR 42 #define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 0 #define UV_VERSION_SUFFIX "dev"
third_party/libuv/src/idna.c view
@@ -19,6 +19,7 @@ #include "uv.h" #include "idna.h"+#include <assert.h> #include <string.h> static unsigned uv__utf8_decode1_slow(const char** p,@@ -32,7 +33,7 @@ if (a > 0xF7) return -1; - switch (*p - pe) {+ switch (pe - *p) { default: if (a > 0xEF) { min = 0x10000;@@ -62,6 +63,8 @@ a = 0; break; }+ /* Fall through. */+ case 0: return -1; /* Invalid continuation byte. */ } @@ -88,6 +91,8 @@ unsigned uv__utf8_decode1(const char** p, const char* pe) { unsigned a; + assert(*p < pe);+ a = (unsigned char) *(*p)++; if (a < 128)@@ -96,9 +101,6 @@ return uv__utf8_decode1_slow(p, pe, a); } -#define foreach_codepoint(c, p, pe) \- for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;)- static int uv__idna_toascii_label(const char* s, const char* se, char** d, char* de) { static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";@@ -121,15 +123,22 @@ ss = s; todo = 0; - foreach_codepoint(c, &s, se) {+ /* Note: after this loop we've visited all UTF-8 characters and know+ * they're legal so we no longer need to check for decode errors.+ */+ while (s < se) {+ c = uv__utf8_decode1(&s, se);++ if (c == -1u)+ return UV_EINVAL;+ if (c < 128) h++;- else if (c == (unsigned) -1)- return UV_EINVAL; else todo++; } + /* Only write "xn--" when there are non-ASCII characters. */ if (todo > 0) { if (*d < de) *(*d)++ = 'x'; if (*d < de) *(*d)++ = 'n';@@ -137,9 +146,13 @@ if (*d < de) *(*d)++ = '-'; } + /* Write ASCII characters. */ x = 0; s = ss;- foreach_codepoint(c, &s, se) {+ while (s < se) {+ c = uv__utf8_decode1(&s, se);+ assert(c != -1u);+ if (c > 127) continue; @@ -166,10 +179,15 @@ while (todo > 0) { m = -1; s = ss;- foreach_codepoint(c, &s, se)++ while (s < se) {+ c = uv__utf8_decode1(&s, se);+ assert(c != -1u);+ if (c >= n) if (c < m) m = c;+ } x = m - n; y = h + 1;@@ -181,7 +199,10 @@ n = m; s = ss;- foreach_codepoint(c, &s, se) {+ while (s < se) {+ c = uv__utf8_decode1(&s, se);+ assert(c != -1u);+ if (c < n) if (++delta == 0) return UV_E2BIG; /* Overflow. */@@ -245,8 +266,6 @@ return 0; } -#undef foreach_codepoint- long uv__idna_toascii(const char* s, const char* se, char* d, char* de) { const char* si; const char* st;@@ -256,9 +275,13 @@ ds = d; - for (si = s; si < se; /* empty */) {+ si = s;+ while (si < se) { st = si; c = uv__utf8_decode1(&si, se);++ if (c == -1u)+ return UV_EINVAL; if (c != '.') if (c != 0x3002) /* 。 */
third_party/libuv/src/inet.c view
@@ -141,8 +141,9 @@ if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words)) *tp++ = ':'; *tp++ = '\0';- if (UV_E2BIG == uv__strscpy(dst, tmp, size))+ if ((size_t) (tp - tmp) > size) return UV_ENOSPC;+ uv__strscpy(dst, tmp, size); return 0; }
third_party/libuv/src/threadpool.c view
@@ -161,7 +161,6 @@ void uv__threadpool_cleanup(void) {-#ifndef _WIN32 unsigned int i; if (nthreads == 0)@@ -181,7 +180,6 @@ threads = NULL; nthreads = 0;-#endif }
third_party/libuv/src/timer.c view
@@ -58,6 +58,7 @@ 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->timeout = 0; handle->repeat = 0; return 0; }
third_party/libuv/src/unix/async.c view
@@ -214,7 +214,7 @@ pipefd[0] = err; pipefd[1] = -1; #else- err = uv__make_pipe(pipefd, UV__F_NONBLOCK);+ err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE); if (err < 0) return err; #endif
third_party/libuv/src/unix/atomic-ops.h view
@@ -52,9 +52,11 @@ UV_UNUSED(static void cpu_relax(void)) { #if defined(__i386__) || defined(__x86_64__)- __asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */+ __asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */ #elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)- __asm__ volatile("yield");+ __asm__ __volatile__ ("yield" ::: "memory");+#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)+ __asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory"); #endif }
third_party/libuv/src/unix/bsd-ifaddrs.c view
@@ -42,8 +42,8 @@ return 1; #if !defined(__CYGWIN__) && !defined(__MSYS__) /*- * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, just see whether `sa_family`- * equals to `AF_LINK` or not. Otherwise, the result depends on the operation+ * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family`+ * equals `AF_LINK`. Otherwise, the result depends on the operating * system with `AF_LINK` or `PF_INET`. */ if (exclude_type == UV__EXCLUDE_IFPHYS)@@ -53,7 +53,7 @@ defined(__HAIKU__) /* * On BSD getifaddrs returns information related to the raw underlying- * devices. We're not interested in this information.+ * devices. We're not interested in this information. */ if (ent->ifa_addr->sa_family == AF_LINK) return 1;
third_party/libuv/src/unix/core.c view
@@ -88,6 +88,10 @@ # define uv__accept4 accept4 #endif +#if defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__)+# include <sanitizer/linux_syscall_hooks.h>+#endif+ static int uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */@@ -539,7 +543,13 @@ return close$NOCANCEL$UNIX2003(fd); #endif #pragma GCC diagnostic pop-#elif defined(__linux__)+#elif defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__)+ long rc;+ __sanitizer_syscall_pre_close(fd);+ rc = syscall(SYS_close, fd);+ __sanitizer_syscall_post_close(rc, fd);+ return rc;+#elif defined(__linux__) && !defined(__SANITIZE_THREAD__) return syscall(SYS_close, fd); #else return close(fd);@@ -574,7 +584,7 @@ return uv__close_nocheckstdio(fd); } -+#if UV__NONBLOCK_IS_IOCTL int uv__nonblock_ioctl(int fd, int set) { int r; @@ -589,7 +599,6 @@ } -#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__) int uv__cloexec_ioctl(int fd, int set) { int r; @@ -925,13 +934,12 @@ if (w->pevents == 0) { QUEUE_REMOVE(&w->watcher_queue); QUEUE_INIT(&w->watcher_queue);+ w->events = 0; - if (loop->watchers[w->fd] != NULL) {- assert(loop->watchers[w->fd] == w);+ if (w == loop->watchers[w->fd]) { assert(loop->nfds > 0); loop->watchers[w->fd] = NULL; loop->nfds--;- w->events = 0; } } else if (QUEUE_EMPTY(&w->watcher_queue))@@ -1175,7 +1183,9 @@ if (buf == NULL) return UV_ENOMEM; - r = getpwuid_r(uid, &pw, buf, bufsize, &result);+ do+ r = getpwuid_r(uid, &pw, buf, bufsize, &result);+ while (r == EINTR); if (r != ERANGE) break;@@ -1185,7 +1195,7 @@ if (r != 0) { uv__free(buf);- return -r;+ return UV__ERR(r); } if (result == NULL) {@@ -1571,7 +1581,7 @@ buf[*buflen] = '\0'; return 0;- } + } /* Case iii). Search PATH environment variable */ cloned_path = NULL;
third_party/libuv/src/unix/darwin.c view
@@ -33,9 +33,7 @@ #include <sys/sysctl.h> #include <unistd.h> /* sysconf */ -#if !TARGET_OS_IPHONE #include "darwin-stub.h"-#endif static uv_once_t once = UV_ONCE_INIT; static uint64_t (*time_func)(void);@@ -223,10 +221,10 @@ err = UV_ENOENT; core_foundation_handle = dlopen("/System/Library/Frameworks/" "CoreFoundation.framework/"- "Versions/A/CoreFoundation",+ "CoreFoundation", RTLD_LAZY | RTLD_LOCAL); iokit_handle = dlopen("/System/Library/Frameworks/IOKit.framework/"- "Versions/A/IOKit",+ "IOKit", RTLD_LAZY | RTLD_LOCAL); if (core_foundation_handle == NULL || iokit_handle == NULL)@@ -304,6 +302,12 @@ pIOObjectRelease(it); err = 0;++ if (device_type_str != NULL)+ pCFRelease(device_type_str);+ if (clock_frequency_str != NULL)+ pCFRelease(clock_frequency_str);+ out: if (core_foundation_handle != NULL) dlclose(core_foundation_handle);
+ third_party/libuv/src/unix/epoll.c view
@@ -0,0 +1,422 @@+/* Copyright libuv 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 <errno.h>+#include <sys/epoll.h>++int uv__epoll_init(uv_loop_t* loop) {+ int fd;+ fd = epoll_create1(O_CLOEXEC);++ /* epoll_create1() can fail either because it's not implemented (old kernel)+ * or because it doesn't understand the O_CLOEXEC flag.+ */+ if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {+ fd = epoll_create(256);++ if (fd != -1)+ uv__cloexec(fd, 1);+ }++ loop->backend_fd = fd;+ if (fd == -1)+ return UV__ERR(errno);++ return 0;+}+++void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {+ struct epoll_event* events;+ struct epoll_event dummy;+ uintptr_t i;+ uintptr_t nfds;++ assert(loop->watchers != NULL);+ assert(fd >= 0);++ events = (struct epoll_event*) loop->watchers[loop->nwatchers];+ nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];+ if (events != NULL)+ /* Invalidate events with same file descriptor */+ for (i = 0; i < nfds; i++)+ if (events[i].data.fd == fd)+ events[i].data.fd = -1;++ /* Remove the file descriptor from the epoll.+ * This avoids a problem where the same file description remains open+ * in another process, causing repeated junk epoll events.+ *+ * We pass in a dummy epoll_event, to work around a bug in old kernels.+ */+ if (loop->backend_fd >= 0) {+ /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that+ * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.+ */+ memset(&dummy, 0, sizeof(dummy));+ epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);+ }+}+++int uv__io_check_fd(uv_loop_t* loop, int fd) {+ struct epoll_event e;+ int rc;++ memset(&e, 0, sizeof(e));+ e.events = POLLIN;+ e.data.fd = -1;++ rc = 0;+ if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))+ if (errno != EEXIST)+ rc = UV__ERR(errno);++ if (rc == 0)+ if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))+ abort();++ return rc;+}+++void uv__io_poll(uv_loop_t* loop, int timeout) {+ /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes+ * effectively infinite on 32 bits architectures. To avoid blocking+ * indefinitely, we cap the timeout and poll again if necessary.+ *+ * Note that "30 minutes" is a simplification because it depends on+ * the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200,+ * that being the largest value I have seen in the wild (and only once.)+ */+ static const int max_safe_timeout = 1789569;+ static int no_epoll_pwait_cached;+ static int no_epoll_wait_cached;+ int no_epoll_pwait;+ int no_epoll_wait;+ struct epoll_event events[1024];+ struct epoll_event* pe;+ struct epoll_event e;+ int real_timeout;+ QUEUE* q;+ uv__io_t* w;+ sigset_t sigset;+ uint64_t sigmask;+ uint64_t base;+ int have_signals;+ int nevents;+ int count;+ int nfds;+ int fd;+ int op;+ int i;+ int user_timeout;+ int reset_timeout;++ if (loop->nfds == 0) {+ assert(QUEUE_EMPTY(&loop->watcher_queue));+ return;+ }++ memset(&e, 0, sizeof(e));++ while (!QUEUE_EMPTY(&loop->watcher_queue)) {+ q = QUEUE_HEAD(&loop->watcher_queue);+ QUEUE_REMOVE(q);+ QUEUE_INIT(q);++ w = QUEUE_DATA(q, uv__io_t, watcher_queue);+ assert(w->pevents != 0);+ assert(w->fd >= 0);+ assert(w->fd < (int) loop->nwatchers);++ e.events = w->pevents;+ e.data.fd = w->fd;++ if (w->events == 0)+ op = EPOLL_CTL_ADD;+ else+ op = EPOLL_CTL_MOD;++ /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching+ * events, skip the syscall and squelch the events after epoll_wait().+ */+ if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {+ if (errno != EEXIST)+ abort();++ assert(op == EPOLL_CTL_ADD);++ /* We've reactivated a file descriptor that's been watched before. */+ if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))+ abort();+ }++ w->events = w->pevents;+ }++ sigmask = 0;+ if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {+ sigemptyset(&sigset);+ sigaddset(&sigset, SIGPROF);+ sigmask |= 1 << (SIGPROF - 1);+ }++ assert(timeout >= -1);+ base = loop->time;+ count = 48; /* Benchmarks suggest this gives the best throughput. */+ real_timeout = timeout;++ if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {+ reset_timeout = 1;+ user_timeout = timeout;+ timeout = 0;+ } else {+ reset_timeout = 0;+ user_timeout = 0;+ }++ /* You could argue there is a dependency between these two but+ * ultimately we don't care about their ordering with respect+ * to one another. Worst case, we make a few system calls that+ * could have been avoided because another thread already knows+ * they fail with ENOSYS. Hardly the end of the world.+ */+ no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached);+ no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached);++ for (;;) {+ /* 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);++ /* See the comment for max_safe_timeout for an explanation of why+ * this is necessary. Executive summary: kernel bug workaround.+ */+ if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)+ timeout = max_safe_timeout;++ if (sigmask != 0 && no_epoll_pwait != 0)+ if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))+ abort();++ if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {+ nfds = epoll_pwait(loop->backend_fd,+ events,+ ARRAY_SIZE(events),+ timeout,+ &sigset);+ if (nfds == -1 && errno == ENOSYS) {+ uv__store_relaxed(&no_epoll_pwait_cached, 1);+ no_epoll_pwait = 1;+ }+ } else {+ nfds = epoll_wait(loop->backend_fd,+ events,+ ARRAY_SIZE(events),+ timeout);+ if (nfds == -1 && errno == ENOSYS) {+ uv__store_relaxed(&no_epoll_wait_cached, 1);+ no_epoll_wait = 1;+ }+ }++ if (sigmask != 0 && no_epoll_pwait != 0)+ if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))+ abort();++ /* Update loop->time unconditionally. It's tempting to skip the update when+ * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the+ * operating system didn't reschedule our process while in the syscall.+ */+ SAVE_ERRNO(uv__update_time(loop));++ if (nfds == 0) {+ assert(timeout != -1);++ if (reset_timeout != 0) {+ timeout = user_timeout;+ reset_timeout = 0;+ }++ if (timeout == -1)+ continue;++ if (timeout == 0)+ return;++ /* We may have been inside the system call for longer than |timeout|+ * milliseconds so we need to update the timestamp to avoid drift.+ */+ goto update_timeout;+ }++ if (nfds == -1) {+ if (errno == ENOSYS) {+ /* epoll_wait() or epoll_pwait() failed, try the other system call. */+ assert(no_epoll_wait == 0 || no_epoll_pwait == 0);+ continue;+ }++ if (errno != EINTR)+ abort();++ if (reset_timeout != 0) {+ timeout = user_timeout;+ reset_timeout = 0;+ }++ if (timeout == -1)+ continue;++ if (timeout == 0)+ return;++ /* Interrupted by a signal. Update timeout and poll again. */+ goto update_timeout;+ }++ have_signals = 0;+ nevents = 0;++ {+ /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */+ union {+ struct epoll_event* events;+ uv__io_t* watchers;+ } x;++ x.events = events;+ assert(loop->watchers != NULL);+ loop->watchers[loop->nwatchers] = x.watchers;+ loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;+ }++ for (i = 0; i < nfds; i++) {+ pe = events + i;+ fd = pe->data.fd;++ /* Skip invalidated events, see uv__platform_invalidate_fd */+ if (fd == -1)+ continue;++ assert(fd >= 0);+ assert((unsigned) fd < loop->nwatchers);++ w = loop->watchers[fd];++ if (w == NULL) {+ /* File descriptor that we've stopped watching, disarm it.+ *+ * Ignore all errors because we may be racing with another thread+ * when the file descriptor is closed.+ */+ epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);+ continue;+ }++ /* Give users only events they're interested in. Prevents spurious+ * callbacks when previous callback invocation in this loop has stopped+ * the current watcher. Also, filters out events that users has not+ * requested us to watch.+ */+ pe->events &= w->pevents | POLLERR | POLLHUP;++ /* Work around an epoll quirk where it sometimes reports just the+ * EPOLLERR or EPOLLHUP event. In order to force the event loop to+ * move forward, we merge in the read/write events that the watcher+ * is interested in; uv__read() and uv__write() will then deal with+ * the error or hangup in the usual fashion.+ *+ * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user+ * reads the available data, calls uv_read_stop(), then sometime later+ * calls uv_read_start() again. By then, libuv has forgotten about the+ * hangup and the kernel won't report EPOLLIN again because there's+ * nothing left to read. If anything, libuv is to blame here. The+ * current hack is just a quick bandaid; to properly fix it, libuv+ * needs to remember the error/hangup event. We should get that for+ * free when we switch over to edge-triggered I/O.+ */+ if (pe->events == POLLERR || pe->events == POLLHUP)+ pe->events |=+ w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);++ if (pe->events != 0) {+ /* Run signal watchers last. This also affects child process watchers+ * because those are implemented in terms of signal watchers.+ */+ if (w == &loop->signal_io_watcher) {+ have_signals = 1;+ } else {+ uv__metrics_update_idle_time(loop);+ w->cb(loop, w, pe->events);+ }++ nevents++;+ }+ }++ if (reset_timeout != 0) {+ timeout = user_timeout;+ reset_timeout = 0;+ }++ if (have_signals != 0) {+ uv__metrics_update_idle_time(loop);+ loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);+ }++ loop->watchers[loop->nwatchers] = NULL;+ loop->watchers[loop->nwatchers + 1] = NULL;++ if (have_signals != 0)+ return; /* Event loop should cycle now so don't poll again. */++ if (nevents != 0) {+ if (nfds == ARRAY_SIZE(events) && --count != 0) {+ /* Poll for more events but don't block this time. */+ timeout = 0;+ continue;+ }+ return;+ }++ if (timeout == 0)+ return;++ if (timeout == -1)+ continue;++update_timeout:+ assert(timeout > 0);++ real_timeout -= (loop->time - base);+ if (real_timeout <= 0)+ return;++ timeout = real_timeout;+ }+}+
third_party/libuv/src/unix/fs.c view
@@ -56,8 +56,13 @@ # define HAVE_PREADV 0 #endif +#if defined(__linux__)+# include "sys/utsname.h"+#endif+ #if defined(__linux__) || defined(__sun) # include <sys/sendfile.h>+# include <sys/sysmacros.h> #endif #if defined(__APPLE__)@@ -212,14 +217,30 @@ UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) { struct timespec ts; ts.tv_sec = time;- ts.tv_nsec = (uint64_t)(time * 1000000) % 1000000 * 1000;+ ts.tv_nsec = (time - ts.tv_sec) * 1e9;++ /* TODO(bnoordhuis) Remove this. utimesat() has nanosecond resolution but we+ * stick to microsecond resolution for the sake of consistency with other+ * platforms. I'm the original author of this compatibility hack but I'm+ * less convinced it's useful nowadays.+ */+ ts.tv_nsec -= ts.tv_nsec % 1000;++ if (ts.tv_nsec < 0) {+ ts.tv_nsec += 1e9;+ ts.tv_sec -= 1;+ } return ts; } UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) { struct timeval tv; tv.tv_sec = time;- tv.tv_usec = (uint64_t)(time * 1000000) % 1000000;+ tv.tv_usec = (time - tv.tv_sec) * 1e6;+ if (tv.tv_usec < 0) {+ tv.tv_usec += 1e6;+ tv.tv_sec -= 1;+ } return tv; } @@ -227,9 +248,6 @@ #if defined(__linux__) \ || defined(_AIX71) \ || defined(__HAIKU__)- /* utimesat() has nanosecond resolution but we stick to microseconds- * for the sake of consistency with other platforms.- */ struct timespec ts[2]; ts[0] = uv__fs_to_timespec(req->atime); ts[1] = uv__fs_to_timespec(req->mtime);@@ -887,6 +905,50 @@ } +#ifdef __linux__+static unsigned uv__kernel_version(void) {+ static unsigned cached_version;+ struct utsname u;+ unsigned version;+ unsigned major;+ unsigned minor;+ unsigned patch;++ version = uv__load_relaxed(&cached_version);+ if (version != 0)+ return version;++ if (-1 == uname(&u))+ return 0;++ if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch))+ return 0;++ version = major * 65536 + minor * 256 + patch;+ uv__store_relaxed(&cached_version, version);++ return version;+}+++/* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command+ * in copy_file_range() when it shouldn't. There is no workaround except to+ * fall back to a regular copy.+ */+static int uv__is_buggy_cephfs(int fd) {+ struct statfs s;++ if (-1 == fstatfs(fd, &s))+ return 0;++ if (s.f_type != /* CephFS */ 0xC36400)+ return 0;++ return uv__kernel_version() < /* 4.20.0 */ 0x041400;+}+#endif /* __linux__ */++ static ssize_t uv__fs_sendfile(uv_fs_t* req) { int in_fd; int out_fd;@@ -903,14 +965,25 @@ #ifdef __linux__ {- static int copy_file_range_support = 1;+ static int no_copy_file_range_support; - if (copy_file_range_support) {- r = uv__fs_copy_file_range(in_fd, NULL, out_fd, &off, req->bufsml[0].len, 0);+ if (uv__load_relaxed(&no_copy_file_range_support) == 0) {+ r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0); if (r == -1 && errno == ENOSYS) {+ /* ENOSYS - it will never work */ errno = 0;- copy_file_range_support = 0;+ uv__store_relaxed(&no_copy_file_range_support, 1);+ } else if (r == -1 && errno == EACCES && uv__is_buggy_cephfs(in_fd)) {+ /* EACCES - pre-4.20 kernels have a bug where CephFS uses the RADOS+ copy-from command when it shouldn't */+ errno = 0;+ uv__store_relaxed(&no_copy_file_range_support, 1);+ } else if (r == -1 && (errno == ENOTSUP || errno == EXDEV)) {+ /* ENOTSUP - it could work on another file system type */+ /* EXDEV - it will not work when in_fd and out_fd are not on the same+ mounted filesystem (pre Linux 5.3) */+ errno = 0; } else { goto ok; }@@ -1010,9 +1083,6 @@ || defined(_AIX71) \ || defined(__sun) \ || defined(__HAIKU__)- /* utimesat() has nanosecond resolution but we stick to microseconds- * for the sake of consistency with other platforms.- */ struct timespec ts[2]; ts[0] = uv__fs_to_timespec(req->atime); ts[1] = uv__fs_to_timespec(req->mtime);@@ -1220,7 +1290,7 @@ if (fstatfs(dstfd, &s) == -1) goto out; - if (s.f_type != /* CIFS */ 0xFF534D42u)+ if ((unsigned) s.f_type != /* CIFS */ 0xFF534D42u) goto out; } @@ -1340,7 +1410,8 @@ dst->st_birthtim.tv_nsec = src->st_ctimensec; dst->st_flags = 0; dst->st_gen = 0;-#elif !defined(_AIX) && ( \+#elif !defined(_AIX) && \+ !defined(__MVS__) && ( \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ defined(__OpenBSD__) || \@@ -1420,8 +1491,9 @@ case -1: /* EPERM happens when a seccomp filter rejects the system call. * Has been observed with libseccomp < 2.3.3 and docker < 18.04.+ * EOPNOTSUPP is used on DVS exported filesystems */- if (errno != EINVAL && errno != EPERM && errno != ENOSYS)+ if (errno != EINVAL && errno != EPERM && errno != ENOSYS && errno != EOPNOTSUPP) return -1; /* Fall through. */ default:@@ -1434,12 +1506,12 @@ return UV_ENOSYS; } - buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;+ buf->st_dev = makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor); buf->st_mode = statxbuf.stx_mode; buf->st_nlink = statxbuf.stx_nlink; buf->st_uid = statxbuf.stx_uid; buf->st_gid = statxbuf.stx_gid;- buf->st_rdev = statxbuf.stx_rdev_major;+ buf->st_rdev = makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor); buf->st_ino = statxbuf.stx_ino; buf->st_size = statxbuf.stx_size; buf->st_blksize = statxbuf.stx_blksize;
third_party/libuv/src/unix/fsevents.c view
@@ -595,8 +595,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { CFRunLoopSourceContext ctx; uv__cf_loop_state_t* state;- pthread_attr_t attr_storage;- pthread_attr_t* attr;+ pthread_attr_t attr; int err; if (loop->cf_state != NULL)@@ -641,25 +640,19 @@ goto fail_signal_source_create; } - /* In the unlikely event that pthread_attr_init() fails, create the thread- * with the default stack size. We'll use a little more address space but- * that in itself is not a fatal error.- */- attr = &attr_storage;- if (pthread_attr_init(attr))- attr = NULL;+ if (pthread_attr_init(&attr))+ abort(); - if (attr != NULL)- if (pthread_attr_setstacksize(attr, 4 * PTHREAD_STACK_MIN))- abort();+ if (pthread_attr_setstacksize(&attr, uv__thread_stack_size()))+ abort(); loop->cf_state = state; /* uv_thread_t is an alias for pthread_t. */- err = UV__ERR(pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop));+ err = UV__ERR(pthread_create(&loop->cf_thread, &attr, uv__cf_loop_runner, loop)); - if (attr != NULL)- pthread_attr_destroy(attr);+ if (pthread_attr_destroy(&attr))+ abort(); if (err) goto fail_thread_create;
third_party/libuv/src/unix/getaddrinfo.c view
@@ -21,9 +21,6 @@ /* Expose glibc-specific EAI_* error codes. Needs to be defined before we * include any headers. */-#ifndef _GNU_SOURCE-# define _GNU_SOURCE-#endif #include "uv.h" #include "internal.h"
third_party/libuv/src/unix/internal.h view
@@ -62,6 +62,17 @@ # include <AvailabilityMacros.h> #endif +/*+ * Define common detection for active Thread Sanitizer+ * - clang uses __has_feature(thread_sanitizer)+ * - gcc-7+ uses __SANITIZE_THREAD__+ */+#if defined(__has_feature)+# if __has_feature(thread_sanitizer)+# define __SANITIZE_THREAD__ 1+# endif+#endif+ #if defined(PATH_MAX) # define UV__PATH_MAX PATH_MAX #else@@ -165,9 +176,11 @@ defined(__NetBSD__) #define uv__cloexec uv__cloexec_ioctl #define uv__nonblock uv__nonblock_ioctl+#define UV__NONBLOCK_IS_IOCTL 1 #else #define uv__cloexec uv__cloexec_fcntl #define uv__nonblock uv__nonblock_fcntl+#define UV__NONBLOCK_IS_IOCTL 0 #endif /* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute@@ -246,6 +259,7 @@ /* platform specific */ uint64_t uv__hrtime(uv_clocktype_t type); int uv__kqueue_init(uv_loop_t* loop);+int uv__epoll_init(uv_loop_t* loop); int uv__platform_loop_init(uv_loop_t* loop); void uv__platform_loop_delete(uv_loop_t* loop); void uv__platform_invalidate_fd(uv_loop_t* loop, int fd);@@ -261,6 +275,7 @@ void uv__process_close(uv_process_t* handle); void uv__stream_close(uv_stream_t* handle); void uv__tcp_close(uv_tcp_t* handle);+size_t uv__thread_stack_size(void); void uv__udp_close(uv_udp_t* handle); void uv__udp_finish_close(uv_udp_t* handle); uv_handle_type uv__handle_type(int fd);@@ -282,12 +297,6 @@ #define uv__stream_fd(handle) ((handle)->io_watcher.fd) #endif /* defined(__APPLE__) */ -#ifdef O_NONBLOCK-# define UV__F_NONBLOCK O_NONBLOCK-#else-# define UV__F_NONBLOCK 1-#endif- int uv__make_pipe(int fds[2], int flags); #if defined(__APPLE__)@@ -327,7 +336,8 @@ #if defined(__linux__) || \ defined(__FreeBSD__) || \- defined(__FreeBSD_kernel__)+ defined(__FreeBSD_kernel__) || \+ defined(__DragonFly__) #define HAVE_MMSG 1 struct uv__mmsghdr { struct msghdr msg_hdr;@@ -338,6 +348,12 @@ int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen); #else #define HAVE_MMSG 0+#endif++#if defined(__sun)+#if !defined(_POSIX_VERSION) || _POSIX_VERSION < 200809L+size_t strnlen(const char* s, size_t maxlen);+#endif #endif
third_party/libuv/src/unix/linux-core.c view
@@ -82,29 +82,12 @@ static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); static uint64_t read_cpufreq(unsigned int cpunum); - int uv__platform_loop_init(uv_loop_t* loop) {- int fd;- fd = epoll_create1(O_CLOEXEC);-- /* epoll_create1() can fail either because it's not implemented (old kernel)- * or because it doesn't understand the O_CLOEXEC flag.- */- if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {- fd = epoll_create(256);-- if (fd != -1)- uv__cloexec(fd, 1);- }-- loop->backend_fd = fd;+ loop->inotify_fd = -1; loop->inotify_watchers = NULL; - if (fd == -1)- return UV__ERR(errno);-- return 0;+ return uv__epoll_init(loop); } @@ -134,381 +117,7 @@ } -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {- struct epoll_event* events;- struct epoll_event dummy;- uintptr_t i;- uintptr_t nfds; - assert(loop->watchers != NULL);- assert(fd >= 0);-- events = (struct epoll_event*) loop->watchers[loop->nwatchers];- nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];- if (events != NULL)- /* Invalidate events with same file descriptor */- for (i = 0; i < nfds; i++)- if (events[i].data.fd == fd)- events[i].data.fd = -1;-- /* Remove the file descriptor from the epoll.- * This avoids a problem where the same file description remains open- * in another process, causing repeated junk epoll events.- *- * We pass in a dummy epoll_event, to work around a bug in old kernels.- */- if (loop->backend_fd >= 0) {- /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that- * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.- */- memset(&dummy, 0, sizeof(dummy));- epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);- }-}---int uv__io_check_fd(uv_loop_t* loop, int fd) {- struct epoll_event e;- int rc;-- memset(&e, 0, sizeof(e));- e.events = POLLIN;- e.data.fd = -1;-- rc = 0;- if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))- if (errno != EEXIST)- rc = UV__ERR(errno);-- if (rc == 0)- if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))- abort();-- return rc;-}---void uv__io_poll(uv_loop_t* loop, int timeout) {- /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes- * effectively infinite on 32 bits architectures. To avoid blocking- * indefinitely, we cap the timeout and poll again if necessary.- *- * Note that "30 minutes" is a simplification because it depends on- * the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200,- * that being the largest value I have seen in the wild (and only once.)- */- static const int max_safe_timeout = 1789569;- static int no_epoll_pwait_cached;- static int no_epoll_wait_cached;- int no_epoll_pwait;- int no_epoll_wait;- struct epoll_event events[1024];- struct epoll_event* pe;- struct epoll_event e;- int real_timeout;- QUEUE* q;- uv__io_t* w;- sigset_t sigset;- uint64_t sigmask;- uint64_t base;- int have_signals;- int nevents;- int count;- int nfds;- int fd;- int op;- int i;- int user_timeout;- int reset_timeout;-- if (loop->nfds == 0) {- assert(QUEUE_EMPTY(&loop->watcher_queue));- return;- }-- memset(&e, 0, sizeof(e));-- while (!QUEUE_EMPTY(&loop->watcher_queue)) {- q = QUEUE_HEAD(&loop->watcher_queue);- QUEUE_REMOVE(q);- QUEUE_INIT(q);-- w = QUEUE_DATA(q, uv__io_t, watcher_queue);- assert(w->pevents != 0);- assert(w->fd >= 0);- assert(w->fd < (int) loop->nwatchers);-- e.events = w->pevents;- e.data.fd = w->fd;-- if (w->events == 0)- op = EPOLL_CTL_ADD;- else- op = EPOLL_CTL_MOD;-- /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching- * events, skip the syscall and squelch the events after epoll_wait().- */- if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {- if (errno != EEXIST)- abort();-- assert(op == EPOLL_CTL_ADD);-- /* We've reactivated a file descriptor that's been watched before. */- if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))- abort();- }-- w->events = w->pevents;- }-- sigmask = 0;- if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {- sigemptyset(&sigset);- sigaddset(&sigset, SIGPROF);- sigmask |= 1 << (SIGPROF - 1);- }-- assert(timeout >= -1);- base = loop->time;- count = 48; /* Benchmarks suggest this gives the best throughput. */- real_timeout = timeout;-- if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {- reset_timeout = 1;- user_timeout = timeout;- timeout = 0;- } else {- reset_timeout = 0;- user_timeout = 0;- }-- /* You could argue there is a dependency between these two but- * ultimately we don't care about their ordering with respect- * to one another. Worst case, we make a few system calls that- * could have been avoided because another thread already knows- * they fail with ENOSYS. Hardly the end of the world.- */- no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached);- no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached);-- for (;;) {- /* 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);-- /* See the comment for max_safe_timeout for an explanation of why- * this is necessary. Executive summary: kernel bug workaround.- */- if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)- timeout = max_safe_timeout;-- if (sigmask != 0 && no_epoll_pwait != 0)- if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))- abort();-- if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {- nfds = epoll_pwait(loop->backend_fd,- events,- ARRAY_SIZE(events),- timeout,- &sigset);- if (nfds == -1 && errno == ENOSYS) {- uv__store_relaxed(&no_epoll_pwait_cached, 1);- no_epoll_pwait = 1;- }- } else {- nfds = epoll_wait(loop->backend_fd,- events,- ARRAY_SIZE(events),- timeout);- if (nfds == -1 && errno == ENOSYS) {- uv__store_relaxed(&no_epoll_wait_cached, 1);- no_epoll_wait = 1;- }- }-- if (sigmask != 0 && no_epoll_pwait != 0)- if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))- abort();-- /* Update loop->time unconditionally. It's tempting to skip the update when- * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the- * operating system didn't reschedule our process while in the syscall.- */- SAVE_ERRNO(uv__update_time(loop));-- if (nfds == 0) {- assert(timeout != -1);-- if (reset_timeout != 0) {- timeout = user_timeout;- reset_timeout = 0;- }-- if (timeout == -1)- continue;-- if (timeout == 0)- return;-- /* We may have been inside the system call for longer than |timeout|- * milliseconds so we need to update the timestamp to avoid drift.- */- goto update_timeout;- }-- if (nfds == -1) {- if (errno == ENOSYS) {- /* epoll_wait() or epoll_pwait() failed, try the other system call. */- assert(no_epoll_wait == 0 || no_epoll_pwait == 0);- continue;- }-- if (errno != EINTR)- abort();-- if (reset_timeout != 0) {- timeout = user_timeout;- reset_timeout = 0;- }-- if (timeout == -1)- continue;-- if (timeout == 0)- return;-- /* Interrupted by a signal. Update timeout and poll again. */- goto update_timeout;- }-- have_signals = 0;- nevents = 0;-- {- /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */- union {- struct epoll_event* events;- uv__io_t* watchers;- } x;-- x.events = events;- assert(loop->watchers != NULL);- loop->watchers[loop->nwatchers] = x.watchers;- loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;- }-- for (i = 0; i < nfds; i++) {- pe = events + i;- fd = pe->data.fd;-- /* Skip invalidated events, see uv__platform_invalidate_fd */- if (fd == -1)- continue;-- assert(fd >= 0);- assert((unsigned) fd < loop->nwatchers);-- w = loop->watchers[fd];-- if (w == NULL) {- /* File descriptor that we've stopped watching, disarm it.- *- * Ignore all errors because we may be racing with another thread- * when the file descriptor is closed.- */- epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);- continue;- }-- /* Give users only events they're interested in. Prevents spurious- * callbacks when previous callback invocation in this loop has stopped- * the current watcher. Also, filters out events that users has not- * requested us to watch.- */- pe->events &= w->pevents | POLLERR | POLLHUP;-- /* Work around an epoll quirk where it sometimes reports just the- * EPOLLERR or EPOLLHUP event. In order to force the event loop to- * move forward, we merge in the read/write events that the watcher- * is interested in; uv__read() and uv__write() will then deal with- * the error or hangup in the usual fashion.- *- * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user- * reads the available data, calls uv_read_stop(), then sometime later- * calls uv_read_start() again. By then, libuv has forgotten about the- * hangup and the kernel won't report EPOLLIN again because there's- * nothing left to read. If anything, libuv is to blame here. The- * current hack is just a quick bandaid; to properly fix it, libuv- * needs to remember the error/hangup event. We should get that for- * free when we switch over to edge-triggered I/O.- */- if (pe->events == POLLERR || pe->events == POLLHUP)- pe->events |=- w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);-- if (pe->events != 0) {- /* Run signal watchers last. This also affects child process watchers- * because those are implemented in terms of signal watchers.- */- if (w == &loop->signal_io_watcher) {- have_signals = 1;- } else {- uv__metrics_update_idle_time(loop);- w->cb(loop, w, pe->events);- }-- nevents++;- }- }-- if (reset_timeout != 0) {- timeout = user_timeout;- reset_timeout = 0;- }-- if (have_signals != 0) {- uv__metrics_update_idle_time(loop);- loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);- }-- loop->watchers[loop->nwatchers] = NULL;- loop->watchers[loop->nwatchers + 1] = NULL;-- if (have_signals != 0)- return; /* Event loop should cycle now so don't poll again. */-- if (nevents != 0) {- if (nfds == ARRAY_SIZE(events) && --count != 0) {- /* Poll for more events but don't block this time. */- timeout = 0;- continue;- }- return;- }-- if (timeout == 0)- return;-- if (timeout == -1)- continue;--update_timeout:- assert(timeout > 0);-- real_timeout -= (loop->time - base);- if (real_timeout <= 0)- return;-- timeout = real_timeout;- }-}-- uint64_t uv__hrtime(uv_clocktype_t type) { static clock_t fast_clock_id = -1; struct timespec t;@@ -602,22 +211,53 @@ return UV_EINVAL; } +static int uv__slurp(const char* filename, char* buf, size_t len) {+ ssize_t n;+ int fd; + assert(len > 0);++ fd = uv__open_cloexec(filename, O_RDONLY);+ if (fd < 0)+ return fd;++ do+ n = read(fd, buf, len - 1);+ while (n == -1 && errno == EINTR);++ if (uv__close_nocheckstdio(fd))+ abort();++ if (n < 0)+ return UV__ERR(errno);++ buf[n] = '\0';++ return 0;+}+ int uv_uptime(double* uptime) { static volatile int no_clock_boottime;+ char buf[128]; struct timespec now; int r; + /* Try /proc/uptime first, then fallback to clock_gettime(). */+ + if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf)))+ if (1 == sscanf(buf, "%lf", uptime))+ return 0;+ /* Try CLOCK_BOOTTIME first, fall back to CLOCK_MONOTONIC if not available * (pre-2.6.39 kernels). CLOCK_MONOTONIC doesn't increase when the system * is suspended. */ if (no_clock_boottime) {- retry: r = clock_gettime(CLOCK_MONOTONIC, &now);+ retry_clock_gettime: r = clock_gettime(CLOCK_MONOTONIC, &now); } else if ((r = clock_gettime(CLOCK_BOOTTIME, &now)) && errno == EINVAL) { no_clock_boottime = 1;- goto retry;+ goto retry_clock_gettime; } if (r)@@ -709,14 +349,19 @@ } -/* Also reads the CPU frequency on x86. The other architectures only have- * a BogoMIPS field, which may not be very accurate.+/* Also reads the CPU frequency on ppc and x86. The other architectures only+ * have a BogoMIPS field, which may not be very accurate. * * Note: Simply returns on error, uv_cpu_info() takes care of the cleanup. */ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {+#if defined(__PPC__)+ static const char model_marker[] = "cpu\t\t: ";+ static const char speed_marker[] = "clock\t\t: ";+#else static const char model_marker[] = "model name\t: "; static const char speed_marker[] = "cpu MHz\t\t: ";+#endif const char* inferred_model; unsigned int model_idx; unsigned int speed_idx;@@ -738,6 +383,7 @@ #if defined(__arm__) || \ defined(__i386__) || \ defined(__mips__) || \+ defined(__PPC__) || \ defined(__x86_64__) fp = uv__open_file("/proc/cpuinfo"); if (fp == NULL)@@ -786,7 +432,7 @@ } fclose(fp);-#endif /* __arm__ || __i386__ || __mips__ || __x86_64__ */+#endif /* __arm__ || __i386__ || __mips__ || __PPC__ || __x86_64__ */ /* Now we want to make sure that all the models contain *something* because * it's not safe to leave them as null. Copy the last entry unless there@@ -824,9 +470,9 @@ char buf[1024]; ticks = (unsigned int)sysconf(_SC_CLK_TCK);- multiplier = ((uint64_t)1000L / ticks); assert(ticks != (unsigned int) -1); assert(ticks != 0);+ multiplier = ((uint64_t)1000L / ticks); rewind(statfile_fp); @@ -1022,32 +668,6 @@ #if defined(PR_SET_NAME) prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */ #endif-}---static int uv__slurp(const char* filename, char* buf, size_t len) {- ssize_t n;- int fd;-- assert(len > 0);-- fd = uv__open_cloexec(filename, O_RDONLY);- if (fd < 0)- return fd;-- do- n = read(fd, buf, len - 1);- while (n == -1 && errno == EINTR);-- if (uv__close_nocheckstdio(fd))- abort();-- if (n < 0)- return UV__ERR(errno);-- buf[n] = '\0';-- return 0; }
third_party/libuv/src/unix/linux-inotify.c view
@@ -178,7 +178,7 @@ /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ char buf[4096]; - while (1) {+ for (;;) { do size = read(loop->inotify_fd, buf, sizeof(buf)); while (size == -1 && errno == EINTR);
third_party/libuv/src/unix/linux-syscalls.c view
@@ -194,37 +194,37 @@ ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {-#if defined(__NR_preadv)- return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));-#else+#if !defined(__NR_preadv) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 return errno = ENOSYS, -1;+#else+ return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); #endif } ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {-#if defined(__NR_pwritev)- return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));-#else+#if !defined(__NR_pwritev) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 return errno = ENOSYS, -1;+#else+ return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); #endif } int uv__dup3(int oldfd, int newfd, int flags) {-#if defined(__NR_dup3)- return syscall(__NR_dup3, oldfd, newfd, flags);-#else+#if !defined(__NR_dup3) || defined(__ANDROID_API__) && __ANDROID_API__ < 21 return errno = ENOSYS, -1;+#else+ return syscall(__NR_dup3, oldfd, newfd, flags); #endif } ssize_t uv__fs_copy_file_range(int fd_in,- ssize_t* off_in,+ off_t* off_in, int fd_out,- ssize_t* off_out,+ off_t* off_out, size_t len, unsigned int flags) {@@ -247,21 +247,18 @@ int flags, unsigned int mask, struct uv__statx* statxbuf) {- /* __NR_statx make Android box killed by SIGSYS.- * That looks like a seccomp2 sandbox filter rejecting the system call.- */-#if defined(__NR_statx) && !defined(__ANDROID__)- return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);-#else+#if !defined(__NR_statx) || defined(__ANDROID_API__) && __ANDROID_API__ < 30 return errno = ENOSYS, -1;+#else+ return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); #endif } ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) {-#if defined(__NR_getrandom)- return syscall(__NR_getrandom, buf, buflen, flags);-#else+#if !defined(__NR_getrandom) || defined(__ANDROID_API__) && __ANDROID_API__ < 28 return errno = ENOSYS, -1;+#else+ return syscall(__NR_getrandom, buf, buflen, flags); #endif }
third_party/libuv/src/unix/linux-syscalls.h view
@@ -22,9 +22,6 @@ #ifndef UV_LINUX_SYSCALL_H_ #define UV_LINUX_SYSCALL_H_ -#undef _GNU_SOURCE-#define _GNU_SOURCE- #include <stdint.h> #include <signal.h> #include <sys/types.h>@@ -66,9 +63,9 @@ int uv__dup3(int oldfd, int newfd, int flags); ssize_t uv__fs_copy_file_range(int fd_in,- ssize_t* off_in,+ off_t* off_in, int fd_out,- ssize_t* off_out,+ off_t* off_out, size_t len, unsigned int flags); int uv__statx(int dirfd,
third_party/libuv/src/unix/os390-syscalls.h view
@@ -28,6 +28,7 @@ #include <dirent.h> #include <poll.h> #include <pthread.h>+#include "zos-base.h" #define EPOLL_CTL_ADD 1 #define EPOLL_CTL_DEL 2@@ -57,7 +58,6 @@ int epoll_file_close(int fd); /* utility functions */-int nanosleep(const struct timespec* req, struct timespec* rem); int scandir(const char* maindir, struct dirent*** namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **,
third_party/libuv/src/unix/pipe.c view
@@ -379,3 +379,57 @@ return r != -1 ? 0 : UV__ERR(errno); }+++int uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) {+ uv_os_fd_t temp[2];+ int err;+#if defined(__FreeBSD__) || defined(__linux__)+ int flags = O_CLOEXEC;++ if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE))+ flags |= UV_FS_O_NONBLOCK;++ if (pipe2(temp, flags))+ return UV__ERR(errno);++ if (flags & UV_FS_O_NONBLOCK) {+ fds[0] = temp[0];+ fds[1] = temp[1];+ return 0;+ }+#else+ if (pipe(temp))+ return UV__ERR(errno);++ if ((err = uv__cloexec(temp[0], 1)))+ goto fail;++ if ((err = uv__cloexec(temp[1], 1)))+ goto fail;+#endif++ if (read_flags & UV_NONBLOCK_PIPE)+ if ((err = uv__nonblock(temp[0], 1)))+ goto fail;++ if (write_flags & UV_NONBLOCK_PIPE)+ if ((err = uv__nonblock(temp[1], 1)))+ goto fail;++ fds[0] = temp[0];+ fds[1] = temp[1];+ return 0;++fail:+ uv__close(temp[0]);+ uv__close(temp[1]);+ return err;+}+++int uv__make_pipe(int fds[2], int flags) {+ return uv_pipe(fds,+ flags & UV_NONBLOCK_PIPE,+ flags & UV_NONBLOCK_PIPE);+}
third_party/libuv/src/unix/poll.c view
@@ -79,9 +79,10 @@ * Workaround for e.g. kqueue fds not supporting ioctls. */ err = uv__nonblock(fd, 1);+#if UV__NONBLOCK_IS_IOCTL if (err == UV_ENOTTY)- if (uv__nonblock == uv__nonblock_ioctl)- err = uv__nonblock_fcntl(fd, 1);+ err = uv__nonblock_fcntl(fd, 1);+#endif if (err) return err;@@ -116,11 +117,20 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {+ uv__io_t** watchers;+ uv__io_t* w; int events; assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT | UV_PRIORITIZED)) == 0); assert(!uv__is_closing(handle));++ watchers = handle->loop->watchers;+ w = &handle->io_watcher;++ if (uv__fd_exists(handle->loop, w->fd))+ if (watchers[w->fd] != w)+ return UV_EEXIST; uv__poll_stop(handle);
third_party/libuv/src/unix/process.c view
@@ -44,7 +44,11 @@ # include <grp.h> #endif +#if defined(__MVS__)+# include "zos-base.h"+#endif + static void uv__chld(uv_signal_t* handle, int signum) { uv_process_t* process; uv_loop_t* loop;@@ -111,68 +115,6 @@ assert(QUEUE_EMPTY(&pending)); } --static int uv__make_socketpair(int fds[2]) {-#if defined(__FreeBSD__) || defined(__linux__)- if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds))- return UV__ERR(errno);-- return 0;-#else- int err;-- if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))- return UV__ERR(errno);-- err = uv__cloexec(fds[0], 1);- if (err == 0)- err = uv__cloexec(fds[1], 1);-- if (err != 0) {- uv__close(fds[0]);- uv__close(fds[1]);- return UV__ERR(errno);- }-- return 0;-#endif-}---int uv__make_pipe(int fds[2], int flags) {-#if defined(__FreeBSD__) || defined(__linux__)- if (pipe2(fds, flags | O_CLOEXEC))- return UV__ERR(errno);-- return 0;-#else- if (pipe(fds))- return UV__ERR(errno);-- if (uv__cloexec(fds[0], 1))- goto fail;-- if (uv__cloexec(fds[1], 1))- goto fail;-- if (flags & UV__F_NONBLOCK) {- if (uv__nonblock(fds[0], 1))- goto fail;-- if (uv__nonblock(fds[1], 1))- goto fail;- }-- return 0;--fail:- uv__close(fds[0]);- uv__close(fds[1]);- return UV__ERR(errno);-#endif-}-- /* * Used for initializing stdio streams like options.stdin_stream. Returns * zero on success. See also the cleanup section in uv_spawn().@@ -192,7 +134,7 @@ if (container->data.stream->type != UV_NAMED_PIPE) return UV_EINVAL; else- return uv__make_socketpair(fds);+ return uv_socketpair(SOCK_STREAM, 0, fds, 0, 0); case UV_INHERIT_FD: case UV_INHERIT_STREAM:@@ -259,6 +201,12 @@ } +static void uv__write_errno(int error_fd) {+ uv__write_int(error_fd, UV__ERR(errno));+ _exit(127);+}++ #if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) /* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be * avoided. Since this isn't called on those targets, the function@@ -287,10 +235,8 @@ if (use_fd < 0 || use_fd >= fd) continue; pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);- if (pipes[fd][1] == -1) {- uv__write_int(error_fd, UV__ERR(errno));- _exit(127);- }+ if (pipes[fd][1] == -1)+ uv__write_errno(error_fd); } for (fd = 0; fd < stdio_count; fd++) {@@ -307,10 +253,8 @@ use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); close_fd = use_fd; - if (use_fd < 0) {- uv__write_int(error_fd, UV__ERR(errno));- _exit(127);- }+ if (use_fd < 0)+ uv__write_errno(error_fd); } } @@ -319,10 +263,8 @@ else fd = dup2(use_fd, fd); - if (fd == -1) {- uv__write_int(error_fd, UV__ERR(errno));- _exit(127);- }+ if (fd == -1)+ uv__write_errno(error_fd); if (fd <= 2) uv__nonblock_fcntl(fd, 0);@@ -338,10 +280,8 @@ uv__close(use_fd); } - if (options->cwd != NULL && chdir(options->cwd)) {- uv__write_int(error_fd, UV__ERR(errno));- _exit(127);- }+ if (options->cwd != NULL && chdir(options->cwd))+ uv__write_errno(error_fd); if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) { /* When dropping privileges from root, the `setgroups` call will@@ -354,15 +294,11 @@ SAVE_ERRNO(setgroups(0, NULL)); } - if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {- uv__write_int(error_fd, UV__ERR(errno));- _exit(127);- }+ if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid))+ uv__write_errno(error_fd); - if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {- uv__write_int(error_fd, UV__ERR(errno));- _exit(127);- }+ if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid))+ uv__write_errno(error_fd); if (options->env != NULL) { environ = options->env;@@ -385,22 +321,23 @@ if (SIG_ERR != signal(n, SIG_DFL)) continue; - uv__write_int(error_fd, UV__ERR(errno));- _exit(127);+ uv__write_errno(error_fd); } /* Reset signal mask. */ sigemptyset(&set); err = pthread_sigmask(SIG_SETMASK, &set, NULL); - if (err != 0) {- uv__write_int(error_fd, UV__ERR(err));- _exit(127);- }+ if (err != 0)+ uv__write_errno(error_fd); +#ifdef __MVS__+ execvpe(options->file, options->args, environ);+#else execvp(options->file, options->args);- uv__write_int(error_fd, UV__ERR(errno));- _exit(127);+#endif++ uv__write_errno(error_fd); } #endif
third_party/libuv/src/unix/proctitle.c view
@@ -84,10 +84,7 @@ } new_argv[i] = NULL; - /* argv is not adjacent on z/os, we use just argv[0] on that platform. */-#ifndef __MVS__ pt.cap = argv[i - 1] + size - argv[0];-#endif args_mem = new_argv; process_title = pt;@@ -119,6 +116,7 @@ memcpy(pt->str, title, len); memset(pt->str + len, '\0', pt->cap - len); pt->len = len;+ uv__set_process_title(pt->str); uv_mutex_unlock(&process_title_mutex);
third_party/libuv/src/unix/signal.c view
@@ -265,7 +265,7 @@ if (loop->signal_pipefd[0] != -1) return 0; - err = uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK);+ err = uv__make_pipe(loop->signal_pipefd, UV_NONBLOCK_PIPE); if (err) return err;
third_party/libuv/src/unix/stream.c view
@@ -164,7 +164,7 @@ else max_fd = s->int_fd; - while (1) {+ for (;;) { /* Terminate on semaphore */ if (uv_sem_trywait(&s->close_sem) == 0) break;@@ -195,7 +195,7 @@ /* Empty socketpair's buffer in case of interruption */ if (FD_ISSET(s->int_fd, s->sread))- while (1) {+ for (;;) { r = read(s->int_fd, buf, sizeof(buf)); if (r == sizeof(buf))@@ -799,33 +799,21 @@ } } -static void uv__write(uv_stream_t* stream) {+static int uv__try_write(uv_stream_t* stream,+ const uv_buf_t bufs[],+ unsigned int nbufs,+ uv_stream_t* send_handle) { struct iovec* iov;- QUEUE* q;- uv_write_t* req; int iovmax; int iovcnt; ssize_t n;- int err; -start:-- assert(uv__stream_fd(stream) >= 0);-- if (QUEUE_EMPTY(&stream->write_queue))- return;-- q = QUEUE_HEAD(&stream->write_queue);- req = QUEUE_DATA(q, uv_write_t, queue);- assert(req->handle == stream);- /* * Cast to iovec. We had to have our own uv_buf_t instead of iovec * because Windows's WSABUF is not an iovec. */- assert(sizeof(uv_buf_t) == sizeof(struct iovec));- iov = (struct iovec*) &(req->bufs[req->write_index]);- iovcnt = req->nbufs - req->write_index;+ iov = (struct iovec*) bufs;+ iovcnt = nbufs; iovmax = uv__getiovmax(); @@ -837,8 +825,7 @@ * Now do the actual writev. Note that we've been updating the pointers * inside the iov each time we write. So there is no need to offset it. */-- if (req->send_handle) {+ if (send_handle != NULL) { int fd_to_send; struct msghdr msg; struct cmsghdr *cmsg;@@ -847,12 +834,10 @@ struct cmsghdr alias; } scratch; - if (uv__is_closing(req->send_handle)) {- err = UV_EBADF;- goto error;- }+ if (uv__is_closing(send_handle))+ return UV_EBADF; - fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);+ fd_to_send = uv__handle_fd((uv_handle_t*) send_handle); memset(&scratch, 0, sizeof(scratch)); @@ -882,44 +867,68 @@ do n = sendmsg(uv__stream_fd(stream), &msg, 0); while (n == -1 && RETRY_ON_WRITE_ERROR(errno));-- /* Ensure the handle isn't sent again in case this is a partial write. */- if (n >= 0)- req->send_handle = NULL; } else { do n = uv__writev(uv__stream_fd(stream), iov, iovcnt); while (n == -1 && RETRY_ON_WRITE_ERROR(errno)); } - if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) {- err = UV__ERR(errno);- goto error;- }+ if (n >= 0)+ return n; - if (n >= 0 && uv__write_req_update(stream, req, n)) {- uv__write_req_finish(req);- return; /* TODO(bnoordhuis) Start trying to write the next request. */- }+ if (IS_TRANSIENT_WRITE_ERROR(errno, send_handle))+ return UV_EAGAIN; - /* If this is a blocking stream, try again. */- if (stream->flags & UV_HANDLE_BLOCKING_WRITES)- goto start;+ return UV__ERR(errno);+} - /* We're not done. */- uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);+static void uv__write(uv_stream_t* stream) {+ QUEUE* q;+ uv_write_t* req;+ ssize_t n; - /* Notify select() thread about state change */- uv__stream_osx_interrupt_select(stream);+ assert(uv__stream_fd(stream) >= 0); - return;+ for (;;) {+ if (QUEUE_EMPTY(&stream->write_queue))+ return; -error:- req->error = err;+ q = QUEUE_HEAD(&stream->write_queue);+ req = QUEUE_DATA(q, uv_write_t, queue);+ assert(req->handle == stream);++ n = uv__try_write(stream,+ &(req->bufs[req->write_index]),+ req->nbufs - req->write_index,+ req->send_handle);++ /* Ensure the handle isn't sent again in case this is a partial write. */+ if (n >= 0) {+ req->send_handle = NULL;+ if (uv__write_req_update(stream, req, n)) {+ uv__write_req_finish(req);+ return; /* TODO(bnoordhuis) Start trying to write the next request. */+ }+ } else if (n != UV_EAGAIN)+ break;++ /* If this is a blocking stream, try again. */+ if (stream->flags & UV_HANDLE_BLOCKING_WRITES)+ continue;++ /* We're not done. */+ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);++ /* Notify select() thread about state change */+ uv__stream_osx_interrupt_select(stream);++ return;+ }++ req->error = n;+ // XXX(jwn): this must call uv__stream_flush_write_queue(stream, n) here, since we won't generate any more events uv__write_req_finish(req); uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);- if (!uv__io_active(&stream->io_watcher, POLLIN))- uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); } @@ -1001,9 +1010,9 @@ static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { stream->flags |= UV_HANDLE_READ_EOF; stream->flags &= ~UV_HANDLE_READING;+ stream->flags &= ~UV_HANDLE_READABLE; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);- if (!uv__io_active(&stream->io_watcher, POLLOUT))- uv__handle_stop(stream);+ uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); stream->read_cb(stream, UV_EOF, buf); }@@ -1188,12 +1197,12 @@ #endif } else { /* Error. User should call uv_close(). */+ stream->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); stream->read_cb(stream, UV__ERR(errno), &buf); if (stream->flags & UV_HANDLE_READING) { stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);- if (!uv__io_active(&stream->io_watcher, POLLOUT))- uv__handle_stop(stream);+ uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); } }@@ -1276,6 +1285,7 @@ req->cb = cb; stream->shutdown_req = req; stream->flags |= UV_HANDLE_SHUTTING;+ stream->flags &= ~UV_HANDLE_WRITABLE; uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream);@@ -1390,14 +1400,9 @@ } -int uv_write2(uv_write_t* req,- uv_stream_t* stream,- const uv_buf_t bufs[],- unsigned int nbufs,- uv_stream_t* send_handle,- uv_write_cb cb) {- int empty_queue;-+static int uv__check_before_write(uv_stream_t* stream,+ unsigned int nbufs,+ uv_stream_t* send_handle) { assert(nbufs > 0); assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||@@ -1410,7 +1415,7 @@ if (!(stream->flags & UV_HANDLE_WRITABLE)) return UV_EPIPE; - if (send_handle) {+ if (send_handle != NULL) { if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc) return UV_EINVAL; @@ -1430,6 +1435,22 @@ #endif } + return 0;+}++int uv_write2(uv_write_t* req,+ uv_stream_t* stream,+ const uv_buf_t bufs[],+ unsigned int nbufs,+ uv_stream_t* send_handle,+ uv_write_cb cb) {+ int empty_queue;+ int err;++ err = uv__check_before_write(stream, nbufs, send_handle);+ if (err < 0)+ return err;+ /* It's legal for write_queue_size > 0 even when the write_queue is empty; * it means there are error-state requests in the write_completed_queue that * will touch up write_queue_size later, see also uv__write_req_finish().@@ -1498,72 +1519,37 @@ } -void uv_try_write_cb(uv_write_t* req, int status) {- /* Should not be called */- abort();-}-- int uv_try_write(uv_stream_t* stream, const uv_buf_t bufs[], unsigned int nbufs) {- int r;- int has_pollout;- size_t written;- size_t req_size;- uv_write_t req;+ return uv_try_write2(stream, bufs, nbufs, NULL);+} ++int uv_try_write2(uv_stream_t* stream,+ const uv_buf_t bufs[],+ unsigned int nbufs,+ uv_stream_t* send_handle) {+ int err;+ /* Connecting or already writing some data */ if (stream->connect_req != NULL || stream->write_queue_size != 0) return UV_EAGAIN; - has_pollout = uv__io_active(&stream->io_watcher, POLLOUT);-- r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb);- if (r != 0)- return r;-- /* Remove not written bytes from write queue size */- written = uv__count_bufs(bufs, nbufs);- if (req.bufs != NULL)- req_size = uv__write_req_size(&req);- else- req_size = 0;- written -= req_size;- stream->write_queue_size -= req_size;-- /* Unqueue request, regardless of immediateness */- QUEUE_REMOVE(&req.queue);- uv__req_unregister(stream->loop, &req);- if (req.bufs != req.bufsml)- uv__free(req.bufs);- req.bufs = NULL;-- /* Do not poll for writable, if we wasn't before calling this */- if (!has_pollout) {- uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);- uv__stream_osx_interrupt_select(stream);- }+ err = uv__check_before_write(stream, nbufs, NULL);+ if (err < 0)+ return err; - if (written == 0 && req_size != 0)- return req.error < 0 ? req.error : UV_EAGAIN;- else- return written;+ return uv__try_write(stream, bufs, nbufs, send_handle); } -int uv_read_start(uv_stream_t* stream,- uv_alloc_cb alloc_cb,- uv_read_cb read_cb) {+int uv__read_start(uv_stream_t* stream,+ uv_alloc_cb alloc_cb,+ uv_read_cb read_cb) { assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY); - if (stream->flags & UV_HANDLE_CLOSING)- return UV_EINVAL;-- if (!(stream->flags & UV_HANDLE_READABLE))- return UV_ENOTCONN;- /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just * expresses the desired state of the user. */@@ -1593,8 +1579,7 @@ stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);- if (!uv__io_active(&stream->io_watcher, POLLOUT))- uv__handle_stop(stream);+ uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); stream->read_cb = NULL;
third_party/libuv/src/unix/tcp.c view
@@ -214,14 +214,15 @@ if (handle->connect_req != NULL) return UV_EALREADY; /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */ + if (handle->delayed_error != 0)+ goto out;+ err = maybe_new_socket(handle, addr->sa_family, UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); if (err) return err; - handle->delayed_error = 0;- do { errno = 0; r = connect(uv__stream_fd(handle), addr, addrlen);@@ -249,6 +250,8 @@ return UV__ERR(errno); } +out:+ uv__req_init(handle->loop, req, UV_CONNECT); req->cb = cb; req->handle = (uv_stream_t*) handle;@@ -458,4 +461,50 @@ void uv__tcp_close(uv_tcp_t* handle) { uv__stream_close((uv_stream_t*)handle);+}+++int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {+ uv_os_sock_t temp[2];+ int err;+#if defined(__FreeBSD__) || defined(__linux__)+ int flags;++ flags = type | SOCK_CLOEXEC;+ if ((flags0 & UV_NONBLOCK_PIPE) && (flags1 & UV_NONBLOCK_PIPE))+ flags |= SOCK_NONBLOCK;++ if (socketpair(AF_UNIX, flags, protocol, temp))+ return UV__ERR(errno);++ if (flags & UV_FS_O_NONBLOCK) {+ fds[0] = temp[0];+ fds[1] = temp[1];+ return 0;+ }+#else+ if (socketpair(AF_UNIX, type, protocol, temp))+ return UV__ERR(errno);++ if ((err = uv__cloexec(temp[0], 1)))+ goto fail;+ if ((err = uv__cloexec(temp[1], 1)))+ goto fail;+#endif++ if (flags0 & UV_NONBLOCK_PIPE)+ if ((err = uv__nonblock(temp[0], 1)))+ goto fail;+ if (flags1 & UV_NONBLOCK_PIPE)+ if ((err = uv__nonblock(temp[1], 1)))+ goto fail;++ fds[0] = temp[0];+ fds[1] = temp[1];+ return 0;++fail:+ uv__close(temp[0]);+ uv__close(temp[1]);+ return err; }
third_party/libuv/src/unix/thread.c view
@@ -107,8 +107,7 @@ } last = (--b->out == 0);- if (!last)- uv_cond_signal(&b->cond); /* Not needed for last thread. */+ uv_cond_signal(&b->cond); uv_mutex_unlock(&b->mutex); return last;@@ -122,9 +121,10 @@ uv_mutex_lock(&b->mutex); assert(b->in == 0);- assert(b->out == 0);+ while (b->out != 0)+ uv_cond_wait(&b->cond, &b->mutex); - if (b->in != 0 || b->out != 0)+ if (b->in != 0) abort(); uv_mutex_unlock(&b->mutex);@@ -168,7 +168,7 @@ * On Linux, threads created by musl have a much smaller stack than threads * created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency. */-static size_t thread_stack_size(void) {+size_t uv__thread_stack_size(void) { #if defined(__APPLE__) || defined(__linux__) struct rlimit lim; @@ -234,7 +234,7 @@ attr = NULL; if (stack_size == 0) {- stack_size = thread_stack_size();+ stack_size = uv__thread_stack_size(); } else { pagesize = (size_t)getpagesize(); /* Round up to the nearest page boundary. */
third_party/libuv/src/unix/tty.c view
@@ -242,6 +242,24 @@ tio->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); tio->c_cflag &= ~(CSIZE | PARENB); tio->c_cflag |= CS8;++ /*+ * By default, most software expects a pending read to block until at+ * least one byte becomes available. As per termio(7I), this requires+ * setting the MIN and TIME parameters appropriately.+ *+ * As a somewhat unfortunate artifact of history, the MIN and TIME slots+ * in the control character array overlap with the EOF and EOL slots used+ * for canonical mode processing. Because the EOF character needs to be+ * the ASCII EOT value (aka Control-D), it has the byte value 4. When+ * switching to raw mode, this is interpreted as a MIN value of 4; i.e.,+ * reads will block until at least four bytes have been input.+ *+ * Other platforms with a distinct MIN slot like Linux and FreeBSD appear+ * to default to a MIN value of 1, so we'll force that value here:+ */+ tio->c_cc[VMIN] = 1;+ tio->c_cc[VTIME] = 0; #else cfmakeraw(tio); #endif /* #ifdef __sun */
third_party/libuv/src/unix/udp.c view
@@ -32,8 +32,6 @@ #endif #include <sys/un.h> -#define UV__UDP_DGRAM_MAXSIZE (64 * 1024)- #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP #endif@@ -504,7 +502,29 @@ return 0; } +/*+ * The Linux kernel suppresses some ICMP error messages by default for UDP+ * sockets. Setting IP_RECVERR/IPV6_RECVERR on the socket enables full ICMP+ * error reporting, hopefully resulting in faster failover to working name+ * servers.+ */+static int uv__set_recverr(int fd, sa_family_t ss_family) {+#if defined(__linux__)+ int yes; + yes = 1;+ if (ss_family == AF_INET) {+ if (setsockopt(fd, IPPROTO_IP, IP_RECVERR, &yes, sizeof(yes)))+ return UV__ERR(errno);+ } else if (ss_family == AF_INET6) {+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVERR, &yes, sizeof(yes)))+ return UV__ERR(errno);+ }+#endif+ return 0;+}++ int uv__udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int addrlen,@@ -514,7 +534,7 @@ int fd; /* Check for bad flags. */- if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR))+ if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR | UV_UDP_LINUX_RECVERR)) return UV_EINVAL; /* Cannot set IPv6-only mode on non-IPv6 socket. */@@ -528,6 +548,12 @@ return err; fd = err; handle->io_watcher.fd = fd;+ }++ if (flags & UV_UDP_LINUX_RECVERR) {+ err = uv__set_recverr(fd, addr->sa_family);+ if (err)+ return err; } if (flags & UV_UDP_REUSEADDR) {
third_party/libuv/src/uv-common.c view
@@ -832,6 +832,25 @@ } +int uv_read_start(uv_stream_t* stream,+ uv_alloc_cb alloc_cb,+ uv_read_cb read_cb) {+ if (stream == NULL || alloc_cb == NULL || read_cb == NULL)+ return UV_EINVAL;++ if (stream->flags & UV_HANDLE_CLOSING)+ return UV_EINVAL;++ if (stream->flags & UV_HANDLE_READING)+ return UV_EALREADY;++ if (!(stream->flags & UV_HANDLE_READABLE))+ return UV_ENOTCONN;++ return uv__read_start(stream, alloc_cb, read_cb);+}++ void uv_os_free_environ(uv_env_item_t* envitems, int count) { int i; @@ -853,7 +872,11 @@ } -#ifdef __GNUC__ /* Also covers __clang__ and __INTEL_COMPILER. */+/* Also covers __clang__ and __INTEL_COMPILER. Disabled on Windows because+ * threads have already been forcibly terminated by the operating system+ * by the time destructors run, ergo, it's not safe to try to clean them up.+ */+#if defined(__GNUC__) && !defined(_WIN32) __attribute__((destructor)) #endif void uv_library_shutdown(void) {
third_party/libuv/src/uv-common.h view
@@ -68,6 +68,8 @@ #define uv__store_relaxed(p, v) do *p = v; while (0) #endif +#define UV__UDP_DGRAM_MAXSIZE (64 * 1024)+ /* Handle flags. Some flags are specific to Windows or UNIX. */ enum { /* Used by all handles. */@@ -106,8 +108,7 @@ UV_HANDLE_TCP_KEEPALIVE = 0x02000000, UV_HANDLE_TCP_SINGLE_ACCEPT = 0x04000000, UV_HANDLE_TCP_ACCEPT_STATE_CHANGING = 0x08000000,- UV_HANDLE_TCP_SOCKET_CLOSED = 0x10000000,- UV_HANDLE_SHARED_TCP_SOCKET = 0x20000000,+ UV_HANDLE_SHARED_TCP_SOCKET = 0x10000000, /* Only used by uv_udp_t handles. */ UV_HANDLE_UDP_PROCESSING = 0x01000000,@@ -135,6 +136,10 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); void uv__loop_close(uv_loop_t* loop);++int uv__read_start(uv_stream_t* stream,+ uv_alloc_cb alloc_cb,+ uv_read_cb read_cb); int uv__tcp_bind(uv_tcp_t* tcp, const struct sockaddr* addr,
third_party/libuv/src/win/atomicops-inl.h view
@@ -39,10 +39,11 @@ return _InterlockedOr8(target, 1); } -#else /* GCC */+#else /* GCC, Clang in mingw mode */ -/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */ static inline char uv__atomic_exchange_set(char volatile* target) {+#if defined(__i386__) || defined(__x86_64__)+ /* Mingw-32 version, hopefully this works for 64-bit gcc as well. */ const char one = 1; char old_value; __asm__ __volatile__ ("lock xchgb %0, %1\n\t"@@ -50,6 +51,9 @@ : "0"(one), "m"(*target) : "memory"); return old_value;+#else+ return __sync_fetch_and_or(target, 1);+#endif } #endif
third_party/libuv/src/win/error.c view
@@ -105,7 +105,6 @@ case ERROR_SYMLINK_NOT_SUPPORTED: return UV_EINVAL; case WSAEINVAL: return UV_EINVAL; case WSAEPFNOSUPPORT: return UV_EINVAL;- case WSAESOCKTNOSUPPORT: return UV_EINVAL; case ERROR_BEGINNING_OF_MEDIA: return UV_EIO; case ERROR_BUS_RESET: return UV_EIO; case ERROR_CRC: return UV_EIO;@@ -168,6 +167,7 @@ case ERROR_NOT_SAME_DEVICE: return UV_EXDEV; case ERROR_INVALID_FUNCTION: return UV_EISDIR; case ERROR_META_EXPANSION_TOO_LONG: return UV_E2BIG;+ case WSAESOCKTNOSUPPORT: return UV_ESOCKTNOSUPPORT; default: return UV_UNKNOWN; } }
third_party/libuv/src/win/fs.c view
@@ -92,30 +92,24 @@ return; \ } -#define MILLIONu (1000U * 1000U)-#define BILLIONu (1000U * 1000U * 1000U)--#define FILETIME_TO_UINT(filetime) \- (*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)--#define FILETIME_TO_TIME_T(filetime) \- (FILETIME_TO_UINT(filetime) / (10u * MILLIONu))--#define FILETIME_TO_TIME_NS(filetime, secs) \- ((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)+#define MILLION ((int64_t) 1000 * 1000)+#define BILLION ((int64_t) 1000 * 1000 * 1000) -#define FILETIME_TO_TIMESPEC(ts, filetime) \- do { \- (ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime); \- (ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec); \- } while(0)+static void uv__filetime_to_timespec(uv_timespec_t *ts, int64_t filetime) {+ filetime -= 116444736 * BILLION;+ ts->tv_sec = (long) (filetime / (10 * MILLION));+ ts->tv_nsec = (long) ((filetime - ts->tv_sec * 10 * MILLION) * 100U);+ if (ts->tv_nsec < 0) {+ ts->tv_sec -= 1;+ ts->tv_nsec += 1e9;+ }+} #define TIME_T_TO_FILETIME(time, filetime_ptr) \ do { \- uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) + \- (uint64_t) 116444736 * BILLIONu; \- (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \- (filetime_ptr)->dwHighDateTime = bigtime >> 32; \+ int64_t bigtime = ((time) * 10 * MILLION + 116444736 * BILLION); \+ (filetime_ptr)->dwLowDateTime = (uint64_t) bigtime & 0xFFFFFFFF; \+ (filetime_ptr)->dwHighDateTime = (uint64_t) bigtime >> 32; \ } while(0) #define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')@@ -1224,7 +1218,8 @@ SET_REQ_RESULT(req, 0); } else { SET_REQ_WIN32_ERROR(req, GetLastError());- if (req->sys_errno_ == ERROR_INVALID_NAME)+ if (req->sys_errno_ == ERROR_INVALID_NAME ||+ req->sys_errno_ == ERROR_DIRECTORY) req->result = UV_EINVAL; } }@@ -1243,7 +1238,7 @@ uint64_t v; char* path; - path = req->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)) {@@ -1791,10 +1786,14 @@ statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) | ((_S_IREAD | _S_IWRITE) >> 6); - FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime);- FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime);- FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime);- FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime);+ uv__filetime_to_timespec(&statbuf->st_atim,+ file_info.BasicInformation.LastAccessTime.QuadPart);+ uv__filetime_to_timespec(&statbuf->st_ctim,+ file_info.BasicInformation.ChangeTime.QuadPart);+ uv__filetime_to_timespec(&statbuf->st_mtim,+ file_info.BasicInformation.LastWriteTime.QuadPart);+ uv__filetime_to_timespec(&statbuf->st_birthtim,+ file_info.BasicInformation.CreationTime.QuadPart); statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart;
third_party/libuv/src/win/internal.h view
@@ -115,8 +115,8 @@ /* * Pipes */-int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,- char* name, size_t nameSize);+int uv__create_stdio_pipe_pair(uv_loop_t* loop,+ uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags); 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);
third_party/libuv/src/win/pipe.c view
@@ -202,17 +202,17 @@ } -int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,- char* name, size_t nameSize) {+static int uv__pipe_server(+ HANDLE* pipeHandle_ptr, DWORD access,+ char* name, size_t nameSize, char* random) { HANDLE pipeHandle; int err;- char* ptr = (char*)handle; for (;;) {- uv_unique_pipe_name(ptr, name, nameSize);+ uv_unique_pipe_name(random, name, nameSize); pipeHandle = CreateNamedPipeA(name,- access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,+ access | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0, NULL); @@ -226,27 +226,226 @@ goto error; } - /* Pipe name collision. Increment the pointer and try again. */- ptr++;+ /* Pipe name collision. Increment the random number and try again. */+ random++; } - if (CreateIoCompletionPort(pipeHandle,+ *pipeHandle_ptr = pipeHandle;++ return 0;++ error:+ if (pipeHandle != INVALID_HANDLE_VALUE)+ CloseHandle(pipeHandle);++ return err;+}+++static int uv__create_pipe_pair(+ HANDLE* server_pipe_ptr, HANDLE* client_pipe_ptr,+ unsigned int server_flags, unsigned int client_flags,+ int inherit_client, char* random) {+ /* allowed flags are: UV_READABLE_PIPE | UV_WRITABLE_PIPE | UV_NONBLOCK_PIPE */+ char pipe_name[64];+ SECURITY_ATTRIBUTES sa;+ DWORD server_access;+ DWORD client_access;+ HANDLE server_pipe;+ HANDLE client_pipe;+ int err;++ server_pipe = INVALID_HANDLE_VALUE;+ client_pipe = INVALID_HANDLE_VALUE;++ server_access = 0;+ if (server_flags & UV_READABLE_PIPE)+ server_access |= PIPE_ACCESS_INBOUND;+ if (server_flags & UV_WRITABLE_PIPE)+ server_access |= PIPE_ACCESS_OUTBOUND;+ if (server_flags & UV_NONBLOCK_PIPE)+ server_access |= FILE_FLAG_OVERLAPPED;+ server_access |= WRITE_DAC;++ client_access = 0;+ if (client_flags & UV_READABLE_PIPE)+ client_access |= GENERIC_READ;+ else+ client_access |= FILE_READ_ATTRIBUTES;+ if (client_flags & UV_WRITABLE_PIPE)+ client_access |= GENERIC_WRITE;+ else+ client_access |= FILE_WRITE_ATTRIBUTES;+ client_access |= WRITE_DAC;++ /* Create server pipe handle. */+ err = uv__pipe_server(&server_pipe,+ server_access,+ pipe_name,+ sizeof(pipe_name),+ random);+ if (err)+ goto error;++ /* Create client pipe handle. */+ sa.nLength = sizeof sa;+ sa.lpSecurityDescriptor = NULL;+ sa.bInheritHandle = inherit_client;++ client_pipe = CreateFileA(pipe_name,+ client_access,+ 0,+ &sa,+ OPEN_EXISTING,+ (client_flags & UV_NONBLOCK_PIPE) ? FILE_FLAG_OVERLAPPED : 0,+ NULL);+ if (client_pipe == INVALID_HANDLE_VALUE) {+ err = GetLastError();+ goto error;+ }++#ifndef NDEBUG+ /* Validate that the pipe was opened in the right mode. */+ {+ DWORD mode;+ BOOL r;+ r = GetNamedPipeHandleState(client_pipe, &mode, NULL, NULL, NULL, NULL, 0);+ if (r == TRUE) {+ assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));+ } else {+ fprintf(stderr, "libuv assertion failure: GetNamedPipeHandleState failed\n");+ }+ }+#endif++ /* Do a blocking ConnectNamedPipe. This should not block because we have+ * both ends of the pipe created. */+ if (!ConnectNamedPipe(server_pipe, NULL)) {+ if (GetLastError() != ERROR_PIPE_CONNECTED) {+ err = GetLastError();+ goto error;+ }+ }++ *client_pipe_ptr = client_pipe;+ *server_pipe_ptr = server_pipe;+ return 0;++ error:+ if (server_pipe != INVALID_HANDLE_VALUE)+ CloseHandle(server_pipe);++ if (client_pipe != INVALID_HANDLE_VALUE)+ CloseHandle(client_pipe);++ return err;+}+++int uv_pipe(uv_file fds[2], int read_flags, int write_flags) {+ uv_file temp[2];+ int err;+ HANDLE readh;+ HANDLE writeh;++ /* Make the server side the inbound (read) end, */+ /* so that both ends will have FILE_READ_ATTRIBUTES permission. */+ /* TODO: better source of local randomness than &fds? */+ read_flags |= UV_READABLE_PIPE;+ write_flags |= UV_WRITABLE_PIPE;+ err = uv__create_pipe_pair(&readh, &writeh, read_flags, write_flags, 0, (char*) &fds[0]);+ if (err != 0)+ return err;+ temp[0] = _open_osfhandle((intptr_t) readh, 0);+ if (temp[0] == -1) {+ if (errno == UV_EMFILE)+ err = UV_EMFILE;+ else+ err = UV_UNKNOWN;+ CloseHandle(readh);+ CloseHandle(writeh);+ return err;+ }+ temp[1] = _open_osfhandle((intptr_t) writeh, 0);+ if (temp[1] == -1) {+ if (errno == UV_EMFILE)+ err = UV_EMFILE;+ else+ err = UV_UNKNOWN;+ _close(temp[0]);+ CloseHandle(writeh);+ return err;+ }+ fds[0] = temp[0];+ fds[1] = temp[1];+ return 0;+}+++int uv__create_stdio_pipe_pair(uv_loop_t* loop,+ uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {+ /* The parent_pipe is always the server_pipe and kept by libuv.+ * The child_pipe is always the client_pipe and is passed to the child.+ * The flags are specified with respect to their usage in the child. */+ HANDLE server_pipe;+ HANDLE client_pipe;+ unsigned int server_flags;+ unsigned int client_flags;+ int err;++ server_pipe = INVALID_HANDLE_VALUE;+ client_pipe = INVALID_HANDLE_VALUE;++ server_flags = 0;+ client_flags = 0;+ if (flags & UV_READABLE_PIPE) {+ /* The server needs inbound (read) 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_flags |= UV_READABLE_PIPE | UV_WRITABLE_PIPE;+ client_flags |= UV_READABLE_PIPE;+ }+ if (flags & UV_WRITABLE_PIPE) {+ server_flags |= UV_READABLE_PIPE;+ client_flags |= UV_WRITABLE_PIPE;+ }+ server_flags |= UV_NONBLOCK_PIPE;+ if (flags & UV_NONBLOCK_PIPE || parent_pipe->ipc) {+ client_flags |= UV_NONBLOCK_PIPE;+ }++ err = uv__create_pipe_pair(&server_pipe, &client_pipe,+ server_flags, client_flags, 1, (char*) server_pipe);+ if (err)+ goto error;++ if (CreateIoCompletionPort(server_pipe, loop->iocp,- (ULONG_PTR)handle,+ (ULONG_PTR) parent_pipe, 0) == NULL) { err = GetLastError(); goto error; } - uv_pipe_connection_init(handle);- handle->handle = pipeHandle;+ uv_pipe_connection_init(parent_pipe);+ parent_pipe->handle = server_pipe;+ *child_pipe_ptr = client_pipe; + /* The server end is now readable and/or writable. */+ if (flags & UV_READABLE_PIPE)+ parent_pipe->flags |= UV_HANDLE_WRITABLE;+ if (flags & UV_WRITABLE_PIPE)+ parent_pipe->flags |= UV_HANDLE_READABLE;+ return 0; error:- if (pipeHandle != INVALID_HANDLE_VALUE)- CloseHandle(pipeHandle);+ if (server_pipe != INVALID_HANDLE_VALUE)+ CloseHandle(server_pipe); + if (client_pipe != INVALID_HANDLE_VALUE)+ CloseHandle(client_pipe);+ return err; } @@ -712,9 +911,8 @@ handle->name = NULL; } - if (pipeHandle != INVALID_HANDLE_VALUE) {+ if (pipeHandle != INVALID_HANDLE_VALUE) CloseHandle(pipeHandle);- } /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, err);
third_party/libuv/src/win/poll.c view
@@ -488,7 +488,8 @@ assert(handle->type == UV_POLL); assert(!(handle->flags & UV_HANDLE_CLOSING));- assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);+ assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT |+ UV_PRIORITIZED)) == 0); handle->events = events; handle->poll_cb = cb;
third_party/libuv/src/win/process-stdio.c view
@@ -95,102 +95,6 @@ } -static int uv__create_stdio_pipe_pair(uv_loop_t* loop,- uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {- char pipe_name[64];- SECURITY_ATTRIBUTES sa;- DWORD server_access = 0;- 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. */- server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;- client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;- }- if (flags & UV_WRITABLE_PIPE) {- server_access |= PIPE_ACCESS_INBOUND;- client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;- }-- /* Create server pipe handle. */- err = uv_stdio_pipe_server(loop,- server_pipe,- server_access,- pipe_name,- sizeof(pipe_name));- if (err)- goto error;-- /* Create child pipe handle. */- sa.nLength = sizeof sa;- 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,- overlap ? FILE_FLAG_OVERLAPPED : 0,- NULL);- if (child_pipe == INVALID_HANDLE_VALUE) {- err = GetLastError();- goto error;- }--#ifndef NDEBUG- /* Validate that the pipe was opened in the right mode. */- {- DWORD mode;- BOOL r = GetNamedPipeHandleState(child_pipe,- &mode,- NULL,- NULL,- NULL,- NULL,- 0);- assert(r == TRUE);- assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));- }-#endif-- /* 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();- goto error;- }- }-- /* The server end is now readable and/or writable. */- if (flags & UV_READABLE_PIPE)- server_pipe->flags |= UV_HANDLE_WRITABLE;- if (flags & UV_WRITABLE_PIPE)- server_pipe->flags |= UV_HANDLE_READABLE;-- *child_pipe_ptr = child_pipe;- return 0;-- error:- if (server_pipe->handle != INVALID_HANDLE_VALUE) {- uv_pipe_cleanup(loop, server_pipe);- }-- if (child_pipe != INVALID_HANDLE_VALUE) {- CloseHandle(child_pipe);- }-- return err;-}-- static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) { HANDLE current_process;
third_party/libuv/src/win/process.c view
@@ -642,7 +642,7 @@ assert(r==nb); B[nb] = L'\0'; - while (1) {+ for (;;) { wchar_t AA = *A++; wchar_t BB = *B++; if (AA < BB) {
third_party/libuv/src/win/stream.c view
@@ -65,18 +65,11 @@ } -int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,- uv_read_cb read_cb) {+int uv__read_start(uv_stream_t* handle,+ uv_alloc_cb alloc_cb,+ uv_read_cb read_cb) { int err; - if (handle->flags & UV_HANDLE_READING) {- return UV_EALREADY;- }-- if (!(handle->flags & UV_HANDLE_READABLE)) {- return UV_ENOTCONN;- }- err = ERROR_INVALID_PARAMETER; switch (handle->type) { case UV_TCP:@@ -192,6 +185,16 @@ assert(0); return UV_ENOSYS; }+}+++int uv_try_write2(uv_stream_t* stream,+ const uv_buf_t bufs[],+ unsigned int nbufs,+ uv_stream_t* send_handle) {+ if (send_handle != NULL)+ return UV_EAGAIN;+ return uv_try_write(stream, bufs, nbufs); }
third_party/libuv/src/win/tcp.c view
@@ -236,12 +236,7 @@ if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED));-- if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) {- closesocket(handle->socket);- handle->socket = INVALID_SOCKET;- handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;- }+ assert(handle->socket == INVALID_SOCKET); if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) { if (handle->flags & UV_HANDLE_EMULATE_IOCP) {@@ -599,6 +594,7 @@ } } + /* If this flag is set, we already made this listen call in xfer. */ if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) && listen(handle->socket, backlog) == SOCKET_ERROR) { return WSAGetLastError();@@ -769,7 +765,7 @@ } // Check if Windows version is 10.0.16299 or later-static int uv__is_fast_loopback_fail_supported() {+static int uv__is_fast_loopback_fail_supported(void) { OSVERSIONINFOW os_info; if (!pRtlGetVersion) return 0;@@ -800,9 +796,8 @@ if (err) return err; - if (handle->delayed_error) {- return handle->delayed_error;- }+ if (handle->delayed_error != 0)+ goto out; if (!(handle->flags & UV_HANDLE_BOUND)) { if (addrlen == sizeof(uv_addr_ip4_any_)) {@@ -815,8 +810,8 @@ err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0); if (err) return err;- if (handle->delayed_error)- return handle->delayed_error;+ if (handle->delayed_error != 0)+ goto out; } if (!handle->tcp.conn.func_connectex) {@@ -844,11 +839,21 @@ NULL); } +out:+ UV_REQ_INIT(req, UV_CONNECT); req->handle = (uv_stream_t*) handle; req->cb = cb; memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); + if (handle->delayed_error != 0) {+ /* Process the req without IOCP. */+ handle->reqs_pending++;+ REGISTER_HANDLE_REQ(loop, handle, req);+ uv_insert_pending_req(loop, (uv_req_t*)req);+ return 0;+ }+ success = handle->tcp.conn.func_connectex(handle->socket, (const struct sockaddr*) &converted, addrlen,@@ -1015,6 +1020,7 @@ */ err = WSAECONNRESET; }+ handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); handle->read_cb((uv_stream_t*)handle, uv_translate_sys_error(err),@@ -1096,6 +1102,7 @@ * Unix. */ err = WSAECONNRESET; }+ handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); handle->read_cb((uv_stream_t*)handle, uv_translate_sys_error(err),@@ -1149,9 +1156,14 @@ } handle->stream.conn.write_reqs_pending--;- if (handle->stream.conn.shutdown_req != NULL &&- handle->stream.conn.write_reqs_pending == 0) {- uv_want_endgame(loop, (uv_handle_t*)handle);+ if (handle->stream.conn.write_reqs_pending == 0) {+ if (handle->flags & UV_HANDLE_CLOSING) {+ closesocket(handle->socket);+ handle->socket = INVALID_SOCKET;+ }+ if (handle->stream.conn.shutdown_req != NULL) {+ uv_want_endgame(loop, (uv_handle_t*)handle);+ } } DECREASE_PENDING_REQ_COUNT(handle);@@ -1215,7 +1227,14 @@ UNREGISTER_HANDLE_REQ(loop, handle, req); err = 0;- if (REQ_SUCCESS(req)) {+ if (handle->delayed_error) {+ /* To smooth over the differences between unixes errors that+ * were reported synchronously on the first connect can be delayed+ * until the next tick--which is now.+ */+ err = handle->delayed_error;+ handle->delayed_error = 0;+ } else if (REQ_SUCCESS(req)) { if (handle->flags & UV_HANDLE_CLOSING) { /* use UV_ECANCELED for consistency with Unix */ err = ERROR_OPERATION_ABORTED;@@ -1320,7 +1339,7 @@ if (handle->socket != INVALID_SOCKET) { err = uv__tcp_nodelay(handle, handle->socket, enable); if (err)- return err;+ return uv_translate_sys_error(err); } if (enable) {@@ -1339,7 +1358,7 @@ if (handle->socket != INVALID_SOCKET) { err = uv__tcp_keepalive(handle, handle->socket, enable, delay); if (err)- return err;+ return uv_translate_sys_error(err); } if (enable) {@@ -1386,10 +1405,25 @@ } -static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {- SOCKET socket = tcp->socket;+static void uv_tcp_try_cancel_reqs(uv_tcp_t* tcp) {+ SOCKET socket; int non_ifs_lsp;+ int reading;+ int writing; + socket = tcp->socket;+ reading = tcp->flags & UV_HANDLE_READING;+ writing = tcp->stream.conn.write_reqs_pending > 0;+ if (!reading && !writing)+ return;++ /* TODO: in libuv v2, keep explicit track of write_reqs, so we can cancel+ * them each explicitly with CancelIoEx (like unix). */+ if (reading)+ CancelIoEx((HANDLE) socket, &tcp->read_req.u.io.overlapped);+ if (writing)+ CancelIo((HANDLE) socket);+ /* Check if we have any non-IFS LSPs stacked on top of TCP */ non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : uv_tcp_non_ifs_lsp_ipv4;@@ -1408,71 +1442,41 @@ NULL, NULL) != 0) { /* Failed. We can't do CancelIo. */- return -1;+ return; } } assert(socket != 0 && socket != INVALID_SOCKET); - if (!CancelIo((HANDLE) socket)) {- return GetLastError();+ if (socket != tcp->socket) {+ if (reading)+ CancelIoEx((HANDLE) socket, &tcp->read_req.u.io.overlapped);+ if (writing)+ CancelIo((HANDLE) socket); }-- /* It worked. */- return 0; } 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 */- 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. */- 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. */+ if (tcp->flags & UV_HANDLE_CONNECTION) {+ uv_tcp_try_cancel_reqs(tcp);+ if (tcp->flags & UV_HANDLE_READING) {+ uv_read_stop((uv_stream_t*) tcp); }-- } 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. */- 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. */+ } else {+ if (tcp->tcp.serv.accept_reqs != NULL) {+ /* First close the incoming sockets to cancel the accept operations before+ * we free their resources. */ unsigned int i; for (i = 0; i < uv_simultaneous_server_accepts; i++) { uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];- if (req->accept_socket != INVALID_SOCKET &&- !HasOverlappedIoCompleted(&req->u.io.overlapped)) {+ if (req->accept_socket != INVALID_SOCKET) { closesocket(req->accept_socket); req->accept_socket = INVALID_SOCKET; } } }- }-- if (tcp->flags & UV_HANDLE_READING) {- tcp->flags &= ~UV_HANDLE_READING;- DECREASE_ACTIVE_COUNT(loop, tcp);+ assert(!(tcp->flags & UV_HANDLE_READING)); } if (tcp->flags & UV_HANDLE_LISTENING) {@@ -1480,10 +1484,15 @@ DECREASE_ACTIVE_COUNT(loop, tcp); } - if (close_socket) {+ /* If any overlapped req failed to cancel, calling `closesocket` now would+ * cause Win32 to send an RST packet. Try to avoid that for writes, if+ * possibly applicable, by waiting to process the completion notifications+ * first (which typically should be cancellations). There's not much we can+ * do about canceled reads, which also will generate an RST packet. */+ if (!(tcp->flags & UV_HANDLE_CONNECTION) ||+ tcp->stream.conn.write_reqs_pending == 0) { closesocket(tcp->socket); tcp->socket = INVALID_SOCKET;- tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; } tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);@@ -1570,4 +1579,119 @@ return uv_translate_sys_error(err); return 0;+}++#ifndef WSA_FLAG_NO_HANDLE_INHERIT+/* Added in Windows 7 SP1. Specify this to avoid race conditions, */+/* but also manually clear the inherit flag in case this failed. */+#define WSA_FLAG_NO_HANDLE_INHERIT 0x80+#endif++int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {+ SOCKET server = INVALID_SOCKET;+ SOCKET client0 = INVALID_SOCKET;+ SOCKET client1 = INVALID_SOCKET;+ SOCKADDR_IN name;+ LPFN_ACCEPTEX func_acceptex;+ WSAOVERLAPPED overlap;+ char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32];+ int namelen;+ int err;+ DWORD bytes;+ DWORD flags;+ DWORD client0_flags = WSA_FLAG_NO_HANDLE_INHERIT;+ DWORD client1_flags = WSA_FLAG_NO_HANDLE_INHERIT;++ if (flags0 & UV_NONBLOCK_PIPE)+ client0_flags |= WSA_FLAG_OVERLAPPED;+ if (flags1 & UV_NONBLOCK_PIPE)+ client1_flags |= WSA_FLAG_OVERLAPPED;++ server = WSASocketW(AF_INET, type, protocol, NULL, 0,+ WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);+ if (server == INVALID_SOCKET)+ goto wsaerror;+ if (!SetHandleInformation((HANDLE) server, HANDLE_FLAG_INHERIT, 0))+ goto error;+ name.sin_family = AF_INET;+ name.sin_addr.s_addr = htonl(INADDR_LOOPBACK);+ name.sin_port = 0;+ if (bind(server, (SOCKADDR*) &name, sizeof(name)) != 0)+ goto wsaerror;+ if (listen(server, 1) != 0)+ goto wsaerror;+ namelen = sizeof(name);+ if (getsockname(server, (SOCKADDR*) &name, &namelen) != 0)+ goto wsaerror;+ client0 = WSASocketW(AF_INET, type, protocol, NULL, 0, client0_flags);+ if (client0 == INVALID_SOCKET)+ goto wsaerror;+ if (!SetHandleInformation((HANDLE) client0, HANDLE_FLAG_INHERIT, 0))+ goto error;+ if (connect(client0, (SOCKADDR*) &name, sizeof(name)) != 0)+ goto wsaerror;+ client1 = WSASocketW(AF_INET, type, protocol, NULL, 0, client1_flags);+ if (client1 == INVALID_SOCKET)+ goto wsaerror;+ if (!SetHandleInformation((HANDLE) client1, HANDLE_FLAG_INHERIT, 0))+ goto error;+ if (!uv_get_acceptex_function(server, &func_acceptex)) {+ err = WSAEAFNOSUPPORT;+ goto cleanup;+ }+ memset(&overlap, 0, sizeof(overlap));+ if (!func_acceptex(server,+ client1,+ accept_buffer,+ 0,+ sizeof(struct sockaddr_storage),+ sizeof(struct sockaddr_storage),+ &bytes,+ &overlap)) {+ err = WSAGetLastError();+ if (err == ERROR_IO_PENDING) {+ /* Result should complete immediately, since we already called connect,+ * but emperically, we sometimes have to poll the kernel a couple times+ * until it notices that. */+ while (!WSAGetOverlappedResult(client1, &overlap, &bytes, FALSE, &flags)) {+ err = WSAGetLastError();+ if (err != WSA_IO_INCOMPLETE)+ goto cleanup;+ SwitchToThread();+ }+ }+ else {+ goto cleanup;+ }+ }+ if (setsockopt(client1, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,+ (char*) &server, sizeof(server)) != 0) {+ goto wsaerror;+ }++ closesocket(server);++ fds[0] = client0;+ fds[1] = client1;++ return 0;++ wsaerror:+ err = WSAGetLastError();+ goto cleanup;++ error:+ err = GetLastError();+ goto cleanup;++ cleanup:+ if (server != INVALID_SOCKET)+ closesocket(server);+ if (client0 != INVALID_SOCKET)+ closesocket(client0);+ if (client1 != INVALID_SOCKET)+ closesocket(client1);++ assert(err);+ return uv_translate_sys_error(err); }
third_party/libuv/src/win/udp.c view
@@ -284,7 +284,7 @@ handle->flags &= ~UV_HANDLE_ZERO_READ; handle->recv_buffer = uv_buf_init(NULL, 0);- handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->recv_buffer);+ handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &handle->recv_buffer); if (handle->recv_buffer.base == NULL || handle->recv_buffer.len == 0) { handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0); return;@@ -501,7 +501,7 @@ /* 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);+ handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf); if (buf.base == NULL || buf.len == 0) { handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); goto done;
third_party/libuv/src/win/util.c view
@@ -1664,26 +1664,33 @@ int uv_os_gethostname(char* buffer, size_t* size) {- char buf[UV_MAXHOSTNAMESIZE];+ WCHAR buf[UV_MAXHOSTNAMESIZE]; size_t len;+ char* utf8_str;+ int convert_result; if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; uv__once_init(); /* Initialize winsock */ - if (gethostname(buf, sizeof(buf)) != 0)+ if (GetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0) return uv_translate_sys_error(WSAGetLastError()); - buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */- len = strlen(buf);+ convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str); + if (convert_result != 0)+ return convert_result;++ len = strlen(utf8_str); if (len >= *size) { *size = len + 1;+ uv__free(utf8_str); return UV_ENOBUFS; } - memcpy(buffer, buf, len + 1);+ memcpy(buffer, utf8_str, len + 1);+ uv__free(utf8_str); *size = len; return 0; }