summaryrefslogtreecommitdiff
path: root/deps/uv
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2018-06-22 11:28:11 -0400
committercjihrig <cjihrig@gmail.com>2018-06-24 20:54:34 -0400
commit537a4baa443daea9850a8e324b5b4d7c21dd2717 (patch)
treef36565e62794a56adfa99a8511c6d2a90c466fbc /deps/uv
parent49e5f0a10fc3784b318842b06854b38475fc884b (diff)
downloadandroid-node-v8-537a4baa443daea9850a8e324b5b4d7c21dd2717.tar.gz
android-node-v8-537a4baa443daea9850a8e324b5b4d7c21dd2717.tar.bz2
android-node-v8-537a4baa443daea9850a8e324b5b4d7c21dd2717.zip
deps: upgrade to libuv 1.21.0
Notable changes: - Building via cmake is now supported. PR-URL: https://github.com/libuv/libuv/pull/1850 - Stricter checks have been added to prevent watching the same file descriptor multiple times. PR-URL: https://github.com/libuv/libuv/pull/1851 Refs: https://github.com/nodejs/node/issues/3604 - An IPC deadlock on Windows has been fixed. PR-URL: https://github.com/libuv/libuv/pull/1843 Fixes: https://github.com/nodejs/node/issues/9706 Fixes: https://github.com/nodejs/node/issues/7657 - uv_fs_lchown() has been added. PR-URL: https://github.com/libuv/libuv/pull/1826 Refs: https://github.com/nodejs/node/issues/19868 - uv_fs_copyfile() sets errno on error. PR-URL: https://github.com/libuv/libuv/pull/1881 Fixes: https://github.com/nodejs/node/issues/21329 - uv_fs_fchmod() supports -A files on Windows. PR-URL: https://github.com/libuv/libuv/pull/1819 Refs: https://github.com/nodejs/node/issues/12803 PR-URL: https://github.com/nodejs/node/pull/21466 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'deps/uv')
-rw-r--r--deps/uv/AUTHORS5
-rw-r--r--deps/uv/CMakeLists.txt381
-rw-r--r--deps/uv/CONTRIBUTING.md5
-rw-r--r--deps/uv/ChangeLog97
-rw-r--r--deps/uv/MAINTAINERS.md1
-rw-r--r--deps/uv/Makefile.am37
-rw-r--r--deps/uv/Makefile.mingw86
-rw-r--r--deps/uv/README.md10
-rwxr-xr-xdeps/uv/checksparse.sh19
-rw-r--r--deps/uv/configure.ac2
-rw-r--r--deps/uv/docs/src/conf.py2
-rw-r--r--deps/uv/docs/src/errors.rst7
-rw-r--r--deps/uv/docs/src/fs.rst10
-rw-r--r--deps/uv/docs/src/handle.rst8
-rw-r--r--deps/uv/docs/src/pipe.rst4
-rw-r--r--deps/uv/docs/src/process.rst5
-rw-r--r--deps/uv/docs/src/request.rst9
-rw-r--r--deps/uv/include/uv.h44
-rw-r--r--deps/uv/include/uv/aix.h (renamed from deps/uv/include/uv-aix.h)0
-rw-r--r--deps/uv/include/uv/android-ifaddrs.h (renamed from deps/uv/include/android-ifaddrs.h)0
-rw-r--r--deps/uv/include/uv/bsd.h (renamed from deps/uv/include/uv-bsd.h)0
-rw-r--r--deps/uv/include/uv/darwin.h (renamed from deps/uv/include/uv-darwin.h)0
-rw-r--r--deps/uv/include/uv/errno.h (renamed from deps/uv/include/uv-errno.h)6
-rw-r--r--deps/uv/include/uv/linux.h (renamed from deps/uv/include/uv-linux.h)0
-rw-r--r--deps/uv/include/uv/os390.h (renamed from deps/uv/include/uv-os390.h)0
-rw-r--r--deps/uv/include/uv/posix.h (renamed from deps/uv/include/uv-posix.h)0
-rw-r--r--deps/uv/include/uv/pthread-barrier.h (renamed from deps/uv/include/pthread-barrier.h)0
-rw-r--r--deps/uv/include/uv/stdint-msvc2008.h (renamed from deps/uv/include/stdint-msvc2008.h)0
-rw-r--r--deps/uv/include/uv/sunos.h (renamed from deps/uv/include/uv-sunos.h)0
-rw-r--r--deps/uv/include/uv/threadpool.h (renamed from deps/uv/include/uv-threadpool.h)0
-rw-r--r--deps/uv/include/uv/tree.h (renamed from deps/uv/include/tree.h)0
-rw-r--r--deps/uv/include/uv/unix.h (renamed from deps/uv/include/uv-unix.h)20
-rw-r--r--deps/uv/include/uv/version.h (renamed from deps/uv/include/uv-version.h)4
-rw-r--r--deps/uv/include/uv/win.h (renamed from deps/uv/include/uv-win.h)43
-rw-r--r--deps/uv/libuv.pc.in2
-rw-r--r--deps/uv/samples/socks5-proxy/main.c6
-rw-r--r--deps/uv/src/inet.c2
-rw-r--r--deps/uv/src/unix/android-ifaddrs.c2
-rw-r--r--deps/uv/src/unix/core.c9
-rw-r--r--deps/uv/src/unix/fs.c29
-rw-r--r--deps/uv/src/unix/internal.h1
-rw-r--r--deps/uv/src/unix/kqueue.c4
-rw-r--r--deps/uv/src/unix/linux-core.c5
-rw-r--r--deps/uv/src/unix/linux-inotify.c2
-rw-r--r--deps/uv/src/unix/loop.c2
-rw-r--r--deps/uv/src/unix/pipe.c3
-rw-r--r--deps/uv/src/unix/poll.c3
-rw-r--r--deps/uv/src/unix/signal.c39
-rw-r--r--deps/uv/src/unix/stream.c3
-rw-r--r--deps/uv/src/unix/tcp.c3
-rw-r--r--deps/uv/src/unix/udp.c3
-rw-r--r--deps/uv/src/uv-common.h4
-rw-r--r--deps/uv/src/win/async.c4
-rw-r--r--deps/uv/src/win/atomicops-inl.h8
-rw-r--r--deps/uv/src/win/core.c73
-rw-r--r--deps/uv/src/win/error.c4
-rw-r--r--deps/uv/src/win/fs.c129
-rw-r--r--deps/uv/src/win/getaddrinfo.c25
-rw-r--r--deps/uv/src/win/handle-inl.h8
-rw-r--r--deps/uv/src/win/internal.h34
-rw-r--r--deps/uv/src/win/pipe.c1058
-rw-r--r--deps/uv/src/win/poll.c41
-rw-r--r--deps/uv/src/win/process-stdio.c58
-rw-r--r--deps/uv/src/win/process.c51
-rw-r--r--deps/uv/src/win/signal.c34
-rw-r--r--deps/uv/src/win/stream.c34
-rw-r--r--deps/uv/src/win/tcp.c183
-rw-r--r--deps/uv/src/win/thread.c229
-rw-r--r--deps/uv/src/win/timer.c2
-rw-r--r--deps/uv/src/win/tty.c129
-rw-r--r--deps/uv/src/win/udp.c89
-rw-r--r--deps/uv/src/win/util.c84
-rw-r--r--deps/uv/src/win/winapi.c67
-rw-r--r--deps/uv/src/win/winapi.h84
-rw-r--r--deps/uv/src/win/winsock.c8
-rw-r--r--deps/uv/test/benchmark-async-pummel.c2
-rw-r--r--deps/uv/test/run-tests.c5
-rw-r--r--deps/uv/test/runner-unix.c13
-rw-r--r--deps/uv/test/runner-win.c4
-rw-r--r--deps/uv/test/runner.h13
-rw-r--r--deps/uv/test/task.h2
-rw-r--r--deps/uv/test/test-callback-stack.c15
-rw-r--r--deps/uv/test/test-connection-fail.c4
-rw-r--r--deps/uv/test/test-delayed-accept.c4
-rw-r--r--deps/uv/test/test-fork.c9
-rw-r--r--deps/uv/test/test-fs-copyfile.c2
-rw-r--r--deps/uv/test/test-fs.c169
-rw-r--r--deps/uv/test/test-hrtime.c6
-rw-r--r--deps/uv/test/test-ipc-heavy-traffic-deadlock-bug.c158
-rw-r--r--deps/uv/test/test-ipc-send-recv.c5
-rw-r--r--deps/uv/test/test-ipc.c15
-rw-r--r--deps/uv/test/test-list.h26
-rw-r--r--deps/uv/test/test-loop-handles.c16
-rw-r--r--deps/uv/test/test-ping-pong.c89
-rw-r--r--deps/uv/test/test-pipe-set-fchmod.c4
-rw-r--r--deps/uv/test/test-process-title-threadsafe.c2
-rw-r--r--deps/uv/test/test-signal-multiple-loops.c2
-rw-r--r--deps/uv/test/test-spawn.c8
-rw-r--r--deps/uv/test/test-tcp-open.c14
-rw-r--r--deps/uv/test/test-timer-again.c4
-rw-r--r--deps/uv/test/test-udp-alloc-cb-fail.c3
-rw-r--r--deps/uv/test/test-udp-multicast-join.c3
-rw-r--r--deps/uv/test/test-udp-multicast-join6.c3
-rw-r--r--deps/uv/test/test-udp-open.c17
-rw-r--r--deps/uv/test/test-udp-options.c19
-rw-r--r--deps/uv/test/test-udp-send-and-recv.c6
-rw-r--r--deps/uv/test/test-udp-send-immediate.c3
-rw-r--r--deps/uv/test/test.gyp3
-rw-r--r--deps/uv/uv.gyp24
109 files changed, 2345 insertions, 1690 deletions
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index b605a0f3bc..eb8501aab1 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -338,3 +338,8 @@ zzzjim <zzzjim@users.noreply.github.com>
Alex Arslan <ararslan@comcast.net>
Kyle Farnung <kfarnung@microsoft.com>
ssrlive <30760636+ssrlive@users.noreply.github.com>
+Tobias Nießen <tniessen@tnie.de>
+Björn Linse <bjorn.linse@gmail.com>
+zyxwvu Shi <i@shiyc.cn>
+Peter Johnson <johnson.peter@gmail.com>
+Paolo Greppi <paolo.greppi@libpf.com>
diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt
new file mode 100644
index 0000000000..f13e529563
--- /dev/null
+++ b/deps/uv/CMakeLists.txt
@@ -0,0 +1,381 @@
+# TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390".
+cmake_minimum_required(VERSION 3.0)
+project(libuv)
+enable_testing()
+
+if(MSVC)
+ list(APPEND uv_cflags /W4)
+elseif(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
+ list(APPEND uv_cflags -fvisibility=hidden --std=gnu89)
+ list(APPEND uv_cflags -Wall -Wextra -Wstrict-prototypes)
+ list(APPEND uv_cflags -Wno-unused-parameter)
+endif()
+
+set(uv_sources
+ src/fs-poll.c
+ src/inet.c
+ src/threadpool.c
+ src/uv-common.c
+ src/uv-data-getter-setters.c
+ src/version.c)
+
+set(uv_test_sources
+ test/blackhole-server.c
+ test/echo-server.c
+ test/run-tests.c
+ test/runner.c
+ test/test-active.c
+ test/test-async-null-cb.c
+ test/test-async.c
+ test/test-barrier.c
+ test/test-callback-order.c
+ test/test-callback-stack.c
+ test/test-close-fd.c
+ test/test-close-order.c
+ test/test-condvar.c
+ test/test-connect-unspecified.c
+ test/test-connection-fail.c
+ test/test-cwd-and-chdir.c
+ test/test-default-loop-close.c
+ test/test-delayed-accept.c
+ test/test-dlerror.c
+ test/test-eintr-handling.c
+ test/test-embed.c
+ test/test-emfile.c
+ test/test-env-vars.c
+ test/test-error.c
+ test/test-fail-always.c
+ test/test-fork.c
+ test/test-fs-copyfile.c
+ test/test-fs-event.c
+ test/test-fs-poll.c
+ test/test-fs.c
+ test/test-get-currentexe.c
+ test/test-get-loadavg.c
+ test/test-get-memory.c
+ test/test-get-passwd.c
+ test/test-getaddrinfo.c
+ test/test-gethostname.c
+ test/test-getnameinfo.c
+ test/test-getsockname.c
+ test/test-getters-setters.c
+ test/test-handle-fileno.c
+ test/test-homedir.c
+ test/test-hrtime.c
+ test/test-idle.c
+ test/test-ip4-addr.c
+ test/test-ip6-addr.c
+ test/test-ip6-addr.c
+ test/test-ipc-heavy-traffic-deadlock-bug.c
+ test/test-ipc-send-recv.c
+ test/test-ipc.c
+ test/test-loop-alive.c
+ test/test-loop-close.c
+ test/test-loop-configure.c
+ test/test-loop-handles.c
+ test/test-loop-stop.c
+ test/test-loop-time.c
+ test/test-multiple-listen.c
+ test/test-mutexes.c
+ test/test-osx-select.c
+ test/test-pass-always.c
+ test/test-ping-pong.c
+ test/test-pipe-bind-error.c
+ test/test-pipe-close-stdout-read-stdin.c
+ test/test-pipe-connect-error.c
+ test/test-pipe-connect-multiple.c
+ test/test-pipe-connect-prepare.c
+ test/test-pipe-getsockname.c
+ test/test-pipe-pending-instances.c
+ test/test-pipe-sendmsg.c
+ test/test-pipe-server-close.c
+ test/test-pipe-set-fchmod.c
+ test/test-pipe-set-non-blocking.c
+ test/test-platform-output.c
+ test/test-poll-close-doesnt-corrupt-stack.c
+ test/test-poll-close.c
+ test/test-poll-closesocket.c
+ test/test-poll-oob.c
+ test/test-poll.c
+ test/test-process-title-threadsafe.c
+ test/test-process-title.c
+ test/test-queue-foreach-delete.c
+ test/test-ref.c
+ test/test-run-nowait.c
+ test/test-run-once.c
+ test/test-semaphore.c
+ test/test-shutdown-close.c
+ test/test-shutdown-eof.c
+ test/test-shutdown-twice.c
+ test/test-signal-multiple-loops.c
+ test/test-signal.c
+ test/test-socket-buffer-size.c
+ test/test-spawn.c
+ test/test-stdio-over-pipes.c
+ test/test-tcp-alloc-cb-fail.c
+ test/test-tcp-bind-error.c
+ test/test-tcp-bind6-error.c
+ test/test-tcp-close-accept.c
+ test/test-tcp-close-while-connecting.c
+ test/test-tcp-close.c
+ test/test-tcp-connect-error-after-write.c
+ test/test-tcp-connect-error.c
+ test/test-tcp-connect-timeout.c
+ test/test-tcp-connect6-error.c
+ test/test-tcp-create-socket-early.c
+ test/test-tcp-flags.c
+ test/test-tcp-oob.c
+ test/test-tcp-open.c
+ test/test-tcp-read-stop.c
+ test/test-tcp-shutdown-after-write.c
+ test/test-tcp-try-write.c
+ test/test-tcp-unexpected-read.c
+ test/test-tcp-write-after-connect.c
+ test/test-tcp-write-fail.c
+ test/test-tcp-write-queue-order.c
+ test/test-tcp-write-to-half-open-connection.c
+ test/test-tcp-writealot.c
+ test/test-thread-equal.c
+ test/test-thread.c
+ test/test-threadpool-cancel.c
+ test/test-threadpool.c
+ test/test-timer-again.c
+ test/test-timer-from-check.c
+ test/test-timer.c
+ test/test-tmpdir.c
+ test/test-tty.c
+ test/test-udp-alloc-cb-fail.c
+ test/test-udp-bind.c
+ test/test-udp-create-socket-early.c
+ test/test-udp-dgram-too-big.c
+ test/test-udp-ipv6.c
+ test/test-udp-multicast-interface.c
+ test/test-udp-multicast-interface6.c
+ test/test-udp-multicast-join.c
+ test/test-udp-multicast-join6.c
+ test/test-udp-multicast-ttl.c
+ test/test-udp-open.c
+ test/test-udp-options.c
+ test/test-udp-send-and-recv.c
+ test/test-udp-send-hang-loop.c
+ test/test-udp-send-immediate.c
+ test/test-udp-send-unreachable.c
+ test/test-udp-try-send.c
+ test/test-walk-handles.c
+ test/test-watcher-cross-stop.c)
+
+if(WIN32)
+ list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0600)
+ list(APPEND uv_libraries
+ advapi32
+ iphlpapi
+ psapi
+ shell32
+ user32
+ userenv
+ ws2_32)
+ list(APPEND uv_sources
+ src/win/async.c
+ src/win/core.c
+ src/win/detect-wakeup.c
+ src/win/dl.c
+ src/win/error.c
+ src/win/fs.c
+ src/win/fs-event.c
+ src/win/getaddrinfo.c
+ src/win/getnameinfo.c
+ src/win/handle.c
+ src/win/loop-watcher.c
+ src/win/pipe.c
+ src/win/thread.c
+ src/win/poll.c
+ src/win/process.c
+ src/win/process-stdio.c
+ src/win/req.c
+ src/win/signal.c
+ src/win/snprintf.c
+ src/win/stream.c
+ src/win/tcp.c
+ src/win/tty.c
+ src/win/timer.c
+ src/win/udp.c
+ src/win/util.c
+ src/win/winapi.c
+ src/win/winsock.c)
+ list(APPEND uv_test_libraries ws2_32)
+ list(APPEND uv_test_sources src/win/snprintf.c test/runner-win.c)
+else()
+ list(APPEND uv_defines _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE)
+ list(APPEND uv_libraries pthread)
+ list(APPEND uv_sources
+ src/unix/async.c
+ src/unix/core.c
+ src/unix/dl.c
+ src/unix/fs.c
+ src/unix/getaddrinfo.c
+ src/unix/getnameinfo.c
+ src/unix/loop-watcher.c
+ src/unix/loop.c
+ src/unix/pipe.c
+ src/unix/poll.c
+ src/unix/process.c
+ src/unix/signal.c
+ src/unix/stream.c
+ src/unix/tcp.c
+ src/unix/thread.c
+ src/unix/timer.c
+ src/unix/tty.c
+ src/unix/udp.c)
+ list(APPEND uv_test_sources test/runner-unix.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+ list(APPEND uv_defines
+ _ALL_SOURCE
+ _LINUX_SOURCE_COMPAT
+ _THREAD_SAFE
+ _XOPEN_SOURCE=500)
+ list(APPEND uv_libraries perfstat)
+ list(APPEND uv_sources src/unix/aix.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Android")
+ list(APPEND uv_libs dl)
+ list(APPEND uv_sources
+ src/unix/android-ifaddrs.c
+ src/unix/linux-core.c
+ src/unix/linux-inotify.c
+ src/unix/linux-syscalls.c
+ src/unix/procfs-exepath.c
+ src/unix/pthread-fixes.c
+ src/unix/sysinfo-loadavg.c
+ src/unix/sysinfo-memory.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|Linux|OS/390")
+ list(APPEND uv_sources src/unix/proctitle.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
+ list(APPEND uv_sources src/unix/freebsd.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
+ list(APPEND uv_sources src/unix/posix-hrtime.c)
+ list(APPEND uv_libraries kvm)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin|DragonFly|FreeBSD|NetBSD|OpenBSD")
+ list(APPEND uv_sources src/unix/bsd-ifaddrs.c src/unix/kqueue.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1)
+ list(APPEND uv_sources
+ src/unix/darwin-proctitle.c
+ src/unix/darwin.c
+ src/unix/fsevents.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112)
+ list(APPEND uv_libraries dl rt)
+ list(APPEND uv_sources
+ src/unix/linux-core.c
+ src/unix/linux-inotify.c
+ src/unix/linux-syscalls.c
+ src/unix/procfs-exepath.c
+ src/unix/sysinfo-loadavg.c
+ src/unix/sysinfo-memory.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
+ list(APPEND uv_sources src/unix/netbsd.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
+ list(APPEND uv_sources src/unix/openbsd.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "OS/390")
+ list(APPEND uv_defines PATH_MAX=255)
+ list(APPEND uv_defines _AE_BIMODAL)
+ list(APPEND uv_defines _ALL_SOURCE)
+ list(APPEND uv_defines _LARGE_TIME_API)
+ list(APPEND uv_defines _OPEN_MSGQ_EXT)
+ list(APPEND uv_defines _OPEN_SYS_FILE_EXT)
+ list(APPEND uv_defines _OPEN_SYS_IF_EXT)
+ list(APPEND uv_defines _OPEN_SYS_SOCK_IPV6)
+ list(APPEND uv_defines _UNIX03_SOURCE)
+ list(APPEND uv_defines _UNIX03_THREADS)
+ list(APPEND uv_defines _UNIX03_WITHDRAWN)
+ list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED)
+ list(APPEND uv_sources
+ src/unix/pthread-fixes.c
+ src/unix/pthread-barrier.c
+ src/unix/os390.c
+ src/unix/os390-syscalls.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+ list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500)
+ list(APPEND uv_libraries kstat nsl sendfile socket)
+ list(APPEND uv_sources src/unix/no-proctitle.c src/unix/sunos.c)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin|DragonFly|FreeBSD|Linux|NetBSD|OpenBSD")
+ list(APPEND uv_test_libraries util)
+endif()
+
+add_library(uv SHARED ${uv_sources})
+target_compile_definitions(uv PRIVATE ${uv_defines} BUILDING_UV_SHARED=1)
+target_compile_options(uv PRIVATE ${uv_cflags})
+target_include_directories(uv PRIVATE include src)
+target_link_libraries(uv ${uv_libraries})
+
+add_library(uv_a STATIC ${uv_sources})
+target_compile_definitions(uv_a PRIVATE ${uv_defines})
+target_compile_options(uv_a PRIVATE ${uv_cflags})
+target_include_directories(uv_a PRIVATE include src)
+target_link_libraries(uv_a ${uv_libraries})
+
+if(BUILD_TESTING)
+ include(CTest)
+ add_executable(uv_run_tests ${uv_test_sources})
+ target_compile_definitions(uv_run_tests PRIVATE ${uv_defines})
+ target_compile_options(uv_run_tests PRIVATE ${uv_cflags})
+ target_include_directories(uv_run_tests PRIVATE include)
+ target_link_libraries(uv_run_tests uv ${uv_test_libraries})
+ add_test(NAME uv_test
+ COMMAND uv_run_tests
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+ add_executable(uv_run_tests_a ${uv_test_sources})
+ target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines})
+ target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags})
+ target_include_directories(uv_run_tests_a PRIVATE include)
+ target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries})
+ add_test(NAME uv_test_a
+ COMMAND uv_run_tests_a
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+endif()
+
+if(UNIX)
+ # Now for some gibbering horrors from beyond the stars...
+ include(GNUInstallDirs)
+ foreach(x ${uv_libraries})
+ set(LIBS "${LIBS} -l${x}")
+ endforeach(x)
+ file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
+ string(REGEX MATCH [0-9]+[.][0-9]+[.][0-9]+ PACKAGE_VERSION "${configure_ac}")
+ set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
+ set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
+ set(prefix ${CMAKE_INSTALL_PREFIX})
+ configure_file(libuv.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc @ONLY)
+
+ install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+ install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
+ install(FILES LICENSE ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+ install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+endif()
diff --git a/deps/uv/CONTRIBUTING.md b/deps/uv/CONTRIBUTING.md
index d9bf0472fb..f22e124e3b 100644
--- a/deps/uv/CONTRIBUTING.md
+++ b/deps/uv/CONTRIBUTING.md
@@ -137,7 +137,10 @@ $ git rebase upstream/v1.x # or upstream/master
### TEST
Bug fixes and features should come with tests. Add your tests in the
-`test/` directory. Each new test needs to be registered in `test/test-list.h`. If you add a new test file, it needs to be registered in two places:
+`test/` directory. Each new test needs to be registered in `test/test-list.h`.
+
+If you add a new test file, it needs to be registered in three places:
+- `CMakeLists.txt`: add the file's name to the `uv_test_sources` list.
- `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list.
- `uv.gyp`: add the file's name to the `sources` list in the `run-tests` target.
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index 0ec1488412..3569d5d575 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,3 +1,100 @@
+2018.06.23, Version 1.21.0 (Stable), e4983a9b0c152932f7553ff4a9ff189d2314cdcb
+
+Changes since version 1.20.3:
+
+* unix,windows: map EFTYPE errno (cjihrig)
+
+* win: perform case insensitive PATH= comparison (cjihrig)
+
+* win, fs: uv_fs_fchmod support for -A files (Bartosz Sosnowski)
+
+* src,lib: fix comments (Tobias Nießen)
+
+* win,process: allow child pipe handles to be opened in overlapped mode (Björn
+ Linse)
+
+* src,test: fix idiosyncratic comment style (Bert Belder)
+
+* test: fs_fchmod_archive_readonly must return a value (Bert Belder)
+
+* win,pipe: fix incorrect error code returned from uv_pipe_write_impl() (Bert
+ Belder)
+
+* win,pipe: properly set uv_write_t.send_handle in uv_write2() (Bert Belder)
+
+* test: add vectored uv_write() ping-pong tests (Bert Belder)
+
+* win,pipe: support vectored uv_write() calls (Bert Belder)
+
+* win,pipe: refactor pipe read cancellation logic (Bert Belder)
+
+* test: improve output from IPC test helpers (Bert Belder)
+
+* test: add test for IPC deadlock on Windows (
+
+* win,pipe: fix IPC pipe deadlock (Bert Belder)
+
+* unix: catch some cases of watching fd twice (Ben Noordhuis)
+
+* test: use custom timeout for getaddrinfo_fail_sync (Ben Noordhuis)
+
+* Revert "win: add Windows XP support to uv_if_indextoname()" (Bert Belder)
+
+* win,thread: remove fallback uv_cond implementation (Bert Belder)
+
+* src,test: s/olny/only (cjihrig)
+
+* unix: close signal pipe fds on unload (Ben Noordhuis)
+
+* win: allow setting udp socket options before bind (cjihrig)
+
+* unix: return UV_ENOTSUP on FICLONE_FORCE failure (cjihrig)
+
+* win,pipe: remove unreferenced local variable (Bert Belder)
+
+* win,code: remove GetQueuedCompletionStatus-based poller (Bert Belder)
+
+* win: remove the remaining dynamic kernel32 imports (Bert Belder)
+
+* test: speedup process-title-threadsafe on macOS (cjihrig)
+
+* core: move all include files except uv.h to uv/ (Saúl Ibarra Corretgé)
+
+* win: move stdint-msvc2008.h to include/uv/ (Ben Noordhuis)
+
+* build: fix cygwin install (Ben Noordhuis)
+
+* build,win: remove MinGW Makefile (Saúl Ibarra Corretgé)
+
+* build: add a cmake build file (Ben Noordhuis)
+
+* build: add test suite option to cmake build (Ben Noordhuis)
+
+* unix: set errno in uv_fs_copyfile() (cjihrig)
+
+* samples: fix inconsistency in parse_opts vs usage (zyxwvu Shi)
+
+* linux: handle exclusive POLLHUP with UV_DISCONNECT (Brad King)
+
+* include: declare uv_cpu_times_s in higher scope (Peter Johnson)
+
+* doc: add uv_fs_fsync() AIX limitations (jBarz)
+
+* unix,win: add uv_fs_lchown() (Paolo Greppi)
+
+* unix: disable clang variable length array warning (Peter Johnson)
+
+* doc: document uv_pipe_t::ipc (Ed Schouten)
+
+* doc: undocument uv_req_type's UV_REQ_TYPE_PRIVATE (Ed Schouten)
+
+* doc: document UV_*_MAP() macros (Ed Schouten)
+
+* win: remove use of min() macro in pipe.c (Peter Johnson)
+
+* doc: add jbarz as maintainer (
+
+
2018.05.08, Version 1.20.3 (Stable), 8cfd67e59195251dff793ee47c185c9d6a8f3818
Changes since version 1.20.2:
diff --git a/deps/uv/MAINTAINERS.md b/deps/uv/MAINTAINERS.md
index d85deb0066..a895780fc1 100644
--- a/deps/uv/MAINTAINERS.md
+++ b/deps/uv/MAINTAINERS.md
@@ -14,6 +14,7 @@ libuv is currently managed by the following individuals:
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
* **Imran Iqbal** ([@iWuzHere](https://github.com/iWuzHere))
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
+* **John Barboza** ([@jbarz](https://github.com/jbarz))
* **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno))
- GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno)
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am
index ae9d96bcf6..5f07dba23a 100644
--- a/deps/uv/Makefile.am
+++ b/deps/uv/Makefile.am
@@ -17,7 +17,10 @@ ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_srcdir)/src
-include_HEADERS=include/uv.h include/uv-errno.h include/uv-threadpool.h include/uv-version.h
+include_HEADERS=include/uv.h
+
+uvincludedir = $(includedir)/uv
+uvinclude_HEADERS=include/uv/errno.h include/uv/threadpool.h include/uv/version.h
CLEANFILES =
@@ -42,7 +45,7 @@ endif
if WINNT
-include_HEADERS += include/uv-win.h include/tree.h
+uvinclude_HEADERS += include/uv/win.h include/uv/tree.h
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
-DWIN32_LEAN_AND_MEAN \
-D_WIN32_WINNT=0x0600
@@ -82,7 +85,7 @@ libuv_la_SOURCES += src/win/async.c \
else # WINNT
-include_HEADERS += include/uv-unix.h
+uvinclude_HEADERS += include/uv/unix.h
AM_CPPFLAGS += -I$(top_srcdir)/src/unix
libuv_la_SOURCES += src/unix/async.c \
src/unix/atomic-ops.h \
@@ -121,7 +124,6 @@ EXTRA_DIST = test/fixtures/empty_file \
README.md \
checksparse.sh \
vcbuild.bat \
- Makefile.mingw \
common.gypi \
gyp_uv.py \
uv.gyp
@@ -191,6 +193,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-idle.c \
test/test-ip4-addr.c \
test/test-ip6-addr.c \
+ test/test-ipc-heavy-traffic-deadlock-bug.c \
test/test-ipc-send-recv.c \
test/test-ipc.c \
test/test-list.h \
@@ -332,19 +335,19 @@ libuv_la_CFLAGS += -D_ALL_SOURCE \
-D_LINUX_SOURCE_COMPAT \
-D_THREAD_SAFE \
-DHAVE_SYS_AHAFS_EVPRODS_H
-include_HEADERS += include/uv-aix.h
+uvinclude_HEADERS += include/uv/aix.h
libuv_la_SOURCES += src/unix/aix.c src/unix/aix-common.c
endif
if ANDROID
-include_HEADERS += include/android-ifaddrs.h \
- include/pthread-barrier.h
+uvinclude_HEADERS += include/uv/android-ifaddrs.h \
+ include/uv/pthread-barrier.h
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
src/unix/pthread-fixes.c
endif
if CYGWIN
-include_HEADERS += include/uv-posix.h
+uvinclude_HEADERS += include/uv/posix.h
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/cygwin.c \
src/unix/bsd-ifaddrs.c \
@@ -358,8 +361,8 @@ libuv_la_SOURCES += src/unix/cygwin.c \
endif
if DARWIN
-include_HEADERS += include/uv-darwin.h \
- include/pthread-barrier.h
+uvinclude_HEADERS += include/uv/darwin.h \
+ include/uv/pthread-barrier.h
libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1
libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
@@ -372,7 +375,7 @@ test_run_tests_LDFLAGS += -lutil
endif
if DRAGONFLY
-include_HEADERS += include/uv-bsd.h
+uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/freebsd.c \
src/unix/kqueue.c \
@@ -381,7 +384,7 @@ test_run_tests_LDFLAGS += -lutil
endif
if FREEBSD
-include_HEADERS += include/uv-bsd.h
+uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/freebsd.c \
src/unix/kqueue.c \
@@ -390,7 +393,7 @@ test_run_tests_LDFLAGS += -lutil
endif
if LINUX
-include_HEADERS += include/uv-linux.h
+uvinclude_HEADERS += include/uv/linux.h
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/linux-core.c \
src/unix/linux-inotify.c \
@@ -417,7 +420,7 @@ libuv_la_SOURCES += src/unix/cygwin.c \
endif
if NETBSD
-include_HEADERS += include/uv-bsd.h
+uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/kqueue.c \
src/unix/netbsd.c \
@@ -426,7 +429,7 @@ test_run_tests_LDFLAGS += -lutil
endif
if OPENBSD
-include_HEADERS += include/uv-bsd.h
+uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/kqueue.c \
src/unix/openbsd.c \
@@ -435,14 +438,14 @@ test_run_tests_LDFLAGS += -lutil
endif
if SUNOS
-include_HEADERS += include/uv-sunos.h
+uvinclude_HEADERS += include/uv/sunos.h
libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
libuv_la_SOURCES += src/unix/no-proctitle.c \
src/unix/sunos.c
endif
if OS390
-include_HEADERS += include/pthread-barrier.h
+uvinclude_HEADERS += include/uv/pthread-barrier.h
libuv_la_CFLAGS += -D_UNIX03_THREADS \
-D_UNIX03_SOURCE \
-D_OPEN_SYS_IF_EXT=1 \
diff --git a/deps/uv/Makefile.mingw b/deps/uv/Makefile.mingw
deleted file mode 100644
index 3acf9e14a9..0000000000
--- a/deps/uv/Makefile.mingw
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-CC ?= gcc
-
-CFLAGS += -Wall \
- -Wextra \
- -Wno-unused-parameter \
- -Wstrict-prototypes \
- -Iinclude \
- -Isrc \
- -Isrc/win \
- -DWIN32_LEAN_AND_MEAN \
- -D_WIN32_WINNT=0x0600
-
-INCLUDES = include/stdint-msvc2008.h \
- include/tree.h \
- include/uv-errno.h \
- include/uv-threadpool.h \
- include/uv-version.h \
- include/uv-win.h \
- include/uv.h \
- src/heap-inl.h \
- src/queue.h \
- src/uv-common.h \
- src/win/atomicops-inl.h \
- src/win/handle-inl.h \
- src/win/internal.h \
- src/win/req-inl.h \
- src/win/stream-inl.h \
- src/win/winapi.h \
- src/win/winsock.h
-
-OBJS = src/fs-poll.o \
- src/inet.o \
- src/threadpool.o \
- src/uv-common.o \
- src/version.o \
- src/win/async.o \
- src/win/core.o \
- src/win/detect-wakeup.o \
- src/win/dl.o \
- src/win/error.o \
- src/win/fs-event.o \
- src/win/fs.o \
- src/win/getaddrinfo.o \
- src/win/getnameinfo.o \
- src/win/handle.o \
- src/win/loop-watcher.o \
- src/win/pipe.o \
- src/win/poll.o \
- src/win/process-stdio.o \
- src/win/process.o \
- src/win/req.o \
- src/win/signal.o \
- src/win/stream.o \
- src/win/tcp.o \
- src/win/thread.o \
- src/win/timer.o \
- src/win/tty.o \
- src/win/udp.o \
- src/win/util.o \
- src/win/winapi.o \
- src/win/winsock.o
-
-all: libuv.a
-
-clean:
- -$(RM) $(OBJS) libuv.a
-
-libuv.a: $(OBJS)
- $(AR) crs $@ $^
-
-$(OBJS): %.o : %.c $(INCLUDES)
- $(CC) $(CFLAGS) -c -o $@ $<
diff --git a/deps/uv/README.md b/deps/uv/README.md
index d42ada56a8..f6e7288ded 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -169,6 +169,16 @@ $ make check
$ make install
```
+To build with [CMake](https://cmake.org/):
+
+```bash
+$ mkdir -p out/cmake ; cd out/cmake ; cmake -DBUILD_TESTING=ON ../..
+$ make all test
+# Or manually:
+$ ./uv_run_tests # shared library build
+$ ./uv_run_tests_a # static library build
+```
+
To build with GYP, first run:
```bash
diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh
index d8b50bc4fe..91f130d4f5 100755
--- a/deps/uv/checksparse.sh
+++ b/deps/uv/checksparse.sh
@@ -26,8 +26,8 @@ SPARSE_FLAGS=${SPARSE_FLAGS:-"
"}
SOURCES="
-include/tree.h
-include/uv-unix.h
+include/uv/tree.h
+include/uv/unix.h
include/uv.h
src/fs-poll.c
src/inet.c
@@ -113,6 +113,7 @@ test/test-homedir.c
test/test-hrtime.c
test/test-idle.c
test/test-ip6-addr.c
+test/test-ipc-heavy-traffic-deadlock-bug.c
test/test-ipc-send-recv.c
test/test-ipc.c
test/test-loop-handles.c
@@ -195,7 +196,7 @@ OS400)
Darwin)
SPARSE_FLAGS="$SPARSE_FLAGS -D__APPLE__=1"
SOURCES="$SOURCES
- include/uv-bsd.h
+ include/uv/bsd.h
src/unix/darwin.c
src/unix/kqueue.c
src/unix/fsevents.c"
@@ -203,21 +204,21 @@ Darwin)
DragonFly)
SPARSE_FLAGS="$SPARSE_FLAGS -D__DragonFly__=1"
SOURCES="$SOURCES
- include/uv-bsd.h
+ include/uv/bsd.h
src/unix/kqueue.c
src/unix/freebsd.c"
;;
FreeBSD)
SPARSE_FLAGS="$SPARSE_FLAGS -D__FreeBSD__=1"
SOURCES="$SOURCES
- include/uv-bsd.h
+ include/uv/bsd.h
src/unix/kqueue.c
src/unix/freebsd.c"
;;
Linux)
SPARSE_FLAGS="$SPARSE_FLAGS -D__linux__=1"
SOURCES="$SOURCES
- include/uv-linux.h
+ include/uv/linux.h
src/unix/linux-inotify.c
src/unix/linux-core.c
src/unix/linux-syscalls.c
@@ -226,21 +227,21 @@ Linux)
NetBSD)
SPARSE_FLAGS="$SPARSE_FLAGS -D__NetBSD__=1"
SOURCES="$SOURCES
- include/uv-bsd.h
+ include/uv/bsd.h
src/unix/kqueue.c
src/unix/netbsd.c"
;;
OpenBSD)
SPARSE_FLAGS="$SPARSE_FLAGS -D__OpenBSD__=1"
SOURCES="$SOURCES
- include/uv-bsd.h
+ include/uv/bsd.h
src/unix/kqueue.c
src/unix/openbsd.c"
;;
SunOS)
SPARSE_FLAGS="$SPARSE_FLAGS -D__sun=1"
SOURCES="$SOURCES
- include/uv-sunos.h
+ include/uv/sunos.h
src/unix/sunos.c"
;;
esac
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index 5178c60ba1..c3a6a77969 100644
--- a/deps/uv/configure.ac
+++ b/deps/uv/configure.ac
@@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
-AC_INIT([libuv], [1.20.3], [https://github.com/libuv/libuv/issues])
+AC_INIT([libuv], [1.21.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
diff --git a/deps/uv/docs/src/conf.py b/deps/uv/docs/src/conf.py
index c9b4ea38c3..f6f43253d3 100644
--- a/deps/uv/docs/src/conf.py
+++ b/deps/uv/docs/src/conf.py
@@ -18,7 +18,7 @@ import sys
def get_libuv_version():
- with open('../../include/uv-version.h') as f:
+ with open('../../include/uv/version.h') as f:
data = f.read()
try:
m = re.search(r"""^#define UV_VERSION_MAJOR (\d+)$""", data, re.MULTILINE)
diff --git a/deps/uv/docs/src/errors.rst b/deps/uv/docs/src/errors.rst
index 4e30447bf1..7c3f95d760 100644
--- a/deps/uv/docs/src/errors.rst
+++ b/deps/uv/docs/src/errors.rst
@@ -323,6 +323,13 @@ Error constants
API
---
+.. c:function:: UV_ERRNO_MAP(iter_macro)
+
+ Macro that expands to a series of invocations of `iter_macro` for
+ each of the error constants above. `iter_macro` is invoked with two
+ arguments: the name of the error constant without the `UV_` prefix,
+ and the error message string literal.
+
.. c:function:: const char* uv_strerror(int err)
Returns the error message for the given error code. Leaks a few bytes
diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst
index 8e8fc2f1d5..a390f1409d 100644
--- a/deps/uv/docs/src/fs.rst
+++ b/deps/uv/docs/src/fs.rst
@@ -92,6 +92,7 @@ Data types
UV_FS_READLINK,
UV_FS_CHOWN,
UV_FS_FCHOWN,
+ UV_FS_LCHOWN,
UV_FS_REALPATH,
UV_FS_COPYFILE
} uv_fs_type;
@@ -234,6 +235,10 @@ API
Equivalent to :man:`fsync(2)`.
+ .. note::
+ For AIX, `uv_fs_fsync` returns `UV_EBADF` on file descriptors referencing
+ non regular files.
+
.. c:function:: int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
Equivalent to :man:`fdatasync(2)`.
@@ -345,12 +350,15 @@ API
.. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
.. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
+.. c:function:: int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
- Equivalent to :man:`chown(2)` and :man:`fchown(2)` respectively.
+ Equivalent to :man:`chown(2)`, :man:`fchown(2)` and :man:`lchown(2)` respectively.
.. note::
These functions are not implemented on Windows.
+ .. versionchanged:: 1.21.0 implemented uv_fs_lchown
+
.. c:function:: uv_fs_type uv_fs_get_type(const uv_fs_t* req)
Returns `req->fs_type`.
diff --git a/deps/uv/docs/src/handle.rst b/deps/uv/docs/src/handle.rst
index cdfb76bf8c..86fa811d3f 100644
--- a/deps/uv/docs/src/handle.rst
+++ b/deps/uv/docs/src/handle.rst
@@ -101,6 +101,14 @@ Public members
API
---
+.. c:function:: UV_HANDLE_TYPE_MAP(iter_macro)
+
+ Macro that expands to a series of invocations of `iter_macro` for
+ each of the handle types. `iter_macro` is invoked with two
+ arguments: the name of the `uv_handle_type` element without the
+ `UV_` prefix, and the name of the corresponding structure type
+ without the `uv_` prefix and `_t` suffix.
+
.. c:function:: int uv_is_active(const uv_handle_t* handle)
Returns non-zero if the handle is active, zero if it's inactive. What
diff --git a/deps/uv/docs/src/pipe.rst b/deps/uv/docs/src/pipe.rst
index bdaeeba9d4..376d6117bb 100644
--- a/deps/uv/docs/src/pipe.rst
+++ b/deps/uv/docs/src/pipe.rst
@@ -21,7 +21,9 @@ Data types
Public members
^^^^^^^^^^^^^^
-N/A
+.. c:member:: int uv_pipe_t.ipc
+
+ Whether this pipe is suitable for handle passing between processes.
.. seealso:: The :c:type:`uv_stream_t` members also apply.
diff --git a/deps/uv/docs/src/process.rst b/deps/uv/docs/src/process.rst
index ecc3cbf348..bc968554e1 100644
--- a/deps/uv/docs/src/process.rst
+++ b/deps/uv/docs/src/process.rst
@@ -109,6 +109,11 @@ Data types
*/
UV_READABLE_PIPE = 0x10,
UV_WRITABLE_PIPE = 0x20
+ /*
+ * Open the child pipe handle in overlapped mode on Windows.
+ * On Unix it is silently ignored.
+ */
+ UV_OVERLAPPED_PIPE = 0x40
} uv_stdio_flags;
diff --git a/deps/uv/docs/src/request.rst b/deps/uv/docs/src/request.rst
index 54d9a2f309..56038287b2 100644
--- a/deps/uv/docs/src/request.rst
+++ b/deps/uv/docs/src/request.rst
@@ -46,7 +46,6 @@ Public members
UV_WORK,
UV_GETADDRINFO,
UV_GETNAMEINFO,
- UV_REQ_TYPE_PRIVATE,
UV_REQ_TYPE_MAX,
} uv_req_type;
@@ -54,6 +53,14 @@ Public members
API
---
+.. c:function:: UV_REQ_TYPE_MAP(iter_macro)
+
+ Macro that expands to a series of invocations of `iter_macro` for
+ each of the request types. `iter_macro` is invoked with two
+ arguments: the name of the `uv_req_type` element without the `UV_`
+ prefix, and the name of the corresponding structure type without the
+ `uv_` prefix and `_t` suffix.
+
.. c:function:: int uv_cancel(uv_req_t* req)
Cancel a pending request. Fails if the request is executing or has finished
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index 41fad45108..91451ada78 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -45,21 +45,21 @@ extern "C" {
# define UV_EXTERN /* nothing */
#endif
-#include "uv-errno.h"
-#include "uv-version.h"
+#include "uv/errno.h"
+#include "uv/version.h"
#include <stddef.h>
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "stdint-msvc2008.h"
+# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
#if defined(_WIN32)
-# include "uv-win.h"
+# include "uv/win.h"
#else
-# include "uv-unix.h"
+# include "uv/unix.h"
#endif
/* Expand this list if necessary. */
@@ -142,6 +142,7 @@ extern "C" {
XX(EHOSTDOWN, "host is down") \
XX(EREMOTEIO, "remote I/O error") \
XX(ENOTTY, "inappropriate ioctl for device") \
+ XX(EFTYPE, "inappropriate file type or format") \
#define UV_HANDLE_TYPE_MAP(XX) \
XX(ASYNC, async) \
@@ -503,7 +504,7 @@ UV_EXTERN int uv_try_write(uv_stream_t* handle,
struct uv_write_s {
UV_REQ_FIELDS
uv_write_cb cb;
- uv_stream_t* send_handle;
+ uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */
uv_stream_t* handle;
UV_WRITE_PRIVATE_FIELDS
};
@@ -865,7 +866,13 @@ typedef enum {
* flags may be specified to create a duplex data stream.
*/
UV_READABLE_PIPE = 0x10,
- UV_WRITABLE_PIPE = 0x20
+ UV_WRITABLE_PIPE = 0x20,
+
+ /*
+ * Open the child pipe handle in overlapped mode on Windows.
+ * On Unix it is silently ignored.
+ */
+ UV_OVERLAPPED_PIPE = 0x40
} uv_stdio_flags;
typedef struct uv_stdio_container_s {
@@ -997,16 +1004,18 @@ UV_EXTERN int uv_queue_work(uv_loop_t* loop,
UV_EXTERN int uv_cancel(uv_req_t* req);
+struct uv_cpu_times_s {
+ uint64_t user;
+ uint64_t nice;
+ uint64_t sys;
+ uint64_t idle;
+ uint64_t irq;
+};
+
struct uv_cpu_info_s {
char* model;
int speed;
- struct uv_cpu_times_s {
- uint64_t user;
- uint64_t nice;
- uint64_t sys;
- uint64_t idle;
- uint64_t irq;
- } cpu_times;
+ struct uv_cpu_times_s cpu_times;
};
struct uv_interface_address_s {
@@ -1132,6 +1141,7 @@ typedef enum {
UV_FS_READLINK,
UV_FS_CHOWN,
UV_FS_FCHOWN,
+ UV_FS_LCHOWN,
UV_FS_REALPATH,
UV_FS_COPYFILE
} uv_fs_type;
@@ -1336,6 +1346,12 @@ UV_EXTERN int uv_fs_fchown(uv_loop_t* loop,
uv_uid_t uid,
uv_gid_t gid,
uv_fs_cb cb);
+UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ uv_uid_t uid,
+ uv_gid_t gid,
+ uv_fs_cb cb);
enum uv_fs_event {
diff --git a/deps/uv/include/uv-aix.h b/deps/uv/include/uv/aix.h
index 7dc992fa6d..7dc992fa6d 100644
--- a/deps/uv/include/uv-aix.h
+++ b/deps/uv/include/uv/aix.h
diff --git a/deps/uv/include/android-ifaddrs.h b/deps/uv/include/uv/android-ifaddrs.h
index 9cd19fec12..9cd19fec12 100644
--- a/deps/uv/include/android-ifaddrs.h
+++ b/deps/uv/include/uv/android-ifaddrs.h
diff --git a/deps/uv/include/uv-bsd.h b/deps/uv/include/uv/bsd.h
index 2d72b3d771..2d72b3d771 100644
--- a/deps/uv/include/uv-bsd.h
+++ b/deps/uv/include/uv/bsd.h
diff --git a/deps/uv/include/uv-darwin.h b/deps/uv/include/uv/darwin.h
index d226415820..d226415820 100644
--- a/deps/uv/include/uv-darwin.h
+++ b/deps/uv/include/uv/darwin.h
diff --git a/deps/uv/include/uv-errno.h b/deps/uv/include/uv/errno.h
index aa4d4509f6..8eeb95de31 100644
--- a/deps/uv/include/uv-errno.h
+++ b/deps/uv/include/uv/errno.h
@@ -433,5 +433,11 @@
# define UV__ENOTTY (-4029)
#endif
+#if defined(EFTYPE) && !defined(_WIN32)
+# define UV__EFTYPE UV__ERR(EFTYPE)
+#else
+# define UV__EFTYPE (-4028)
+#endif
+
#endif /* UV_ERRNO_H_ */
diff --git a/deps/uv/include/uv-linux.h b/deps/uv/include/uv/linux.h
index 9b38405a19..9b38405a19 100644
--- a/deps/uv/include/uv-linux.h
+++ b/deps/uv/include/uv/linux.h
diff --git a/deps/uv/include/uv-os390.h b/deps/uv/include/uv/os390.h
index 0267d74cbd..0267d74cbd 100644
--- a/deps/uv/include/uv-os390.h
+++ b/deps/uv/include/uv/os390.h
diff --git a/deps/uv/include/uv-posix.h b/deps/uv/include/uv/posix.h
index 9a96634db0..9a96634db0 100644
--- a/deps/uv/include/uv-posix.h
+++ b/deps/uv/include/uv/posix.h
diff --git a/deps/uv/include/pthread-barrier.h b/deps/uv/include/uv/pthread-barrier.h
index 07db9b8a6a..07db9b8a6a 100644
--- a/deps/uv/include/pthread-barrier.h
+++ b/deps/uv/include/uv/pthread-barrier.h
diff --git a/deps/uv/include/stdint-msvc2008.h b/deps/uv/include/uv/stdint-msvc2008.h
index d02608a597..d02608a597 100644
--- a/deps/uv/include/stdint-msvc2008.h
+++ b/deps/uv/include/uv/stdint-msvc2008.h
diff --git a/deps/uv/include/uv-sunos.h b/deps/uv/include/uv/sunos.h
index 042166424e..042166424e 100644
--- a/deps/uv/include/uv-sunos.h
+++ b/deps/uv/include/uv/sunos.h
diff --git a/deps/uv/include/uv-threadpool.h b/deps/uv/include/uv/threadpool.h
index 9708ebdd53..9708ebdd53 100644
--- a/deps/uv/include/uv-threadpool.h
+++ b/deps/uv/include/uv/threadpool.h
diff --git a/deps/uv/include/tree.h b/deps/uv/include/uv/tree.h
index f936416e3d..f936416e3d 100644
--- a/deps/uv/include/tree.h
+++ b/deps/uv/include/uv/tree.h
diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv/unix.h
index 480a0691ea..74a0d643ce 100644
--- a/deps/uv/include/uv-unix.h
+++ b/deps/uv/include/uv/unix.h
@@ -42,32 +42,32 @@
#include <pthread.h>
#include <signal.h>
-#include "uv-threadpool.h"
+#include "uv/threadpool.h"
#if defined(__linux__)
-# include "uv-linux.h"
+# include "uv/linux.h"
#elif defined (__MVS__)
-# include "uv-os390.h"
+# include "uv/os390.h"
#elif defined(__PASE__)
-# include "uv-posix.h"
+# include "uv/posix.h"
#elif defined(_AIX)
-# include "uv-aix.h"
+# include "uv/aix.h"
#elif defined(__sun)
-# include "uv-sunos.h"
+# include "uv/sunos.h"
#elif defined(__APPLE__)
-# include "uv-darwin.h"
+# include "uv/darwin.h"
#elif defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
-# include "uv-bsd.h"
+# include "uv/bsd.h"
#elif defined(__CYGWIN__) || defined(__MSYS__)
-# include "uv-posix.h"
+# include "uv/posix.h"
#endif
#ifndef PTHREAD_BARRIER_SERIAL_THREAD
-# include "pthread-barrier.h"
+# include "uv/pthread-barrier.h"
#endif
#ifndef NI_MAXHOST
diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv/version.h
index 75f2940cd4..0b829717b8 100644
--- a/deps/uv/include/uv-version.h
+++ b/deps/uv/include/uv/version.h
@@ -31,8 +31,8 @@
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 20
-#define UV_VERSION_PATCH 3
+#define UV_VERSION_MINOR 21
+#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv/win.h
index 4c6c50a29c..f01335296a 100644
--- a/deps/uv/include/uv-win.h
+++ b/deps/uv/include/uv/win.h
@@ -53,13 +53,13 @@ typedef struct pollfd {
#include <sys/stat.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "stdint-msvc2008.h"
+# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
-#include "tree.h"
-#include "uv-threadpool.h"
+#include "uv/tree.h"
+#include "uv/threadpool.h"
#define MAX_PIPENAME_LEN 256
@@ -86,8 +86,8 @@ typedef struct pollfd {
#define SIGKILL 9
#define SIGWINCH 28
-/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many */
-/* unix-like platforms. However MinGW doesn't define it, so we do. */
+/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like
+ * platforms. However MinGW doesn't define it, so we do. */
#ifndef SIGABRT_COMPAT
# define SIGABRT_COMPAT 6
#endif
@@ -244,7 +244,7 @@ typedef union {
CRITICAL_SECTION waiters_count_lock;
HANDLE signal_event;
HANDLE broadcast_event;
- } fallback;
+ } unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */
} uv_cond_t;
typedef union {
@@ -368,10 +368,10 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
} u; \
struct uv_req_s* next_req;
-#define UV_WRITE_PRIVATE_FIELDS \
- int ipc_header; \
- uv_buf_t write_buffer; \
- HANDLE event_handle; \
+#define UV_WRITE_PRIVATE_FIELDS \
+ int coalesced; \
+ uv_buf_t write_buffer; \
+ HANDLE event_handle; \
HANDLE wait_handle;
#define UV_CONNECT_PRIVATE_FIELDS \
@@ -459,16 +459,17 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define uv_pipe_connection_fields \
uv_timer_t* eof_timer; \
- uv_write_t ipc_header_write_req; \
- int ipc_pid; \
- uint64_t remaining_ipc_rawdata_bytes; \
- struct { \
- void* queue[2]; \
- int queue_len; \
- } pending_ipc_info; \
+ uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
+ DWORD ipc_remote_pid; \
+ union { \
+ uint32_t payload_remaining; \
+ uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
+ } ipc_data_frame; \
+ void* ipc_xfer_queue[2]; \
+ int ipc_xfer_queue_length; \
uv_write_t* non_overlapped_writes_tail; \
- uv_mutex_t readfile_mutex; \
- volatile HANDLE readfile_thread;
+ CRITICAL_SECTION readfile_thread_lock; \
+ volatile HANDLE readfile_thread_handle;
#define UV_PIPE_PRIVATE_FIELDS \
HANDLE handle; \
@@ -478,8 +479,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
struct { uv_pipe_connection_fields } conn; \
} pipe;
-/* TODO: put the parser states in an union - TTY handles are always */
-/* half-duplex so read-state can safely overlap write-state. */
+/* TODO: put the parser states in an union - TTY handles are always half-duplex
+ * so read-state can safely overlap write-state. */
#define UV_TTY_PRIVATE_FIELDS \
HANDLE handle; \
union { \
diff --git a/deps/uv/libuv.pc.in b/deps/uv/libuv.pc.in
index 55c4b65d5d..1d7b86f751 100644
--- a/deps/uv/libuv.pc.in
+++ b/deps/uv/libuv.pc.in
@@ -3,7 +3,7 @@ exec_prefix=${prefix}
libdir=@libdir@
includedir=@includedir@
-Name: @PACKAGE_NAME@
+Name: libuv
Version: @PACKAGE_VERSION@
Description: multi-platform support library with a focus on asynchronous I/O.
URL: http://libuv.org/
diff --git a/deps/uv/samples/socks5-proxy/main.c b/deps/uv/samples/socks5-proxy/main.c
index 04020cbd3a..e77c7c6907 100644
--- a/deps/uv/samples/socks5-proxy/main.c
+++ b/deps/uv/samples/socks5-proxy/main.c
@@ -63,9 +63,9 @@ const char *_getprogname(void) {
static void parse_opts(server_config *cf, int argc, char **argv) {
int opt;
- while (-1 != (opt = getopt(argc, argv, "H:hp:"))) {
+ while (-1 != (opt = getopt(argc, argv, "b:hp:"))) {
switch (opt) {
- case 'H':
+ case 'b':
cf->bind_host = optarg;
break;
@@ -85,7 +85,7 @@ static void parse_opts(server_config *cf, int argc, char **argv) {
static void usage(void) {
printf("Usage:\n"
"\n"
- " %s [-b <address> [-h] [-p <port>]\n"
+ " %s [-b <address>] [-h] [-p <port>]\n"
"\n"
"Options:\n"
"\n"
diff --git a/deps/uv/src/inet.c b/deps/uv/src/inet.c
index da63a688c4..4598ca1e9f 100644
--- a/deps/uv/src/inet.c
+++ b/deps/uv/src/inet.c
@@ -19,7 +19,7 @@
#include <string.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "stdint-msvc2008.h"
+# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
diff --git a/deps/uv/src/unix/android-ifaddrs.c b/deps/uv/src/unix/android-ifaddrs.c
index bf30b14179..99fb25a43b 100644
--- a/deps/uv/src/unix/android-ifaddrs.c
+++ b/deps/uv/src/unix/android-ifaddrs.c
@@ -23,7 +23,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "android-ifaddrs.h"
+#include "uv/android-ifaddrs.h"
#include "uv-common.h"
#include <string.h>
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 18c8fcd808..c2e7bd730d 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -174,8 +174,8 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
case UV_SIGNAL:
uv__signal_close((uv_signal_t*) handle);
- /* Signal handles may not be closed immediately. The signal code will */
- /* itself close uv__make_close_pending whenever appropriate. */
+ /* Signal handles may not be closed immediately. The signal code will
+ * itself close uv__make_close_pending whenever appropriate. */
return;
default:
@@ -927,6 +927,11 @@ int uv__io_active(const uv__io_t* w, unsigned int events) {
}
+int uv__fd_exists(uv_loop_t* loop, int fd) {
+ return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL;
+}
+
+
int uv_getrusage(uv_rusage_t* rusage) {
struct rusage usage;
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index de678733a9..652cdfd734 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -865,9 +865,11 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
/* If an error occurred that the sendfile fallback also won't handle, or
this is a force clone then exit. Otherwise, fall through to try using
sendfile(). */
- if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) ||
- req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
- err = -errno;
+ if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) {
+ err = UV__ERR(errno);
+ goto out;
+ } else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = UV_ENOTSUP;
goto out;
}
} else {
@@ -927,7 +929,11 @@ out:
}
}
- return result;
+ if (result == 0)
+ return 0;
+
+ errno = UV__ERR(result);
+ return -1;
#endif
}
@@ -1114,6 +1120,7 @@ static void uv__fs_work(struct uv__work* w) {
X(COPYFILE, uv__fs_copyfile(req));
X(FCHMOD, fchmod(req->file, req->mode));
X(FCHOWN, fchown(req->file, req->uid, req->gid));
+ X(LCHOWN, lchown(req->path, req->uid, req->gid));
X(FDATASYNC, uv__fs_fdatasync(req));
X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
X(FSYNC, uv__fs_fsync(req));
@@ -1240,6 +1247,20 @@ int uv_fs_fchown(uv_loop_t* loop,
}
+int uv_fs_lchown(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ uv_uid_t uid,
+ uv_gid_t gid,
+ uv_fs_cb cb) {
+ INIT(LCHOWN);
+ PATH;
+ req->uid = uid;
+ req->gid = gid;
+ POST;
+}
+
+
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
INIT(FDATASYNC);
req->file = file;
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 63e478fd98..b0c5dcadf1 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -219,6 +219,7 @@ int uv__io_active(const uv__io_t* w, unsigned int events);
int uv__io_check_fd(uv_loop_t* loop, int fd);
void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
int uv__io_fork(uv_loop_t* loop);
+int uv__fd_exists(uv_loop_t* loop, int fd);
/* async */
void uv__async_stop(uv_loop_t* loop);
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index a30fd730ff..930f2da712 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -261,8 +261,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w = loop->watchers[fd];
if (w == NULL) {
- /* File descriptor that we've stopped watching, disarm it. */
- /* TODO batch up */
+ /* File descriptor that we've stopped watching, disarm it.
+ * TODO: batch up. */
struct kevent events[1];
EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index b63c25f3c2..d09bbcdd6f 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -51,7 +51,7 @@
#ifdef HAVE_IFADDRS_H
# if defined(__ANDROID__)
-# include "android-ifaddrs.h"
+# include "uv/android-ifaddrs.h"
# else
# include <ifaddrs.h>
# endif
@@ -388,7 +388,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* free when we switch over to edge-triggered I/O.
*/
if (pe->events == POLLERR || pe->events == POLLHUP)
- pe->events |= w->pevents & (POLLIN | POLLOUT | UV__POLLPRI);
+ pe->events |=
+ w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
if (pe->events != 0) {
/* Run signal watchers last. This also affects child process watchers
diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c
index bcad630fab..7797f84252 100644
--- a/deps/uv/src/unix/linux-inotify.c
+++ b/deps/uv/src/unix/linux-inotify.c
@@ -19,7 +19,7 @@
*/
#include "uv.h"
-#include "tree.h"
+#include "uv/tree.h"
#include "internal.h"
#include <stdint.h>
diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c
index 99ead6cbc0..f990403d40 100644
--- a/deps/uv/src/unix/loop.c
+++ b/deps/uv/src/unix/loop.c
@@ -20,7 +20,7 @@
*/
#include "uv.h"
-#include "tree.h"
+#include "uv/tree.h"
#include "internal.h"
#include "heap-inl.h"
#include <stdlib.h>
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index 2c578dcb35..91114db616 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -134,6 +134,9 @@ void uv__pipe_close(uv_pipe_t* handle) {
int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
int err;
+ if (uv__fd_exists(handle->loop, fd))
+ return UV_EEXIST;
+
err = uv__nonblock(fd, 1);
if (err)
return err;
diff --git a/deps/uv/src/unix/poll.c b/deps/uv/src/unix/poll.c
index f3b0bf4e43..3d5022b22e 100644
--- a/deps/uv/src/unix/poll.c
+++ b/deps/uv/src/unix/poll.c
@@ -68,6 +68,9 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
int err;
+ if (uv__fd_exists(loop, fd))
+ return UV_EEXIST;
+
err = uv__io_check_fd(loop, fd);
if (err)
return err;
diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c
index b9d0a56084..8da08b8680 100644
--- a/deps/uv/src/unix/signal.c
+++ b/deps/uv/src/unix/signal.c
@@ -54,8 +54,7 @@ static void uv__signal_unregister_handler(int signum);
static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
static struct uv__signal_tree_s uv__signal_tree =
RB_INITIALIZER(uv__signal_tree);
-static int uv__signal_lock_pipefd[2];
-
+static int uv__signal_lock_pipefd[2] = { -1, -1 };
RB_GENERATE_STATIC(uv__signal_tree_s,
uv_signal_s, tree_entry,
@@ -64,7 +63,7 @@ RB_GENERATE_STATIC(uv__signal_tree_s,
static void uv__signal_global_reinit(void);
static void uv__signal_global_init(void) {
- if (!uv__signal_lock_pipefd[0])
+ if (uv__signal_lock_pipefd[0] == -1)
/* pthread_atfork can register before and after handlers, one
* for each child. This only registers one for the child. That
* state is both persistent and cumulative, so if we keep doing
@@ -74,15 +73,11 @@ static void uv__signal_global_init(void) {
if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
abort();
- if (uv__make_pipe(uv__signal_lock_pipefd, 0))
- abort();
-
- if (uv__signal_unlock())
- abort();
+ uv__signal_global_reinit();
}
-static void uv__signal_global_reinit(void) {
+UV_DESTRUCTOR(static void uv__signal_global_fini(void)) {
/* We can only use signal-safe functions here.
* That includes read/write and close, fortunately.
* We do all of this directly here instead of resetting
@@ -90,11 +85,26 @@ static void uv__signal_global_reinit(void) {
* uv__signal_global_once_init is only called from uv_loop_init
* and this needs to function in existing loops.
*/
- uv__close(uv__signal_lock_pipefd[0]);
- uv__signal_lock_pipefd[0] = -1;
- uv__close(uv__signal_lock_pipefd[1]);
- uv__signal_lock_pipefd[1] = -1;
- uv__signal_global_init();
+ if (uv__signal_lock_pipefd[0] != -1) {
+ uv__close(uv__signal_lock_pipefd[0]);
+ uv__signal_lock_pipefd[0] = -1;
+ }
+
+ if (uv__signal_lock_pipefd[1] != -1) {
+ uv__close(uv__signal_lock_pipefd[1]);
+ uv__signal_lock_pipefd[1] = -1;
+ }
+}
+
+
+static void uv__signal_global_reinit(void) {
+ uv__signal_global_fini();
+
+ if (uv__make_pipe(uv__signal_lock_pipefd, 0))
+ abort();
+
+ if (uv__signal_unlock())
+ abort();
}
@@ -103,7 +113,6 @@ void uv__signal_global_once_init(void) {
}
-
static int uv__signal_lock(void) {
int r;
char data;
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 5ec6bf4de2..fb56a06b43 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -1121,6 +1121,7 @@ static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) {
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wgnu-folding-constant"
+# pragma clang diagnostic ignored "-Wvla-extension"
#endif
static void uv__read(uv_stream_t* stream) {
@@ -1311,7 +1312,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
assert(uv__stream_fd(stream) >= 0);
- /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */
+ /* Ignore POLLHUP here. Even if it's set, there may still be data to read. */
if (events & (POLLIN | POLLERR | POLLHUP))
uv__read(stream);
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index 9a46793fdb..27a2a6130c 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -263,6 +263,9 @@ int uv__tcp_connect(uv_connect_t* req,
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
int err;
+ if (uv__fd_exists(handle->loop, sock))
+ return UV_EEXIST;
+
err = uv__nonblock(sock, 1);
if (err)
return err;
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index 74d613b684..15da047a5c 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -624,6 +624,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
if (handle->io_watcher.fd != -1)
return UV_EBUSY;
+ if (uv__fd_exists(handle->loop, sock))
+ return UV_EEXIST;
+
err = uv__nonblock(sock, 1);
if (err)
return err;
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index c497d014fd..85bcbe6c8a 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -32,13 +32,13 @@
#include <stddef.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "stdint-msvc2008.h"
+# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
#include "uv.h"
-#include "tree.h"
+#include "uv/tree.h"
#include "queue.h"
#if EDOM > 0
diff --git a/deps/uv/src/win/async.c b/deps/uv/src/win/async.c
index 0b636ed1e9..13d3c7b33e 100644
--- a/deps/uv/src/win/async.c
+++ b/deps/uv/src/win/async.c
@@ -71,8 +71,8 @@ int uv_async_send(uv_async_t* handle) {
return -1;
}
- /* The user should make sure never to call uv_async_send to a closing */
- /* or closed handle. */
+ /* The user should make sure never to call uv_async_send to a closing or
+ * closed handle. */
assert(!(handle->flags & UV__HANDLE_CLOSING));
if (!uv__atomic_exchange_set(&handle->async_sent)) {
diff --git a/deps/uv/src/win/atomicops-inl.h b/deps/uv/src/win/atomicops-inl.h
index 6d8126f692..52713cf305 100644
--- a/deps/uv/src/win/atomicops-inl.h
+++ b/deps/uv/src/win/atomicops-inl.h
@@ -29,10 +29,10 @@
/* Atomic set operation on char */
#ifdef _MSC_VER /* MSVC */
-/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less */
-/* efficient than InterlockedExchange, but InterlockedExchange8 does not */
-/* exist, and interlocked operations on larger targets might require the */
-/* target to be aligned. */
+/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less
+ * efficient than InterlockedExchange, but InterlockedExchange8 does not exist,
+ * and interlocked operations on larger targets might require the target to be
+ * aligned. */
#pragma intrinsic(_InterlockedOr8)
static char INLINE uv__atomic_exchange_set(char volatile* target) {
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index 5fa9b6666d..d6af282a29 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -359,58 +359,7 @@ int uv_backend_timeout(const uv_loop_t* loop) {
}
-static void uv_poll(uv_loop_t* loop, DWORD timeout) {
- DWORD bytes;
- ULONG_PTR key;
- OVERLAPPED* overlapped;
- uv_req_t* req;
- int repeat;
- uint64_t timeout_time;
-
- timeout_time = loop->time + timeout;
-
- for (repeat = 0; ; repeat++) {
- GetQueuedCompletionStatus(loop->iocp,
- &bytes,
- &key,
- &overlapped,
- timeout);
-
- if (overlapped) {
- /* Package was dequeued */
- req = uv_overlapped_to_req(overlapped);
- uv_insert_pending_req(loop, req);
-
- /* Some time might have passed waiting for I/O,
- * so update the loop time here.
- */
- uv_update_time(loop);
- } else if (GetLastError() != WAIT_TIMEOUT) {
- /* Serious error */
- uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
- } else if (timeout > 0) {
- /* GetQueuedCompletionStatus can occasionally return a little early.
- * Make sure that the desired timeout target time is reached.
- */
- uv_update_time(loop);
- if (timeout_time > loop->time) {
- timeout = (DWORD)(timeout_time - loop->time);
- /* The first call to GetQueuedCompletionStatus should return very
- * close to the target time and the second should reach it, but
- * this is not stated in the documentation. To make sure a busy
- * loop cannot happen, the timeout is increased exponentially
- * starting on the third round.
- */
- timeout += repeat ? (1 << (repeat - 1)) : 0;
- continue;
- }
- }
- break;
- }
-}
-
-
-static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
+static void uv__poll(uv_loop_t* loop, DWORD timeout) {
BOOL success;
uv_req_t* req;
OVERLAPPED_ENTRY overlappeds[128];
@@ -422,12 +371,12 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
timeout_time = loop->time + timeout;
for (repeat = 0; ; repeat++) {
- success = pGetQueuedCompletionStatusEx(loop->iocp,
- overlappeds,
- ARRAY_SIZE(overlappeds),
- &count,
- timeout,
- FALSE);
+ success = GetQueuedCompletionStatusEx(loop->iocp,
+ overlappeds,
+ ARRAY_SIZE(overlappeds),
+ &count,
+ timeout,
+ FALSE);
if (success) {
for (i = 0; i < count; i++) {
@@ -485,12 +434,6 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
DWORD timeout;
int r;
int ran_pending;
- void (*poll)(uv_loop_t* loop, DWORD timeout);
-
- if (pGetQueuedCompletionStatusEx)
- poll = &uv_poll_ex;
- else
- poll = &uv_poll;
r = uv__loop_alive(loop);
if (!r)
@@ -508,7 +451,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
- (*poll)(loop, timeout);
+ uv__poll(loop, timeout);
uv_check_invoke(loop);
uv_process_endgames(loop);
diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c
index 9b03bfef6b..24924ba81e 100644
--- a/deps/uv/src/win/error.c
+++ b/deps/uv/src/win/error.c
@@ -46,8 +46,8 @@ void uv_fatal_error(const int errorno, const char* syscall) {
errmsg = "Unknown error";
}
- /* FormatMessage messages include a newline character already, */
- /* so don't add another. */
+ /* FormatMessage messages include a newline character already, so don't add
+ * another. */
if (syscall) {
fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg);
} else {
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 30b87ac515..71b6a81a0d 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -326,12 +326,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
- /* Real symlinks can contain pretty much everything, but the only thing */
- /* we really care about is undoing the implicit conversion to an NT */
- /* namespaced path that CreateSymbolicLink will perform on absolute */
- /* paths. If the path is win32-namespaced then the user must have */
- /* explicitly made it so, and we better just return the unmodified */
- /* reparse data. */
+ /* Real symlinks can contain pretty much everything, but the only thing we
+ * really care about is undoing the implicit conversion to an NT namespaced
+ * path that CreateSymbolicLink will perform on absolute paths. If the path
+ * is win32-namespaced then the user must have explicitly made it so, and
+ * we better just return the unmodified reparse data. */
if (w_target_len >= 4 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
@@ -352,8 +351,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
(w_target[5] == L'N' || w_target[5] == L'n') &&
(w_target[6] == L'C' || w_target[6] == L'c') &&
w_target[7] == L'\\') {
- /* \??\UNC\<server>\<share>\ - make sure the final path looks like */
- /* \\<server>\<share>\ */
+ /* \??\UNC\<server>\<share>\ - make sure the final path looks like
+ * \\<server>\<share>\ */
w_target += 6;
w_target[0] = L'\\';
w_target_len -= 6;
@@ -368,11 +367,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
- /* Only treat junctions that look like \??\<drive>:\ as symlink. */
- /* Junctions can also be used as mount points, like \??\Volume{<guid>}, */
- /* but that's confusing for programs since they wouldn't be able to */
- /* actually understand such a path when returned by uv_readlink(). */
- /* UNC paths are never valid for junctions so we don't care about them. */
+ /* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions
+ * can also be used as mount points, like \??\Volume{<guid>}, but that's
+ * confusing for programs since they wouldn't be able to actually
+ * understand such a path when returned by uv_readlink(). UNC paths are
+ * never valid for junctions so we don't care about them. */
if (!(w_target_len >= 6 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
@@ -409,8 +408,8 @@ void fs__open(uv_fs_t* req) {
int fd, current_umask;
int flags = req->fs.info.file_flags;
- /* Obtain the active umask. umask() never fails and returns the previous */
- /* umask. */
+ /* Obtain the active umask. umask() never fails and returns the previous
+ * umask. */
current_umask = umask(0);
umask(current_umask);
@@ -530,8 +529,8 @@ void fs__open(uv_fs_t* req) {
DWORD error = GetLastError();
if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
!(flags & UV_FS_O_EXCL)) {
- /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was */
- /* specified, it means the path referred to a directory. */
+ /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was
+ * specified, it means the path referred to a directory. */
SET_REQ_UV_ERROR(req, UV_EISDIR, error);
} else {
SET_REQ_WIN32_ERROR(req, GetLastError());
@@ -756,9 +755,9 @@ void fs__unlink(uv_fs_t* req) {
}
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- /* Do not allow deletion of directories, unless it is a symlink. When */
- /* the path refers to a non-symlink directory, report EPERM as mandated */
- /* by POSIX.1. */
+ /* Do not allow deletion of directories, unless it is a symlink. When the
+ * path refers to a non-symlink directory, report EPERM as mandated by
+ * POSIX.1. */
/* Check if it is a reparse point. If it's not, it's a normal directory. */
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
@@ -767,8 +766,8 @@ void fs__unlink(uv_fs_t* req) {
return;
}
- /* Read the reparse point and check if it is a valid symlink. */
- /* If not, don't unlink. */
+ /* Read the reparse point and check if it is a valid symlink. If not, don't
+ * unlink. */
if (fs__readlink_handle(handle, NULL, NULL) < 0) {
DWORD error = GetLastError();
if (error == ERROR_SYMLINK_NOT_SUPPORTED)
@@ -1490,6 +1489,7 @@ static void fs__chmod(uv_fs_t* req) {
static void fs__fchmod(uv_fs_t* req) {
int fd = req->file.fd;
+ int clear_archive_flag;
HANDLE handle;
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
@@ -1497,7 +1497,11 @@ static void fs__fchmod(uv_fs_t* req) {
VERIFY_FD(fd, req);
- handle = uv__get_osfhandle(fd);
+ handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);
+ if (handle == INVALID_HANDLE_VALUE) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
nt_status = pNtQueryInformationFile(handle,
&io_status,
@@ -1507,7 +1511,27 @@ static void fs__fchmod(uv_fs_t* req) {
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
- return;
+ goto fchmod_cleanup;
+ }
+
+ /* Test if the Archive attribute is cleared */
+ if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {
+ /* Set Archive flag, otherwise setting or clearing the read-only
+ flag will not work */
+ file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
+ nt_status = pNtSetInformationFile(handle,
+ &io_status,
+ &file_info,
+ sizeof file_info,
+ FileBasicInformation);
+ if (!NT_SUCCESS(nt_status)) {
+ SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
+ goto fchmod_cleanup;
+ }
+ /* Remeber to clear the flag later on */
+ clear_archive_flag = 1;
+ } else {
+ clear_archive_flag = 0;
}
if (req->fs.info.mode & _S_IWRITE) {
@@ -1524,10 +1548,28 @@ static void fs__fchmod(uv_fs_t* req) {
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
- return;
+ goto fchmod_cleanup;
+ }
+
+ if (clear_archive_flag) {
+ file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
+ if (file_info.FileAttributes == 0) {
+ file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+ nt_status = pNtSetInformationFile(handle,
+ &io_status,
+ &file_info,
+ sizeof file_info,
+ FileBasicInformation);
+ if (!NT_SUCCESS(nt_status)) {
+ SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
+ goto fchmod_cleanup;
+ }
}
SET_REQ_SUCCESS(req);
+fchmod_cleanup:
+ CloseHandle(handle);
}
@@ -1787,17 +1829,13 @@ static void fs__symlink(uv_fs_t* req) {
fs__create_junction(req, pathw, new_pathw);
return;
}
- if (!pCreateSymbolicLinkW) {
- SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
- return;
- }
if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
else
flags = uv__file_symlink_usermode_flag;
- if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) {
+ if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {
SET_REQ_RESULT(req, 0);
return;
}
@@ -1854,7 +1892,7 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
WCHAR* w_realpath_ptr = NULL;
WCHAR* w_realpath_buf;
- w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
+ w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
if (w_realpath_len == 0) {
return -1;
}
@@ -1866,10 +1904,8 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
}
w_realpath_ptr = w_realpath_buf;
- if (pGetFinalPathNameByHandleW(handle,
- w_realpath_ptr,
- w_realpath_len,
- VOLUME_NAME_DOS) == 0) {
+ if (GetFinalPathNameByHandleW(
+ handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {
uv__free(w_realpath_buf);
SetLastError(ERROR_INVALID_HANDLE);
return -1;
@@ -1901,11 +1937,6 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
static void fs__realpath(uv_fs_t* req) {
HANDLE handle;
- if (!pGetFinalPathNameByHandleW) {
- SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
- return;
- }
-
handle = CreateFileW(req->file.pathw,
0,
0,
@@ -1940,6 +1971,10 @@ static void fs__fchown(uv_fs_t* req) {
}
+static void fs__lchown(uv_fs_t* req) {
+ req->result = 0;
+}
+
static void uv__fs_work(struct uv__work* w) {
uv_fs_t* req;
@@ -1977,6 +2012,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(REALPATH, realpath)
XX(CHOWN, chown)
XX(FCHOWN, fchown);
+ XX(LCHOWN, lchown);
default:
assert(!"bad uv_fs_type");
}
@@ -2262,6 +2298,19 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
}
+int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
+ uv_gid_t gid, uv_fs_cb cb) {
+ int err;
+
+ INIT(UV_FS_LCHOWN);
+ err = fs__capture_path(req, path, NULL, cb != NULL);
+ if (err) {
+ return uv_translate_sys_error(err);
+ }
+ POST;
+}
+
+
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
int err;
diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c
index 5adc7663bd..063b4937cd 100644
--- a/deps/uv/src/win/getaddrinfo.c
+++ b/deps/uv/src/win/getaddrinfo.c
@@ -71,8 +71,8 @@ int uv__getaddrinfo_translate_error(int sys_err) {
#endif
-/* adjust size value to be multiple of 4. Use to keep pointer aligned */
-/* Do we need different versions of this for different architectures? */
+/* Adjust size value to be multiple of 4. Use to keep pointer aligned.
+ * Do we need different versions of this for different architectures? */
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
#ifndef NDIS_IF_MAX_STRING_SIZE
@@ -124,8 +124,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
}
if (req->retcode == 0) {
- /* convert addrinfoW to addrinfo */
- /* first calculate required length */
+ /* Convert addrinfoW to addrinfo. First calculate required length. */
addrinfow_ptr = req->addrinfow;
while (addrinfow_ptr != NULL) {
addrinfo_len += addrinfo_struct_len +
@@ -313,8 +312,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* save alloc_ptr now so we can free if error */
req->alloc = (void*)alloc_ptr;
- /* convert node string to UTF16 into allocated memory and save pointer in */
- /* the request. */
+ /* Convert node string to UTF16 into allocated memory and save pointer in the
+ * request. */
if (node != NULL) {
req->node = (WCHAR*)alloc_ptr;
if (MultiByteToWideChar(CP_UTF8,
@@ -331,8 +330,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
req->node = NULL;
}
- /* convert service string to UTF16 into allocated memory and save pointer */
- /* in the req. */
+ /* Convert service string to UTF16 into allocated memory and save pointer in
+ * the req. */
if (service != NULL) {
req->service = (WCHAR*)alloc_ptr;
if (MultiByteToWideChar(CP_UTF8,
@@ -392,21 +391,15 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
DWORD bufsize;
int r;
- uv__once_init();
-
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
- if (pConvertInterfaceIndexToLuid == NULL)
- return UV_ENOSYS;
- r = pConvertInterfaceIndexToLuid(ifindex, &luid);
+ r = ConvertInterfaceIndexToLuid(ifindex, &luid);
if (r != 0)
return uv_translate_sys_error(r);
- if (pConvertInterfaceLuidToNameW == NULL)
- return UV_ENOSYS;
- r = pConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
+ r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
if (r != 0)
return uv_translate_sys_error(r);
diff --git a/deps/uv/src/win/handle-inl.h b/deps/uv/src/win/handle-inl.h
index 8d0334cc52..ed843072df 100644
--- a/deps/uv/src/win/handle-inl.h
+++ b/deps/uv/src/win/handle-inl.h
@@ -164,10 +164,10 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
INLINE static HANDLE uv__get_osfhandle(int fd)
{
- /* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */
- /* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */
- /* for invalid FDs in release builds (or if you let the assert continue). */
- /* So this wrapper function disables asserts when calling _get_osfhandle. */
+ /* _get_osfhandle() raises an assert in debug builds if the FD is invalid.
+ * But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for
+ * invalid FDs in release builds (or if you let the assert continue). So this
+ * wrapper function disables asserts when calling _get_osfhandle. */
HANDLE handle;
UV_BEGIN_DISABLE_CRT_ASSERT();
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index cce4e204d2..fa926d9a44 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -25,7 +25,7 @@
#include "uv.h"
#include "../uv-common.h"
-#include "tree.h"
+#include "uv/tree.h"
#include "winapi.h"
#include "winsock.h"
@@ -99,7 +99,6 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
/* Only used by uv_pipe_t handles. */
#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000
#define UV_HANDLE_PIPESERVER 0x02000000
-#define UV_HANDLE_PIPE_READ_CANCELABLE 0x04000000
/* Only used by uv_tty_t handles. */
#define UV_HANDLE_TTY_READABLE 0x01000000
@@ -127,8 +126,9 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
typedef struct {
WSAPROTOCOL_INFOW socket_info;
- int delayed_error;
-} uv__ipc_socket_info_ex;
+ uint32_t delayed_error;
+ uint32_t flags; /* Either zero or UV_HANDLE_CONNECTION. */
+} uv__ipc_socket_xfer_info_t;
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
@@ -150,11 +150,10 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
-int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
- int tcp_connection);
-
-int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
- LPWSAPROTOCOL_INFOW protocol_info);
+int uv__tcp_xfer_export(uv_tcp_t* handle,
+ int pid,
+ uv__ipc_socket_xfer_info_t* xfer_info);
+int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_info_t* xfer_info);
/*
@@ -178,14 +177,14 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
-int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
- const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
-int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
- const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle,
- uv_write_cb cb);
-void uv__pipe_pause_read(uv_pipe_t* handle);
-void uv__pipe_unpause_read(uv_pipe_t* handle);
-void uv__pipe_stop_read(uv_pipe_t* handle);
+void uv__pipe_read_stop(uv_pipe_t* handle);
+int uv__pipe_write(uv_loop_t* loop,
+ uv_write_t* req,
+ uv_pipe_t* handle,
+ const uv_buf_t bufs[],
+ size_t nbufs,
+ uv_stream_t* send_handle,
+ uv_write_cb cb);
void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_req_t* req);
@@ -332,7 +331,6 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
void uv__util_init(void);
uint64_t uv__hrtime(double scale);
-int uv_current_pid(void);
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index 83ee4f99ca..ae569326dd 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -21,9 +21,10 @@
#include <assert.h>
#include <io.h>
-#include <string.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "uv.h"
#include "internal.h"
@@ -34,26 +35,14 @@
#include <aclapi.h>
#include <accctrl.h>
-typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t;
-
-struct uv__ipc_queue_item_s {
- /*
- * NOTE: It is important for socket_info_ex to be the first field,
- * because we will we assigning it to the pending_ipc_info.socket_info
- */
- uv__ipc_socket_info_ex socket_info_ex;
- QUEUE member;
- int tcp_connection;
-};
-
/* A zero-size buffer for use by uv_pipe_read */
static char uv_zero_[] = "";
/* Null uv_buf_t */
static const uv_buf_t uv_null_buf_ = { 0, NULL };
-/* The timeout that the pipe will wait for the remote end to write data */
-/* when the local ends wants to shut it down. */
+/* The timeout that the pipe will wait for the remote end to write data when
+ * the local ends wants to shut it down. */
static const int64_t eof_timeout = 50; /* ms */
static const int default_pending_pipe_instances = 4;
@@ -62,22 +51,27 @@ static const int default_pending_pipe_instances = 4;
static char pipe_prefix[] = "\\\\?\\pipe";
static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
-/* IPC protocol flags. */
-#define UV_IPC_RAW_DATA 0x0001
-#define UV_IPC_TCP_SERVER 0x0002
-#define UV_IPC_TCP_CONNECTION 0x0004
+/* IPC incoming xfer queue item. */
+typedef struct {
+ uv__ipc_socket_xfer_info_t xfer_info;
+ QUEUE member;
+} uv__ipc_xfer_queue_item_t;
+
+/* IPC frame types. */
+enum { UV__IPC_DATA_FRAME = 0, UV__IPC_XFER_FRAME = 1 };
/* IPC frame header. */
typedef struct {
- int flags;
- uint64_t raw_data_length;
-} uv_ipc_frame_header_t;
+ uint32_t type;
+ uint32_t payload_length;
+} uv__ipc_frame_header_t;
-/* IPC frame, which contains an imported TCP socket stream. */
+/* Coalesced write request. */
typedef struct {
- uv_ipc_frame_header_t header;
- uv__ipc_socket_info_ex socket_info_ex;
-} uv_ipc_frame_uv_stream;
+ uv_write_t req; /* Internal heap-allocated write request. */
+ uv_write_t* user_req; /* Pointer to user-specified uv_write_t. */
+} uv__coalesced_write_t;
+
static void eof_timer_init(uv_pipe_t* pipe);
static void eof_timer_start(uv_pipe_t* pipe);
@@ -98,15 +92,12 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
handle->reqs_pending = 0;
handle->handle = INVALID_HANDLE_VALUE;
handle->name = NULL;
- handle->pipe.conn.ipc_pid = 0;
- handle->pipe.conn.remaining_ipc_rawdata_bytes = 0;
- QUEUE_INIT(&handle->pipe.conn.pending_ipc_info.queue);
- handle->pipe.conn.pending_ipc_info.queue_len = 0;
+ handle->pipe.conn.ipc_remote_pid = 0;
+ handle->pipe.conn.ipc_data_frame.payload_remaining = 0;
+ QUEUE_INIT(&handle->pipe.conn.ipc_xfer_queue);
+ handle->pipe.conn.ipc_xfer_queue_length = 0;
handle->ipc = ipc;
handle->pipe.conn.non_overlapped_writes_tail = NULL;
- handle->pipe.conn.readfile_thread = NULL;
-
- UV_REQ_INIT(&handle->pipe.conn.ipc_header_write_req, UV_UNKNOWN_REQ);
return 0;
}
@@ -117,10 +108,9 @@ static void uv_pipe_connection_init(uv_pipe_t* handle) {
handle->read_req.data = handle;
handle->pipe.conn.eof_timer = NULL;
assert(!(handle->flags & UV_HANDLE_PIPESERVER));
- if (pCancelSynchronousIo &&
- handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
- uv_mutex_init(&handle->pipe.conn.readfile_mutex);
- handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE;
+ if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
+ handle->pipe.conn.readfile_thread_handle = NULL;
+ InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);
}
}
@@ -347,12 +337,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_PIPE_LOCAL_INFORMATION pipe_info;
- uv__ipc_queue_item_t* item;
-
- if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- handle->flags &= ~UV_HANDLE_PIPE_READ_CANCELABLE;
- uv_mutex_destroy(&handle->pipe.conn.readfile_mutex);
- }
+ uv__ipc_xfer_queue_item_t* xfer_queue_item;
if ((handle->flags & UV_HANDLE_CONNECTION) &&
handle->stream.conn.shutdown_req != NULL &&
@@ -429,27 +414,27 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
if (handle->flags & UV_HANDLE_CONNECTION) {
/* Free pending sockets */
- while (!QUEUE_EMPTY(&handle->pipe.conn.pending_ipc_info.queue)) {
+ while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {
QUEUE* q;
SOCKET socket;
- q = QUEUE_HEAD(&handle->pipe.conn.pending_ipc_info.queue);
+ q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);
QUEUE_REMOVE(q);
- item = QUEUE_DATA(q, uv__ipc_queue_item_t, member);
+ xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
/* Materialize socket and close it */
socket = WSASocketW(FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
- &item->socket_info_ex.socket_info,
+ &xfer_queue_item->xfer_info.socket_info,
0,
WSA_FLAG_OVERLAPPED);
- uv__free(item);
+ uv__free(xfer_queue_item);
if (socket != INVALID_SOCKET)
closesocket(socket);
}
- handle->pipe.conn.pending_ipc_info.queue_len = 0;
+ handle->pipe.conn.ipc_xfer_queue_length = 0;
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
@@ -461,6 +446,9 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
handle->read_req.event_handle = NULL;
}
}
+
+ if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)
+ DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);
}
if (handle->flags & UV_HANDLE_PIPESERVER) {
@@ -595,8 +583,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
loop = handle->loop;
assert(loop);
- /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. */
- /* We wait for the pipe to become available with WaitNamedPipe. */
+ /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait
+ * for the pipe to become available with WaitNamedPipe. */
while (WaitNamedPipeW(handle->name, 30000)) {
/* The pipe is now available, try to connect. */
pipeHandle = open_named_pipe(handle->name, &duplex_flags);
@@ -706,55 +694,68 @@ error:
}
-void uv__pipe_pause_read(uv_pipe_t* handle) {
- if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- /* Pause the ReadFile task briefly, to work
- around the Windows kernel bug that causes
- any access to a NamedPipe to deadlock if
- any process has called ReadFile */
- HANDLE h;
- uv_mutex_lock(&handle->pipe.conn.readfile_mutex);
- h = handle->pipe.conn.readfile_thread;
- while (h) {
- /* spinlock: we expect this to finish quickly,
- or we are probably about to deadlock anyways
- (in the kernel), so it doesn't matter */
- pCancelSynchronousIo(h);
- SwitchToThread(); /* yield thread control briefly */
- h = handle->pipe.conn.readfile_thread;
- }
- }
-}
+void uv__pipe_interrupt_read(uv_pipe_t* handle) {
+ BOOL r;
+
+ if (!(handle->flags & UV_HANDLE_READ_PENDING))
+ return; /* No pending reads. */
+ if (handle->flags & UV_HANDLE_CANCELLATION_PENDING)
+ return; /* Already cancelled. */
+ if (handle->handle == INVALID_HANDLE_VALUE)
+ return; /* Pipe handle closed. */
+
+ if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) {
+ /* Cancel asynchronous read. */
+ r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
+ assert(r || GetLastError() == ERROR_NOT_FOUND);
+ } else {
+ /* Cancel synchronous read (which is happening in the thread pool). */
+ HANDLE thread;
+ volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
+
+ EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock);
+
+ thread = *thread_ptr;
+ if (thread == NULL) {
+ /* The thread pool thread has not yet reached the point of blocking, we
+ * can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */
+ *thread_ptr = INVALID_HANDLE_VALUE;
+
+ } else {
+ /* Spin until the thread has acknowledged (by setting the thread to
+ * INVALID_HANDLE_VALUE) that it is past the point of blocking. */
+ while (thread != INVALID_HANDLE_VALUE) {
+ r = CancelSynchronousIo(thread);
+ assert(r || GetLastError() == ERROR_NOT_FOUND);
+ SwitchToThread(); /* Yield thread. */
+ thread = *thread_ptr;
+ }
+ }
-void uv__pipe_unpause_read(uv_pipe_t* handle) {
- if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- uv_mutex_unlock(&handle->pipe.conn.readfile_mutex);
+ LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock);
}
+
+ /* Set flag to indicate that read has been cancelled. */
+ handle->flags |= UV_HANDLE_CANCELLATION_PENDING;
}
-void uv__pipe_stop_read(uv_pipe_t* handle) {
- if (pCancelIoEx &&
- !(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) &&
- !(handle->flags & UV_HANDLE_EMULATE_IOCP) &&
- handle->flags & UV_HANDLE_READING &&
- handle->read_req.type == UV_READ) {
- pCancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
- }
+void uv__pipe_read_stop(uv_pipe_t* handle) {
handle->flags &= ~UV_HANDLE_READING;
- uv__pipe_pause_read((uv_pipe_t*)handle);
- uv__pipe_unpause_read((uv_pipe_t*)handle);
+ DECREASE_ACTIVE_COUNT(handle->loop, handle);
+
+ uv__pipe_interrupt_read(handle);
}
-/* Cleans up uv_pipe_t (server or connection) and all resources associated */
-/* with it. */
+/* Cleans up uv_pipe_t (server or connection) and all resources associated with
+ * it. */
void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
int i;
HANDLE pipeHandle;
- uv__pipe_stop_read(handle);
+ uv__pipe_interrupt_read(handle);
if (handle->name) {
uv__free(handle->name);
@@ -864,23 +865,21 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
uv_pipe_t* pipe_client;
uv_pipe_accept_t* req;
QUEUE* q;
- uv__ipc_queue_item_t* item;
+ uv__ipc_xfer_queue_item_t* item;
int err;
if (server->ipc) {
- if (QUEUE_EMPTY(&server->pipe.conn.pending_ipc_info.queue)) {
+ if (QUEUE_EMPTY(&server->pipe.conn.ipc_xfer_queue)) {
/* No valid pending sockets. */
return WSAEWOULDBLOCK;
}
- q = QUEUE_HEAD(&server->pipe.conn.pending_ipc_info.queue);
+ q = QUEUE_HEAD(&server->pipe.conn.ipc_xfer_queue);
QUEUE_REMOVE(q);
- server->pipe.conn.pending_ipc_info.queue_len--;
- item = QUEUE_DATA(q, uv__ipc_queue_item_t, member);
+ server->pipe.conn.ipc_xfer_queue_length--;
+ item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
- err = uv_tcp_import((uv_tcp_t*)client,
- &item->socket_info_ex,
- item->tcp_connection);
+ err = uv__tcp_xfer_import((uv_tcp_t*) client, &item->xfer_info);
if (err != 0)
return err;
@@ -889,8 +888,8 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
} else {
pipe_client = (uv_pipe_t*)client;
- /* Find a connection instance that has been connected, but not yet */
- /* accepted. */
+ /* Find a connection instance that has been connected, but not yet
+ * accepted. */
req = server->pipe.serv.pending_accepts;
if (!req) {
@@ -953,74 +952,75 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
}
-static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) {
- int result;
- DWORD bytes;
- uv_read_t* req = (uv_read_t*) parameter;
+static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* arg) {
+ uv_read_t* req = (uv_read_t*) arg;
uv_pipe_t* handle = (uv_pipe_t*) req->data;
uv_loop_t* loop = handle->loop;
- HANDLE hThread = NULL;
+ volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
+ CRITICAL_SECTION* lock = &handle->pipe.conn.readfile_thread_lock;
+ HANDLE thread;
+ DWORD bytes;
DWORD err;
- uv_mutex_t *m = &handle->pipe.conn.readfile_mutex;
- assert(req != NULL);
assert(req->type == UV_READ);
assert(handle->type == UV_NAMED_PIPE);
- if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */
- if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
- GetCurrentProcess(), &hThread,
- 0, FALSE, DUPLICATE_SAME_ACCESS)) {
- handle->pipe.conn.readfile_thread = hThread;
- } else {
- hThread = NULL;
- }
- uv_mutex_unlock(m);
+ err = 0;
+
+ /* Create a handle to the current thread. */
+ if (!DuplicateHandle(GetCurrentProcess(),
+ GetCurrentThread(),
+ GetCurrentProcess(),
+ &thread,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ err = GetLastError();
+ goto out1;
}
-restart_readfile:
- if (handle->flags & UV_HANDLE_READING) {
- result = ReadFile(handle->handle,
- &uv_zero_,
- 0,
- &bytes,
- NULL);
- if (!result) {
- err = GetLastError();
- if (err == ERROR_OPERATION_ABORTED &&
- handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- if (handle->flags & UV_HANDLE_READING) {
- /* just a brief break to do something else */
- handle->pipe.conn.readfile_thread = NULL;
- /* resume after it is finished */
- uv_mutex_lock(m);
- handle->pipe.conn.readfile_thread = hThread;
- uv_mutex_unlock(m);
- goto restart_readfile;
- } else {
- result = 1; /* successfully stopped reading */
- }
- }
- }
+
+ /* The lock needs to be held when thread handle is modified. */
+ EnterCriticalSection(lock);
+ if (*thread_ptr == INVALID_HANDLE_VALUE) {
+ /* uv__pipe_interrupt_read() cancelled reading before we got here. */
+ err = ERROR_OPERATION_ABORTED;
} else {
- result = 1; /* successfully aborted read before it even started */
- }
- if (hThread) {
- assert(hThread == handle->pipe.conn.readfile_thread);
- /* mutex does not control clearing readfile_thread */
- handle->pipe.conn.readfile_thread = NULL;
- uv_mutex_lock(m);
- /* only when we hold the mutex lock is it safe to
- open or close the handle */
- CloseHandle(hThread);
- uv_mutex_unlock(m);
+ /* Let main thread know which worker thread is doing the blocking read. */
+ assert(*thread_ptr == NULL);
+ *thread_ptr = thread;
}
+ LeaveCriticalSection(lock);
- if (!result) {
- SET_REQ_ERROR(req, err);
- }
+ if (err)
+ goto out2;
+
+ /* Block the thread until data is available on the pipe, or the read is
+ * cancelled. */
+ if (!ReadFile(handle->handle, &uv_zero_, 0, &bytes, NULL))
+ err = GetLastError();
+
+ /* Let the main thread know the worker is past the point of blocking. */
+ assert(thread == *thread_ptr);
+ *thread_ptr = INVALID_HANDLE_VALUE;
+ /* Briefly acquire the mutex. Since the main thread holds the lock while it
+ * is spinning trying to cancel this thread's I/O, we will block here until
+ * it stops doing that. */
+ EnterCriticalSection(lock);
+ LeaveCriticalSection(lock);
+
+out2:
+ /* Close the handle to the current thread. */
+ CloseHandle(thread);
+
+out1:
+ /* Set request status and post a completion record to the IOCP. */
+ if (err)
+ SET_REQ_ERROR(req, err);
+ else
+ SET_REQ_SUCCESS(req);
POST_COMPLETION_FOR_REQ(loop, req);
+
return 0;
}
@@ -1102,6 +1102,7 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
req = &handle->read_req;
if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
+ handle->pipe.conn.readfile_thread_handle = NULL; /* Reset cancellation. */
if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc,
req,
WT_EXECUTELONGFUNCTION)) {
@@ -1169,8 +1170,8 @@ int uv_pipe_read_start(uv_pipe_t* handle,
handle->read_cb = read_cb;
handle->alloc_cb = alloc_cb;
- /* If reading was stopped and then started again, there could still be a */
- /* read request pending. */
+ /* If reading was stopped and then started again, there could still be a read
+ * request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING))
uv_pipe_queue_read(loop, handle);
@@ -1226,154 +1227,111 @@ static void uv_queue_non_overlapped_write(uv_pipe_t* handle) {
}
-static int uv_pipe_write_impl(uv_loop_t* loop,
- uv_write_t* req,
- uv_pipe_t* handle,
- const uv_buf_t bufs[],
- unsigned int nbufs,
- uv_stream_t* send_handle,
- uv_write_cb cb) {
- int err;
- int result;
- uv_tcp_t* tcp_send_handle;
- uv_write_t* ipc_header_req = NULL;
- uv_ipc_frame_uv_stream ipc_frame;
+static int uv__build_coalesced_write_req(uv_write_t* user_req,
+ const uv_buf_t bufs[],
+ size_t nbufs,
+ uv_write_t** req_out,
+ uv_buf_t* write_buf_out) {
+ /* Pack into a single heap-allocated buffer:
+ * (a) a uv_write_t structure where libuv stores the actual state.
+ * (b) a pointer to the original uv_write_t.
+ * (c) data from all `bufs` entries.
+ */
+ char* heap_buffer;
+ size_t heap_buffer_length, heap_buffer_offset;
+ uv__coalesced_write_t* coalesced_write_req; /* (a) + (b) */
+ char* data_start; /* (c) */
+ size_t data_length;
+ unsigned int i;
+
+ /* Compute combined size of all combined buffers from `bufs`. */
+ data_length = 0;
+ for (i = 0; i < nbufs; i++)
+ data_length += bufs[i].len;
+
+ /* The total combined size of data buffers should not exceed UINT32_MAX,
+ * because WriteFile() won't accept buffers larger than that. */
+ if (data_length > UINT32_MAX)
+ return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
+
+ /* Compute heap buffer size. */
+ heap_buffer_length = sizeof *coalesced_write_req + /* (a) + (b) */
+ data_length; /* (c) */
+
+ /* Allocate buffer. */
+ heap_buffer = uv__malloc(heap_buffer_length);
+ if (heap_buffer == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */
+
+ /* Copy uv_write_t information to the buffer. */
+ coalesced_write_req = (uv__coalesced_write_t*) heap_buffer;
+ coalesced_write_req->req = *user_req; /* copy (a) */
+ coalesced_write_req->req.coalesced = 1;
+ coalesced_write_req->user_req = user_req; /* copy (b) */
+ heap_buffer_offset = sizeof *coalesced_write_req; /* offset (a) + (b) */
+
+ /* Copy data buffers to the heap buffer. */
+ data_start = &heap_buffer[heap_buffer_offset];
+ for (i = 0; i < nbufs; i++) {
+ memcpy(&heap_buffer[heap_buffer_offset],
+ bufs[i].base,
+ bufs[i].len); /* copy (c) */
+ heap_buffer_offset += bufs[i].len; /* offset (c) */
+ }
+ assert(heap_buffer_offset == heap_buffer_length);
+
+ /* Set out arguments and return. */
+ *req_out = &coalesced_write_req->req;
+ *write_buf_out = uv_buf_init(data_start, (unsigned int) data_length);
+ return 0;
+}
- if (nbufs != 1 && (nbufs != 0 || !send_handle)) {
- return ERROR_NOT_SUPPORTED;
- }
- /* Only TCP handles are supported for sharing. */
- if (send_handle && ((send_handle->type != UV_TCP) ||
- (!(send_handle->flags & UV_HANDLE_BOUND) &&
- !(send_handle->flags & UV_HANDLE_CONNECTION)))) {
- return ERROR_NOT_SUPPORTED;
- }
+static int uv__pipe_write_data(uv_loop_t* loop,
+ uv_write_t* req,
+ uv_pipe_t* handle,
+ const uv_buf_t bufs[],
+ size_t nbufs,
+ uv_stream_t* send_handle,
+ uv_write_cb cb,
+ bool copy_always) {
+ int err;
+ int result;
+ uv_buf_t write_buf;
assert(handle->handle != INVALID_HANDLE_VALUE);
UV_REQ_INIT(req, UV_WRITE);
req->handle = (uv_stream_t*) handle;
+ req->send_handle = send_handle;
req->cb = cb;
- req->ipc_header = 0;
+ /* Private fields. */
+ req->coalesced = 0;
req->event_handle = NULL;
req->wait_handle = INVALID_HANDLE_VALUE;
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-
- if (handle->ipc) {
- assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
- ipc_frame.header.flags = 0;
-
- /* Use the IPC framing protocol. */
- if (send_handle) {
- tcp_send_handle = (uv_tcp_t*)send_handle;
-
- if (handle->pipe.conn.ipc_pid == 0) {
- handle->pipe.conn.ipc_pid = uv_current_pid();
- }
-
- err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid,
- &ipc_frame.socket_info_ex.socket_info);
- if (err) {
- return err;
- }
-
- ipc_frame.socket_info_ex.delayed_error = tcp_send_handle->delayed_error;
-
- ipc_frame.header.flags |= UV_IPC_TCP_SERVER;
-
- if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) {
- ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION;
- }
- }
-
- if (nbufs == 1) {
- ipc_frame.header.flags |= UV_IPC_RAW_DATA;
- ipc_frame.header.raw_data_length = bufs[0].len;
- }
-
- /*
- * Use the provided req if we're only doing a single write.
- * If we're doing multiple writes, use ipc_header_write_req to do
- * the first write, and then use the provided req for the second write.
- */
- if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) {
- ipc_header_req = req;
- } else {
- /*
- * Try to use the preallocated write req if it's available.
- * Otherwise allocate a new one.
- */
- if (handle->pipe.conn.ipc_header_write_req.type != UV_WRITE) {
- ipc_header_req = (uv_write_t*)&handle->pipe.conn.ipc_header_write_req;
- } else {
- ipc_header_req = (uv_write_t*)uv__malloc(sizeof(uv_write_t));
- if (!ipc_header_req) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
- }
- }
-
- UV_REQ_INIT(ipc_header_req, UV_WRITE);
- ipc_header_req->handle = (uv_stream_t*) handle;
- ipc_header_req->cb = NULL;
- ipc_header_req->ipc_header = 1;
- }
-
- /* Write the header or the whole frame. */
- memset(&ipc_header_req->u.io.overlapped, 0,
- sizeof(ipc_header_req->u.io.overlapped));
-
- /* Using overlapped IO, but wait for completion before returning.
- This write is blocking because ipc_frame is on stack. */
- ipc_header_req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL);
- if (!ipc_header_req->u.io.overlapped.hEvent) {
- uv_fatal_error(GetLastError(), "CreateEvent");
- }
-
- result = WriteFile(handle->handle,
- &ipc_frame,
- ipc_frame.header.flags & UV_IPC_TCP_SERVER ?
- sizeof(ipc_frame) : sizeof(ipc_frame.header),
- NULL,
- &ipc_header_req->u.io.overlapped);
- if (!result && GetLastError() != ERROR_IO_PENDING) {
- err = GetLastError();
- CloseHandle(ipc_header_req->u.io.overlapped.hEvent);
+ req->write_buffer = uv_null_buf_;
+
+ if (nbufs == 0) {
+ /* Write empty buffer. */
+ write_buf = uv_null_buf_;
+ } else if (nbufs == 1 && !copy_always) {
+ /* Write directly from bufs[0]. */
+ write_buf = bufs[0];
+ } else {
+ /* Coalesce all `bufs` into one big buffer. This also creates a new
+ * write-request structure that replaces the old one. */
+ err = uv__build_coalesced_write_req(req, bufs, nbufs, &req, &write_buf);
+ if (err != 0)
return err;
- }
-
- if (!result) {
- /* Request not completed immediately. Wait for it.*/
- if (WaitForSingleObject(ipc_header_req->u.io.overlapped.hEvent, INFINITE) !=
- WAIT_OBJECT_0) {
- err = GetLastError();
- CloseHandle(ipc_header_req->u.io.overlapped.hEvent);
- return err;
- }
- }
- ipc_header_req->u.io.queued_bytes = 0;
- CloseHandle(ipc_header_req->u.io.overlapped.hEvent);
- ipc_header_req->u.io.overlapped.hEvent = NULL;
-
- REGISTER_HANDLE_REQ(loop, handle, ipc_header_req);
- handle->reqs_pending++;
- handle->stream.conn.write_reqs_pending++;
-
- /* If we don't have any raw data to write - we're done. */
- if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) {
- return 0;
- }
}
if ((handle->flags &
(UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) ==
(UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) {
DWORD bytes;
- result = WriteFile(handle->handle,
- bufs[0].base,
- bufs[0].len,
- &bytes,
- NULL);
+ result =
+ WriteFile(handle->handle, write_buf.base, write_buf.len, &bytes, NULL);
if (!result) {
err = GetLastError();
@@ -1389,14 +1347,14 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
POST_COMPLETION_FOR_REQ(loop, req);
return 0;
} else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
- req->write_buffer = bufs[0];
+ req->write_buffer = write_buf;
uv_insert_non_overlapped_write_req(handle, req);
if (handle->stream.conn.write_reqs_pending == 0) {
uv_queue_non_overlapped_write(handle);
}
/* Request queued by the kernel. */
- req->u.io.queued_bytes = bufs[0].len;
+ req->u.io.queued_bytes = write_buf.len;
handle->write_queue_size += req->u.io.queued_bytes;
} else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) {
/* Using overlapped IO, but wait for completion before returning */
@@ -1406,8 +1364,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
}
result = WriteFile(handle->handle,
- bufs[0].base,
- bufs[0].len,
+ write_buf.base,
+ write_buf.len,
NULL,
&req->u.io.overlapped);
@@ -1422,13 +1380,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
req->u.io.queued_bytes = 0;
} else {
/* Request queued by the kernel. */
- req->u.io.queued_bytes = bufs[0].len;
+ req->u.io.queued_bytes = write_buf.len;
handle->write_queue_size += req->u.io.queued_bytes;
if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) !=
WAIT_OBJECT_0) {
err = GetLastError();
CloseHandle(req->u.io.overlapped.hEvent);
- return uv_translate_sys_error(err);
+ return err;
}
}
CloseHandle(req->u.io.overlapped.hEvent);
@@ -1439,8 +1397,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
return 0;
} else {
result = WriteFile(handle->handle,
- bufs[0].base,
- bufs[0].len,
+ write_buf.base,
+ write_buf.len,
NULL,
&req->u.io.overlapped);
@@ -1453,7 +1411,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
req->u.io.queued_bytes = 0;
} else {
/* Request queued by the kernel. */
- req->u.io.queued_bytes = bufs[0].len;
+ req->u.io.queued_bytes = write_buf.len;
handle->write_queue_size += req->u.io.queued_bytes;
}
@@ -1478,35 +1436,140 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
}
-int uv_pipe_write(uv_loop_t* loop,
- uv_write_t* req,
- uv_pipe_t* handle,
- const uv_buf_t bufs[],
- unsigned int nbufs,
- uv_write_cb cb) {
- return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, NULL, cb);
+static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t* handle) {
+ DWORD* pid = &handle->pipe.conn.ipc_remote_pid;
+
+ /* If the both ends of the IPC pipe are owned by the same process,
+ * the remote end pid may not yet be set. If so, do it here.
+ * TODO: this is weird; it'd probably better to use a handshake. */
+ if (*pid == 0)
+ *pid = GetCurrentProcessId();
+
+ return *pid;
+}
+
+
+int uv__pipe_write_ipc(uv_loop_t* loop,
+ uv_write_t* req,
+ uv_pipe_t* handle,
+ const uv_buf_t data_bufs[],
+ size_t data_buf_count,
+ uv_stream_t* send_handle,
+ uv_write_cb cb) {
+ uv_buf_t stack_bufs[6];
+ uv_buf_t* bufs;
+ size_t buf_count, buf_index;
+ uv__ipc_frame_header_t xfer_frame_header;
+ uv__ipc_socket_xfer_info_t xfer_info;
+ uv__ipc_frame_header_t data_frame_header;
+ size_t data_length;
+ size_t i;
+ int err;
+
+ /* Compute the combined size of data buffers. */
+ data_length = 0;
+ for (i = 0; i < data_buf_count; i++)
+ data_length += data_bufs[i].len;
+ if (data_length > UINT32_MAX)
+ return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
+
+ /* Prepare xfer frame payload. */
+ if (send_handle) {
+ uv_tcp_t* send_tcp_handle = (uv_tcp_t*) send_handle;
+
+ /* Verify that `send_handle` it is indeed a tcp handle. */
+ if (send_tcp_handle->type != UV_TCP)
+ return ERROR_NOT_SUPPORTED;
+
+ /* Export the tcp handle. */
+ err = uv__tcp_xfer_export(
+ send_tcp_handle, uv__pipe_get_ipc_remote_pid(handle), &xfer_info);
+ if (err != 0)
+ return err;
+ }
+
+ /* Compute the number of uv_buf_t's required. */
+ buf_count = 0;
+ if (send_handle != NULL) {
+ buf_count += 2; /* One for the frame header, one for the payload. */
+ }
+ if (data_buf_count > 0) {
+ buf_count += 1 + data_buf_count; /* One extra for the frame header. */
+ }
+
+ /* Use the on-stack buffer array if it is big enough; otherwise allocate
+ * space for it on the heap. */
+ if (buf_count < ARRAY_SIZE(stack_bufs)) {
+ /* Use on-stack buffer array. */
+ bufs = stack_bufs;
+ } else {
+ /* Use heap-allocated buffer array. */
+ bufs = uv__calloc(buf_count, sizeof(uv_buf_t));
+ if (bufs == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */
+ }
+ buf_index = 0;
+
+ if (send_handle != NULL) {
+ /* Add xfer frame header. */
+ xfer_frame_header.type = UV__IPC_XFER_FRAME;
+ xfer_frame_header.payload_length = sizeof xfer_info;
+ bufs[buf_index++] =
+ uv_buf_init((char*) &xfer_frame_header, sizeof xfer_frame_header);
+
+ /* Add xfer frame payload. */
+ bufs[buf_index++] = uv_buf_init((char*) &xfer_info, sizeof xfer_info);
+ }
+
+ if (data_length > 0) {
+ /* Add data frame header. */
+ data_frame_header.type = UV__IPC_DATA_FRAME;
+ data_frame_header.payload_length = (uint32_t) data_length;
+ bufs[buf_index++] =
+ uv_buf_init((char*) &data_frame_header, sizeof data_frame_header);
+
+ /* Add data buffers. */
+ for (i = 0; i < data_buf_count; i++)
+ bufs[buf_index++] = data_bufs[i];
+ }
+
+ /* Write buffers. We set the `always_copy` flag, so it is not a problem that
+ * some of the written data lives on the stack. */
+ err = uv__pipe_write_data(
+ loop, req, handle, bufs, buf_count, send_handle, cb, true);
+
+ /* If we had to heap-allocate the bufs array, free it now. */
+ if (bufs != stack_bufs) {
+ uv__free(bufs);
+ }
+
+ return err;
}
-int uv_pipe_write2(uv_loop_t* loop,
+int uv__pipe_write(uv_loop_t* loop,
uv_write_t* req,
uv_pipe_t* handle,
const uv_buf_t bufs[],
- unsigned int nbufs,
+ size_t nbufs,
uv_stream_t* send_handle,
uv_write_cb cb) {
- if (!handle->ipc) {
- return WSAEINVAL;
+ if (handle->ipc) {
+ /* IPC pipe write: use framing protocol. */
+ return uv__pipe_write_ipc(loop, req, handle, bufs, nbufs, send_handle, cb);
+ } else {
+ /* Non-IPC pipe write: put data on the wire directly. */
+ assert(send_handle == NULL);
+ return uv__pipe_write_data(
+ loop, req, handle, bufs, nbufs, NULL, cb, false);
}
-
- return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, send_handle, cb);
}
static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
uv_buf_t buf) {
- /* If there is an eof timer running, we don't need it any more, */
- /* so discard it. */
+ /* If there is an eof timer running, we don't need it any more, so discard
+ * it. */
eof_timer_destroy(handle);
handle->flags &= ~UV_HANDLE_READABLE;
@@ -1518,8 +1581,8 @@ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
uv_buf_t buf) {
- /* If there is an eof timer running, we don't need it any more, */
- /* so discard it. */
+ /* If there is an eof timer running, we don't need it any more, so discard
+ * it. */
eof_timer_destroy(handle);
uv_read_stop((uv_stream_t*) handle);
@@ -1530,10 +1593,7 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
int error, uv_buf_t buf) {
- if (error == ERROR_OPERATION_ABORTED) {
- /* do nothing (equivalent to EINTR) */
- }
- else if (error == ERROR_BROKEN_PIPE) {
+ if (error == ERROR_BROKEN_PIPE) {
uv_pipe_read_eof(loop, handle, buf);
} else {
uv_pipe_read_error(loop, handle, error, buf);
@@ -1541,152 +1601,198 @@ static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
}
-void uv__pipe_insert_pending_socket(uv_pipe_t* handle,
- uv__ipc_socket_info_ex* info,
- int tcp_connection) {
- uv__ipc_queue_item_t* item;
+static void uv__pipe_queue_ipc_xfer_info(
+ uv_pipe_t* handle, uv__ipc_socket_xfer_info_t* xfer_info) {
+ uv__ipc_xfer_queue_item_t* item;
- item = (uv__ipc_queue_item_t*) uv__malloc(sizeof(*item));
+ item = (uv__ipc_xfer_queue_item_t*) uv__malloc(sizeof(*item));
if (item == NULL)
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
- memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex));
- item->tcp_connection = tcp_connection;
- QUEUE_INSERT_TAIL(&handle->pipe.conn.pending_ipc_info.queue, &item->member);
- handle->pipe.conn.pending_ipc_info.queue_len++;
+ memcpy(&item->xfer_info, xfer_info, sizeof(item->xfer_info));
+ QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member);
+ handle->pipe.conn.ipc_xfer_queue_length++;
}
-void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
- uv_req_t* req) {
- DWORD bytes, avail;
+/* Read an exact number of bytes from a pipe. If an error or end-of-file is
+ * encountered before the requested number of bytes are read, an error is
+ * returned. */
+static int uv__pipe_read_exactly(HANDLE h, void* buffer, DWORD count) {
+ DWORD bytes_read, bytes_read_now;
+
+ bytes_read = 0;
+ while (bytes_read < count) {
+ if (!ReadFile(h,
+ (char*) buffer + bytes_read,
+ count - bytes_read,
+ &bytes_read_now,
+ NULL)) {
+ return GetLastError();
+ }
+
+ bytes_read += bytes_read_now;
+ }
+
+ assert(bytes_read == count);
+ return 0;
+}
+
+
+static DWORD uv__pipe_read_data(uv_loop_t* loop,
+ uv_pipe_t* handle,
+ DWORD suggested_bytes,
+ DWORD max_bytes) {
+ DWORD bytes_read;
uv_buf_t buf;
- uv_ipc_frame_uv_stream ipc_frame;
+ /* Ask the user for a buffer to read data into. */
+ buf = uv_buf_init(NULL, 0);
+ handle->alloc_cb((uv_handle_t*) handle, suggested_bytes, &buf);
+ if (buf.base == NULL || buf.len == 0) {
+ handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
+ return 0; /* Break out of read loop. */
+ }
+
+ /* Ensure we read at most the smaller of:
+ * (a) the length of the user-allocated buffer.
+ * (b) the maximum data length as specified by the `max_bytes` argument.
+ */
+ if (max_bytes > buf.len)
+ max_bytes = buf.len;
+
+ /* Read into the user buffer. */
+ if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) {
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
+ return 0; /* Break out of read loop. */
+ }
+
+ /* Call the read callback. */
+ handle->read_cb((uv_stream_t*) handle, bytes_read, &buf);
+
+ return bytes_read;
+}
+
+
+static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
+ DWORD* data_remaining = &handle->pipe.conn.ipc_data_frame.payload_remaining;
+ int err;
+
+ if (*data_remaining > 0) {
+ /* Read data frame payload. */
+ DWORD bytes_read =
+ uv__pipe_read_data(loop, handle, *data_remaining, *data_remaining);
+ *data_remaining -= bytes_read;
+ return bytes_read;
+
+ } else {
+ /* Start of a new IPC frame. */
+ uv__ipc_frame_header_t frame_header;
+ uv__ipc_socket_xfer_info_t xfer_info;
+
+ /* Read the IPC frame header. */
+ err = uv__pipe_read_exactly(
+ handle->handle, &frame_header, sizeof frame_header);
+ if (err)
+ goto error;
+
+ if (frame_header.type == UV__IPC_DATA_FRAME) {
+ /* Data frame: capture payload length. Actual data will be read in
+ * subsequent call to uv__pipe_read_ipc(). */
+ *data_remaining = frame_header.payload_length;
+
+ /* Return number of bytes read. */
+ return sizeof frame_header;
+
+ } else if (frame_header.type == UV__IPC_XFER_FRAME) {
+ /* Xfer frame: read the payload. */
+ assert(frame_header.payload_length == sizeof xfer_info);
+ err =
+ uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info);
+ if (err)
+ goto error;
+
+ /* Store the pending socket info. */
+ uv__pipe_queue_ipc_xfer_info(handle, &xfer_info);
+
+ /* Return number of bytes read. */
+ return sizeof frame_header + sizeof xfer_info;
+ }
+
+ /* Invalid frame. */
+ err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */
+ }
+
+error:
+ uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
+ return 0; /* Break out of read loop. */
+}
+
+
+void uv_process_pipe_read_req(uv_loop_t* loop,
+ uv_pipe_t* handle,
+ uv_req_t* req) {
assert(handle->type == UV_NAMED_PIPE);
- handle->flags &= ~UV_HANDLE_READ_PENDING;
+ handle->flags &= ~(UV_HANDLE_READ_PENDING | UV_HANDLE_CANCELLATION_PENDING);
+ DECREASE_PENDING_REQ_COUNT(handle);
eof_timer_stop(handle);
- if (!REQ_SUCCESS(req)) {
- /* An error occurred doing the 0-read. */
- if (handle->flags & UV_HANDLE_READING) {
- uv_pipe_read_error_or_eof(loop,
- handle,
- GET_REQ_ERROR(req),
- uv_null_buf_);
- }
- } else {
- /* Do non-blocking reads until the buffer is empty */
- while (handle->flags & UV_HANDLE_READING) {
- if (!PeekNamedPipe(handle->handle,
- NULL,
- 0,
- NULL,
- &avail,
- NULL)) {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
- break;
- }
+ /* At this point, we're done with bookkeeping. If the user has stopped
+ * reading the pipe in the meantime, there is nothing left to do, since there
+ * is no callback that we can call. */
+ if (!(handle->flags & UV_HANDLE_READING))
+ return;
- if (avail == 0) {
- /* There is nothing to read after all. */
- break;
- }
+ if (!REQ_SUCCESS(req)) {
+ /* An error occurred doing the zero-read. */
+ DWORD err = GET_REQ_ERROR(req);
- if (handle->ipc) {
- /* Use the IPC framing protocol to read the incoming data. */
- if (handle->pipe.conn.remaining_ipc_rawdata_bytes == 0) {
- /* We're reading a new frame. First, read the header. */
- assert(avail >= sizeof(ipc_frame.header));
-
- if (!ReadFile(handle->handle,
- &ipc_frame.header,
- sizeof(ipc_frame.header),
- &bytes,
- NULL)) {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(),
- uv_null_buf_);
- break;
- }
-
- assert(bytes == sizeof(ipc_frame.header));
- assert(ipc_frame.header.flags <= (UV_IPC_TCP_SERVER | UV_IPC_RAW_DATA |
- UV_IPC_TCP_CONNECTION));
-
- if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) {
- assert(avail - sizeof(ipc_frame.header) >=
- sizeof(ipc_frame.socket_info_ex));
-
- /* Read the TCP socket info. */
- if (!ReadFile(handle->handle,
- &ipc_frame.socket_info_ex,
- sizeof(ipc_frame) - sizeof(ipc_frame.header),
- &bytes,
- NULL)) {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(),
- uv_null_buf_);
- break;
- }
-
- assert(bytes == sizeof(ipc_frame) - sizeof(ipc_frame.header));
-
- /* Store the pending socket info. */
- uv__pipe_insert_pending_socket(
- handle,
- &ipc_frame.socket_info_ex,
- ipc_frame.header.flags & UV_IPC_TCP_CONNECTION);
- }
-
- if (ipc_frame.header.flags & UV_IPC_RAW_DATA) {
- handle->pipe.conn.remaining_ipc_rawdata_bytes =
- ipc_frame.header.raw_data_length;
- continue;
- }
- } else {
- avail = min(avail, (DWORD)handle->pipe.conn.remaining_ipc_rawdata_bytes);
- }
- }
+ /* If the read was cancelled by uv__pipe_interrupt_read(), the request may
+ * indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to
+ * the user; we'll start a new zero-read at the end of this function. */
+ if (err != ERROR_OPERATION_ABORTED)
+ uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
- buf = uv_buf_init(NULL, 0);
- handle->alloc_cb((uv_handle_t*) handle, avail, &buf);
- if (buf.base == NULL || buf.len == 0) {
- handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
+ } else {
+ /* The zero-read completed without error, indicating there is data
+ * available in the kernel buffer. */
+ DWORD avail;
+
+ /* Get the number of bytes available. */
+ avail = 0;
+ if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL))
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
+
+ /* Read until we've either read all the bytes available, or the 'reading'
+ * flag is cleared. */
+ while (avail > 0 && handle->flags & UV_HANDLE_READING) {
+ /* Depending on the type of pipe, read either IPC frames or raw data. */
+ DWORD bytes_read =
+ handle->ipc ? uv__pipe_read_ipc(loop, handle)
+ : uv__pipe_read_data(loop, handle, avail, (DWORD) -1);
+
+ /* If no bytes were read, treat this as an indication that an error
+ * occurred, and break out of the read loop. */
+ if (bytes_read == 0)
break;
- }
- assert(buf.base != NULL);
-
- if (ReadFile(handle->handle,
- buf.base,
- min(buf.len, avail),
- &bytes,
- NULL)) {
- /* Successful read */
- if (handle->ipc) {
- assert(handle->pipe.conn.remaining_ipc_rawdata_bytes >= bytes);
- handle->pipe.conn.remaining_ipc_rawdata_bytes =
- handle->pipe.conn.remaining_ipc_rawdata_bytes - bytes;
- }
- handle->read_cb((uv_stream_t*)handle, bytes, &buf);
- /* Read again only if bytes == buf.len */
- if (bytes <= buf.len) {
- break;
- }
- } else {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
+ /* It is possible that more bytes were read than we thought were
+ * available. To prevent `avail` from underflowing, break out of the loop
+ * if this is the case. */
+ if (bytes_read > avail)
break;
- }
- }
- /* Post another 0-read if still reading and not closing. */
- if ((handle->flags & UV_HANDLE_READING) &&
- !(handle->flags & UV_HANDLE_READ_PENDING)) {
- uv_pipe_queue_read(loop, handle);
+ /* Recompute the number of bytes available. */
+ avail -= bytes_read;
}
}
- DECREASE_PENDING_REQ_COUNT(handle);
+ /* Start another zero-read request if necessary. */
+ if ((handle->flags & UV_HANDLE_READING) &&
+ !(handle->flags & UV_HANDLE_READ_PENDING)) {
+ uv_pipe_queue_read(loop, handle);
+ }
}
@@ -1712,17 +1818,19 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
}
}
- if (req->ipc_header) {
- if (req == &handle->pipe.conn.ipc_header_write_req) {
- req->type = UV_UNKNOWN_REQ;
- } else {
- uv__free(req);
- }
- } else {
- if (req->cb) {
- err = GET_REQ_ERROR(req);
- req->cb(req, uv_translate_sys_error(err));
- }
+ err = GET_REQ_ERROR(req);
+
+ /* If this was a coalesced write, extract pointer to the user_provided
+ * uv_write_t structure so we can pass the expected pointer to the callback,
+ * then free the heap-allocated write req. */
+ if (req->coalesced) {
+ uv__coalesced_write_t* coalesced_write =
+ container_of(req, uv__coalesced_write_t, req);
+ req = coalesced_write->user_req;
+ uv__free(coalesced_write);
+ }
+ if (req->cb) {
+ req->cb(req, uv_translate_sys_error(err));
}
handle->stream.conn.write_reqs_pending--;
@@ -1806,19 +1914,19 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (handle->flags & UV_HANDLE_READABLE) {
- /* Initialize and optionally start the eof timer. Only do this if the */
- /* pipe is readable and we haven't seen EOF come in ourselves. */
+ /* Initialize and optionally start the eof timer. Only do this if the pipe
+ * is readable and we haven't seen EOF come in ourselves. */
eof_timer_init(handle);
- /* If reading start the timer right now. */
- /* Otherwise uv_pipe_queue_read will start it. */
+ /* If reading start the timer right now. Otherwise uv_pipe_queue_read will
+ * start it. */
if (handle->flags & UV_HANDLE_READ_PENDING) {
eof_timer_start(handle);
}
} else {
- /* This pipe is not readable. We can just close it to let the other end */
- /* know that we're done writing. */
+ /* This pipe is not readable. We can just close it to let the other end
+ * know that we're done writing. */
close_pipe(handle);
}
@@ -1869,17 +1977,16 @@ static void eof_timer_cb(uv_timer_t* timer) {
assert(pipe->type == UV_NAMED_PIPE);
- /* This should always be true, since we start the timer only */
- /* in uv_pipe_queue_read after successfully calling ReadFile, */
- /* or in uv_process_pipe_shutdown_req if a read is pending, */
- /* and we always immediately stop the timer in */
- /* uv_process_pipe_read_req. */
+ /* This should always be true, since we start the timer only in
+ * uv_pipe_queue_read after successfully calling ReadFile, or in
+ * uv_process_pipe_shutdown_req if a read is pending, and we always
+ * immediately stop the timer in uv_process_pipe_read_req. */
assert(pipe->flags & UV_HANDLE_READ_PENDING);
- /* If there are many packets coming off the iocp then the timer callback */
- /* may be called before the read request is coming off the queue. */
- /* Therefore we check here if the read request has completed but will */
- /* be processed later. */
+ /* If there are many packets coming off the iocp then the timer callback may
+ * be called before the read request is coming off the queue. Therefore we
+ * check here if the read request has completed but will be processed later.
+ */
if ((pipe->flags & UV_HANDLE_READ_PENDING) &&
HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) {
return;
@@ -1888,12 +1995,12 @@ static void eof_timer_cb(uv_timer_t* timer) {
/* Force both ends off the pipe. */
close_pipe(pipe);
- /* Stop reading, so the pending read that is going to fail will */
- /* not be reported to the user. */
+ /* Stop reading, so the pending read that is going to fail will not be
+ * reported to the user. */
uv_read_stop((uv_stream_t*) pipe);
- /* Report the eof and update flags. This will get reported even if the */
- /* user stopped reading in the meantime. TODO: is that okay? */
+ /* Report the eof and update flags. This will get reported even if the user
+ * stopped reading in the meantime. TODO: is that okay? */
uv_pipe_read_eof(loop, pipe, uv_null_buf_);
}
@@ -1980,8 +2087,8 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
if (pipe->ipc) {
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
- pipe->pipe.conn.ipc_pid = uv_os_getppid();
- assert(pipe->pipe.conn.ipc_pid != -1);
+ pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
+ assert(pipe->pipe.conn.ipc_remote_pid != -1);
}
return 0;
}
@@ -2006,7 +2113,15 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
return UV_EINVAL;
}
- uv__pipe_pause_read((uv_pipe_t*)handle); /* cast away const warning */
+ /* NtQueryInformationFile will block if another thread is performing a
+ * blocking operation on the queried handle. If the pipe handle is
+ * synchronous, there may be a worker thread currently calling ReadFile() on
+ * the pipe handle, which could cause a deadlock. To avoid this, interrupt
+ * the read. */
+ if (handle->flags & UV_HANDLE_CONNECTION &&
+ handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
+ uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */
+ }
nt_status = pNtQueryInformationFile(handle->handle,
&io_status,
@@ -2097,7 +2212,6 @@ error:
uv__free(name_info);
cleanup:
- uv__pipe_unpause_read((uv_pipe_t*)handle); /* cast away const warning */
return err;
}
@@ -2105,7 +2219,7 @@ cleanup:
int uv_pipe_pending_count(uv_pipe_t* handle) {
if (!handle->ipc)
return 0;
- return handle->pipe.conn.pending_ipc_info.queue_len;
+ return handle->pipe.conn.ipc_xfer_queue_length;
}
@@ -2138,7 +2252,7 @@ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
if (!handle->ipc)
return UV_UNKNOWN_HANDLE;
- if (handle->pipe.conn.pending_ipc_info.queue_len == 0)
+ if (handle->pipe.conn.ipc_xfer_queue_length == 0)
return UV_UNKNOWN_HANDLE;
else
return UV_TCP;
diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c
index a648ba711d..b1369df3c4 100644
--- a/deps/uv/src/win/poll.c
+++ b/deps/uv/src/win/poll.c
@@ -91,16 +91,16 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
handle->mask_events_1 = handle->events;
handle->mask_events_2 = 0;
} else {
- /* Just wait until there's an unsubmitted req. */
- /* This will happen almost immediately as one of the 2 outstanding */
- /* requests is about to return. When this happens, */
- /* uv__fast_poll_process_poll_req will be called, and the pending */
- /* events, if needed, will be processed in a subsequent request. */
+ /* Just wait until there's an unsubmitted req. This will happen almost
+ * immediately as one of the 2 outstanding requests is about to return.
+ * When this happens, uv__fast_poll_process_poll_req will be called, and
+ * the pending events, if needed, will be processed in a subsequent
+ * request. */
return;
}
- /* Setting Exclusive to TRUE makes the other poll request return if there */
- /* is any. */
+ /* Setting Exclusive to TRUE makes the other poll request return if there is
+ * any. */
afd_poll_info->Exclusive = TRUE;
afd_poll_info->NumberOfHandles = 1;
afd_poll_info->Timeout.QuadPart = INT64_MAX;
@@ -257,8 +257,8 @@ static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
uv_want_endgame(loop, (uv_handle_t*) handle);
return 0;
} else {
- /* Cancel outstanding poll requests by executing another, unique poll */
- /* request that forces the outstanding ones to return. */
+ /* Cancel outstanding poll requests by executing another, unique poll
+ * request that forces the outstanding ones to return. */
return uv__fast_poll_cancel_poll_req(loop, handle);
}
}
@@ -316,9 +316,8 @@ static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
return INVALID_SOCKET;
}
- /* If we didn't (try) to create a peer socket yet, try to make one. Don't */
- /* try again if the peer socket creation failed earlier for the same */
- /* protocol. */
+ /* If we didn't (try) to create a peer socket yet, try to make one. Don't try
+ * again if the peer socket creation failed earlier for the same protocol. */
peer_socket = loop->poll_peer_sockets[index];
if (peer_socket == 0) {
peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
@@ -357,8 +356,8 @@ static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
efds.fd_count = 0;
}
- /* Make the select() time out after 3 minutes. If select() hangs because */
- /* the user closed the socket, we will at least not hang indefinitely. */
+ /* Make the select() time out after 3 minutes. If select() hangs because the
+ * user closed the socket, we will at least not hang indefinitely. */
timeout.tv_sec = 3 * 60;
timeout.tv_usec = 0;
@@ -522,10 +521,10 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
return uv_translate_sys_error(WSAGetLastError());
- /* Try to obtain a base handle for the socket. This increases this chances */
- /* that we find an AFD handle and are able to use the fast poll mechanism. */
- /* This will always fail on windows XP/2k3, since they don't support the */
- /* SIO_BASE_HANDLE ioctl. */
+/* Try to obtain a base handle for the socket. This increases this chances that
+ * we find an AFD handle and are able to use the fast poll mechanism. This will
+ * always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE
+ * ioctl. */
#ifndef NDEBUG
base_socket = INVALID_SOCKET;
#endif
@@ -557,9 +556,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
return uv_translate_sys_error(WSAGetLastError());
}
- /* Get the peer socket that is needed to enable fast poll. If the returned */
- /* value is NULL, the protocol is not implemented by MSAFD and we'll have */
- /* to use slow mode. */
+ /* Get the peer socket that is needed to enable fast poll. If the returned
+ * value is NULL, the protocol is not implemented by MSAFD and we'll have to
+ * use slow mode. */
peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
if (peer_socket != INVALID_SOCKET) {
diff --git a/deps/uv/src/win/process-stdio.c b/deps/uv/src/win/process-stdio.c
index 032e30935c..0ae9f0624a 100644
--- a/deps/uv/src/win/process-stdio.c
+++ b/deps/uv/src/win/process-stdio.c
@@ -105,10 +105,9 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
int err;
if (flags & UV_READABLE_PIPE) {
- /* The server needs inbound access too, otherwise CreateNamedPipe() */
- /* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */
- /* probe the state of the write buffer when we're trying to shutdown */
- /* the pipe. */
+ /* The server needs inbound access too, otherwise CreateNamedPipe() won't
+ * give us the FILE_READ_ATTRIBUTES permission. We need that to probe the
+ * state of the write buffer when we're trying to shutdown the pipe. */
server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
}
@@ -131,12 +130,13 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
+ BOOL overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);
child_pipe = CreateFileA(pipe_name,
client_access,
0,
&sa,
OPEN_EXISTING,
- server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0,
+ overlap ? FILE_FLAG_OVERLAPPED : 0,
NULL);
if (child_pipe == INVALID_HANDLE_VALUE) {
err = GetLastError();
@@ -159,8 +159,8 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
}
#endif
- /* Do a blocking ConnectNamedPipe. This should not block because we have */
- /* both ends of the pipe created. */
+ /* Do a blocking ConnectNamedPipe. This should not block because we have both
+ * ends of the pipe created. */
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
if (GetLastError() != ERROR_PIPE_CONNECTED) {
err = GetLastError();
@@ -194,11 +194,11 @@ static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
HANDLE current_process;
- /* _get_osfhandle will sometimes return -2 in case of an error. This seems */
- /* to happen when fd <= 2 and the process' corresponding stdio handle is */
- /* set to NULL. Unfortunately DuplicateHandle will happily duplicate */
- /* (HANDLE) -2, so this situation goes unnoticed until someone tries to */
- /* use the duplicate. Therefore we filter out known-invalid handles here. */
+ /* _get_osfhandle will sometimes return -2 in case of an error. This seems to
+ * happen when fd <= 2 and the process' corresponding stdio handle is set to
+ * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so
+ * this situation goes unnoticed until someone tries to use the duplicate.
+ * Therefore we filter out known-invalid handles here. */
if (handle == INVALID_HANDLE_VALUE ||
handle == NULL ||
handle == (HANDLE) -2) {
@@ -284,8 +284,8 @@ int uv__stdio_create(uv_loop_t* loop,
return ERROR_OUTOFMEMORY;
}
- /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
- /* clean up on failure. */
+ /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean
+ * up on failure. */
CHILD_STDIO_COUNT(buffer) = count;
for (i = 0; i < count; i++) {
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
@@ -303,12 +303,12 @@ int uv__stdio_create(uv_loop_t* loop,
switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
UV_INHERIT_STREAM)) {
case UV_IGNORE:
- /* Starting a process with no stdin/stout/stderr can confuse it. */
- /* So no matter what the user specified, we make sure the first */
- /* three FDs are always open in their typical modes, e.g. stdin */
- /* be readable and stdout/err should be writable. For FDs > 2, don't */
- /* do anything - all handles in the stdio buffer are initialized with */
- /* INVALID_HANDLE_VALUE, which should be okay. */
+ /* Starting a process with no stdin/stout/stderr can confuse it. So no
+ * matter what the user specified, we make sure the first three FDs are
+ * always open in their typical modes, e. g. stdin be readable and
+ * stdout/err should be writable. For FDs > 2, don't do anything - all
+ * handles in the stdio buffer are initialized with.
+ * INVALID_HANDLE_VALUE, which should be okay. */
if (i <= 2) {
DWORD access = (i == 0) ? FILE_GENERIC_READ :
FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
@@ -323,14 +323,14 @@ int uv__stdio_create(uv_loop_t* loop,
break;
case UV_CREATE_PIPE: {
- /* Create a pair of two connected pipe ends; one end is turned into */
- /* an uv_pipe_t for use by the parent. The other one is given to */
- /* the child. */
+ /* Create a pair of two connected pipe ends; one end is turned into an
+ * uv_pipe_t for use by the parent. The other one is given to the
+ * child. */
uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
HANDLE child_pipe = INVALID_HANDLE_VALUE;
- /* Create a new, connected pipe pair. stdio[i].stream should point */
- /* to an uninitialized, but not connected pipe handle. */
+ /* Create a new, connected pipe pair. stdio[i]. stream should point to
+ * an uninitialized, but not connected pipe handle. */
assert(fdopt.data.stream->type == UV_NAMED_PIPE);
assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
@@ -354,8 +354,8 @@ int uv__stdio_create(uv_loop_t* loop,
/* Make an inheritable duplicate of the handle. */
err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle);
if (err) {
- /* If fdopt.data.fd is not valid and fd fd <= 2, then ignore the */
- /* error. */
+ /* If fdopt. data. fd is not valid and fd <= 2, then ignore the
+ * error. */
if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) {
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
@@ -418,8 +418,8 @@ int uv__stdio_create(uv_loop_t* loop,
if (stream_handle == NULL ||
stream_handle == INVALID_HANDLE_VALUE) {
- /* The handle is already closed, or not yet created, or the */
- /* stream type is not supported. */
+ /* The handle is already closed, or not yet created, or the stream
+ * type is not supported. */
err = ERROR_NOT_SUPPORTED;
goto error;
}
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index 7523522217..08910088e4 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -360,8 +360,8 @@ static WCHAR* search_path(const WCHAR *file,
return NULL;
}
- /* Find the start of the filename so we can split the directory from the */
- /* name. */
+ /* Find the start of the filename so we can split the directory from the
+ * name. */
for (file_name_start = (WCHAR*)file + file_len;
file_name_start > file
&& file_name_start[-1] != L'\\'
@@ -556,8 +556,8 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {
arg_count++;
}
- /* Adjust for potential quotes. Also assume the worst-case scenario */
- /* that every character needs escaping, so we need twice as much space. */
+ /* Adjust for potential quotes. Also assume the worst-case scenario that
+ * every character needs escaping, so we need twice as much space. */
dst_len = dst_len * 2 + arg_count * 2;
/* Allocate buffer for the final command line. */
@@ -831,8 +831,13 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
*/
static WCHAR* find_path(WCHAR *env) {
for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
- if (wcsncmp(env, L"PATH=", 5) == 0)
+ if ((env[0] == L'P' || env[0] == L'p') &&
+ (env[1] == L'A' || env[1] == L'a') &&
+ (env[2] == L'T' || env[2] == L't') &&
+ (env[3] == L'H' || env[3] == L'h') &&
+ (env[4] == L'=')) {
return &env[5];
+ }
}
return NULL;
@@ -865,8 +870,8 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
assert(handle->exit_cb_pending);
handle->exit_cb_pending = 0;
- /* If we're closing, don't call the exit callback. Just schedule a close */
- /* callback now. */
+ /* If we're closing, don't call the exit callback. Just schedule a close
+ * callback now. */
if (handle->flags & UV__HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*) handle);
return;
@@ -878,14 +883,14 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
handle->wait_handle = INVALID_HANDLE_VALUE;
}
- /* Set the handle to inactive: no callbacks will be made after the exit */
- /* callback.*/
+ /* Set the handle to inactive: no callbacks will be made after the exit
+ * callback. */
uv__handle_stop(handle);
if (GetExitCodeProcess(handle->process_handle, &status)) {
exit_code = status;
} else {
- /* Unable to to obtain the exit code. This should never happen. */
+ /* Unable to obtain the exit code. This should never happen. */
exit_code = uv_translate_sys_error(GetLastError());
}
@@ -900,8 +905,8 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
uv__handle_closing(handle);
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
- /* This blocks until either the wait was cancelled, or the callback has */
- /* completed. */
+ /* This blocks until either the wait was cancelled, or the callback has
+ * completed. */
BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
if (!r) {
/* This should never happen, and if it happens, we can't recover... */
@@ -1104,14 +1109,13 @@ int uv_spawn(uv_loop_t* loop,
goto done;
}
- /* Spawn succeeded */
- /* Beyond this point, failure is reported asynchronously. */
+ /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
process->process_handle = info.hProcess;
process->pid = info.dwProcessId;
- /* If the process isn't spawned as detached, assign to the global job */
- /* object so windows will kill it when the parent process dies. */
+ /* If the process isn't spawned as detached, assign to the global job object
+ * so windows will kill it when the parent process dies. */
if (!(options->flags & UV_PROCESS_DETACHED)) {
uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
@@ -1138,7 +1142,8 @@ int uv_spawn(uv_loop_t* loop,
if (fdopt->flags & UV_CREATE_PIPE &&
fdopt->data.stream->type == UV_NAMED_PIPE &&
((uv_pipe_t*) fdopt->data.stream)->ipc) {
- ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId;
+ ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid =
+ info.dwProcessId;
}
}
@@ -1154,8 +1159,8 @@ int uv_spawn(uv_loop_t* loop,
assert(!err);
- /* Make the handle active. It will remain active until the exit callback */
- /* is made or the handle is closed, whichever happens first. */
+ /* Make the handle active. It will remain active until the exit callback is
+ * made or the handle is closed, whichever happens first. */
uv__handle_start(process);
/* Cleanup, whether we succeeded or failed. */
@@ -1186,16 +1191,16 @@ static int uv__kill(HANDLE process_handle, int signum) {
case SIGTERM:
case SIGKILL:
case SIGINT: {
- /* Unconditionally terminate the process. On Windows, killed processes */
- /* normally return 1. */
+ /* Unconditionally terminate the process. On Windows, killed processes
+ * normally return 1. */
DWORD status;
int err;
if (TerminateProcess(process_handle, 1))
return 0;
- /* If the process already exited before TerminateProcess was called, */
- /* TerminateProcess will fail with ERROR_ACCESS_DENIED. */
+ /* If the process already exited before TerminateProcess was called,.
+ * TerminateProcess will fail with ERROR_ACCESS_DENIED. */
err = GetLastError();
if (err == ERROR_ACCESS_DENIED &&
GetExitCodeProcess(process_handle, &status) &&
diff --git a/deps/uv/src/win/signal.c b/deps/uv/src/win/signal.c
index a174da1f76..750c1b36ef 100644
--- a/deps/uv/src/win/signal.c
+++ b/deps/uv/src/win/signal.c
@@ -47,13 +47,13 @@ void uv_signals_init(void) {
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
- /* Compare signums first so all watchers with the same signnum end up */
- /* adjacent. */
+ /* Compare signums first so all watchers with the same signnum end up
+ * adjacent. */
if (w1->signum < w2->signum) return -1;
if (w1->signum > w2->signum) return 1;
- /* Sort by loop pointer, so we can easily look up the first item after */
- /* { .signum = x, .loop = NULL } */
+ /* Sort by loop pointer, so we can easily look up the first item after
+ * { .signum = x, .loop = NULL }. */
if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1;
if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1;
@@ -118,10 +118,10 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
case CTRL_CLOSE_EVENT:
if (uv__signal_dispatch(SIGHUP)) {
- /* Windows will terminate the process after the control handler */
- /* returns. After that it will just terminate our process. Therefore */
- /* block the signal handler so the main loop has some time to pick */
- /* up the signal and do something for a few seconds. */
+ /* Windows will terminate the process after the control handler
+ * returns. After that it will just terminate our process. Therefore
+ * block the signal handler so the main loop has some time to pick up
+ * the signal and do something for a few seconds. */
Sleep(INFINITE);
return TRUE;
}
@@ -129,8 +129,8 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
- /* These signals are only sent to services. Services have their own */
- /* notification mechanism, so there's no point in handling these. */
+ /* These signals are only sent to services. Services have their own
+ * notification mechanism, so there's no point in handling these. */
default:
/* We don't handle these. */
@@ -193,10 +193,10 @@ int uv__signal_start(uv_signal_t* handle,
if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG))
return UV_EINVAL;
- /* Short circuit: if the signal watcher is already watching {signum} don't */
- /* go through the process of deregistering and registering the handler. */
- /* Additionally, this avoids pending signals getting lost in the (small) */
- /* time frame that handle->signum == 0. */
+ /* Short circuit: if the signal watcher is already watching {signum} don't go
+ * through the process of deregistering and registering the handler.
+ * Additionally, this avoids pending signals getting lost in the (small) time
+ * frame that handle->signum == 0. */
if (signum == handle->signum) {
handle->signal_cb = signal_cb;
return 0;
@@ -237,9 +237,9 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
(volatile LONG*) &handle->pending_signum, 0);
assert(dispatched_signum != 0);
- /* Check if the pending signal equals the signum that we are watching for. */
- /* These can get out of sync when the handler is stopped and restarted */
- /* while the signal_req is pending. */
+ /* Check if the pending signal equals the signum that we are watching for.
+ * These can get out of sync when the handler is stopped and restarted while
+ * the signal_req is pending. */
if (dispatched_signum == handle->signum)
handle->signal_cb(handle, dispatched_signum);
diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c
index 13cbfdcb9e..3273a03c1c 100644
--- a/deps/uv/src/win/stream.c
+++ b/deps/uv/src/win/stream.c
@@ -105,12 +105,10 @@ int uv_read_stop(uv_stream_t* handle) {
err = 0;
if (handle->type == UV_TTY) {
err = uv_tty_read_stop((uv_tty_t*) handle);
+ } else if (handle->type == UV_NAMED_PIPE) {
+ uv__pipe_read_stop((uv_pipe_t*) handle);
} else {
- if (handle->type == UV_NAMED_PIPE) {
- uv__pipe_stop_read((uv_pipe_t*) handle);
- } else {
- handle->flags &= ~UV_HANDLE_READING;
- }
+ handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(handle->loop, handle);
}
@@ -136,7 +134,8 @@ int uv_write(uv_write_t* req,
err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);
break;
case UV_NAMED_PIPE:
- err = uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, nbufs, cb);
+ err = uv__pipe_write(
+ loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb);
break;
case UV_TTY:
err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);
@@ -158,25 +157,18 @@ int uv_write2(uv_write_t* req,
uv_loop_t* loop = handle->loop;
int err;
- if (!(handle->flags & UV_HANDLE_WRITABLE)) {
- return UV_EPIPE;
+ if (send_handle == NULL) {
+ return uv_write(req, handle, bufs, nbufs, cb);
}
- err = ERROR_INVALID_PARAMETER;
- switch (handle->type) {
- case UV_NAMED_PIPE:
- err = uv_pipe_write2(loop,
- req,
- (uv_pipe_t*) handle,
- bufs,
- nbufs,
- send_handle,
- cb);
- break;
- default:
- assert(0);
+ if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) {
+ return UV_EINVAL;
+ } else if (!(handle->flags & UV_HANDLE_WRITABLE)) {
+ return UV_EPIPE;
}
+ err = uv__pipe_write(
+ loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb);
return uv_translate_sys_error(err);
}
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index 39c1ff0565..38cd73e0d1 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -99,8 +99,8 @@ static int uv_tcp_set_socket(uv_loop_t* loop,
if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0))
return GetLastError();
- /* Associate it with the I/O completion port. */
- /* Use uv_handle_t pointer as completion key. */
+ /* Associate it with the I/O completion port. Use uv_handle_t pointer as
+ * completion key. */
if (CreateIoCompletionPort((HANDLE)socket,
loop->iocp,
(ULONG_PTR)socket,
@@ -118,15 +118,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop,
non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;
}
- if (pSetFileCompletionNotificationModes &&
- !(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
- if (pSetFileCompletionNotificationModes((HANDLE) socket,
- FILE_SKIP_SET_EVENT_ON_HANDLE |
- FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
- handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
- } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
+ if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
+ UCHAR sfcnm_flags =
+ FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
+ if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags))
return GetLastError();
- }
+ handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
}
if (handle->flags & UV_HANDLE_TCP_NODELAY) {
@@ -326,9 +323,9 @@ static int uv_tcp_try_bind(uv_tcp_t* handle,
on = (flags & UV_TCP_IPV6ONLY) != 0;
- /* TODO: how to handle errors? This may fail if there is no ipv4 stack */
- /* available, or when run on XP/2003 which have no support for dualstack */
- /* sockets. For now we're silently ignoring the error. */
+ /* TODO: how to handle errors? This may fail if there is no ipv4 stack
+ * available, or when run on XP/2003 which have no support for dualstack
+ * sockets. For now we're silently ignoring the error. */
setsockopt(handle->socket,
IPPROTO_IPV6,
IPV6_V6ONLY,
@@ -626,9 +623,9 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
uv_tcp_queue_accept(handle, req);
}
- /* Initialize other unused requests too, because uv_tcp_endgame */
- /* doesn't know how how many requests were initialized, so it will */
- /* try to clean up {uv_simultaneous_server_accepts} requests. */
+ /* Initialize other unused requests too, because uv_tcp_endgame doesn't
+ * know how many requests were initialized, so it will try to clean up
+ * {uv_simultaneous_server_accepts} requests. */
for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
req = &handle->tcp.serv.accept_reqs[i];
UV_REQ_INIT(req, UV_ACCEPT);
@@ -721,8 +718,8 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
handle->alloc_cb = alloc_cb;
INCREASE_ACTIVE_COUNT(loop, handle);
- /* If reading was stopped and then started again, there could still be a */
- /* read request pending. */
+ /* If reading was stopped and then started again, there could still be a read
+ * request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING)) {
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
!handle->read_req.event_handle) {
@@ -965,8 +962,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
err = GET_REQ_SOCK_ERROR(req);
if (err == WSAECONNABORTED) {
- /*
- * Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
+ /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
*/
err = WSAECONNRESET;
}
@@ -1046,8 +1042,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
DECREASE_ACTIVE_COUNT(loop, handle);
if (err == WSAECONNABORTED) {
- /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */
- /* Unix. */
+ /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with
+ * Unix. */
err = WSAECONNRESET;
}
@@ -1119,10 +1115,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
assert(handle->type == UV_TCP);
- /* If handle->accepted_socket is not a valid socket, then */
- /* uv_queue_accept must have failed. This is a serious error. We stop */
- /* accepting connections and report this error to the connection */
- /* callback. */
+ /* If handle->accepted_socket is not a valid socket, then uv_queue_accept
+ * must have failed. This is a serious error. We stop accepting connections
+ * and report this error to the connection callback. */
if (req->accept_socket == INVALID_SOCKET) {
if (handle->flags & UV_HANDLE_LISTENING) {
handle->flags &= ~UV_HANDLE_LISTENING;
@@ -1147,9 +1142,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);
}
} else {
- /* Error related to accepted socket is ignored because the server */
- /* socket may still be healthy. If the server socket is broken */
- /* uv_queue_accept will detect it. */
+ /* Error related to accepted socket is ignored because the server socket
+ * may still be healthy. If the server socket is broken uv_queue_accept
+ * will detect it. */
closesocket(req->accept_socket);
req->accept_socket = INVALID_SOCKET;
if (handle->flags & UV_HANDLE_LISTENING) {
@@ -1194,13 +1189,46 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
}
-int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
- int tcp_connection) {
+int uv__tcp_xfer_export(uv_tcp_t* handle,
+ int target_pid,
+ uv__ipc_socket_xfer_info_t* xfer_info) {
+ if (!(handle->flags & UV_HANDLE_CONNECTION)) {
+ /* We're about to share the socket with another process. Because this is a
+ * listening socket, we assume that the other process will be accepting
+ * connections on it. Thus, before sharing the socket with another process,
+ * we call listen here in the parent process. */
+ if (!(handle->flags & UV_HANDLE_LISTENING)) {
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ return ERROR_NOT_SUPPORTED;
+ }
+ if (handle->delayed_error == 0 &&
+ listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
+ handle->delayed_error = WSAGetLastError();
+ }
+ }
+ }
+
+ if (WSADuplicateSocketW(
+ handle->socket, target_pid, &xfer_info->socket_info)) {
+ return WSAGetLastError();
+ }
+ xfer_info->delayed_error = handle->delayed_error;
+ xfer_info->flags = handle->flags & UV_HANDLE_CONNECTION;
+
+ /* Mark the local copy of the handle as 'shared' so we behave in a way that's
+ * friendly to the process(es) that we share the socket with. */
+ handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
+
+ return 0;
+}
+
+
+int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_info_t* xfer_info) {
int err;
SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
- &socket_info_ex->socket_info,
+ &xfer_info->socket_info,
0,
WSA_FLAG_OVERLAPPED);
@@ -1208,26 +1236,21 @@ int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
return WSAGetLastError();
}
- err = uv_tcp_set_socket(tcp->loop,
- tcp,
- socket,
- socket_info_ex->socket_info.iAddressFamily,
- 1);
+ err = uv_tcp_set_socket(
+ tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1);
if (err) {
closesocket(socket);
return err;
}
- if (tcp_connection) {
+ tcp->delayed_error = xfer_info->delayed_error;
+ tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET;
+
+ if (xfer_info->flags & UV_HANDLE_CONNECTION) {
uv_connection_init((uv_stream_t*)tcp);
tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
}
- tcp->flags |= UV_HANDLE_BOUND;
- tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
-
- tcp->delayed_error = socket_info_ex->delayed_error;
-
tcp->loop->active_tcp_streams++;
return 0;
}
@@ -1273,39 +1296,6 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
}
-int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
- LPWSAPROTOCOL_INFOW protocol_info) {
- if (!(handle->flags & UV_HANDLE_CONNECTION)) {
- /*
- * We're about to share the socket with another process. Because
- * this is a listening socket, we assume that the other process will
- * be accepting connections on it. So, before sharing the socket
- * with another process, we call listen here in the parent process.
- */
-
- if (!(handle->flags & UV_HANDLE_LISTENING)) {
- if (!(handle->flags & UV_HANDLE_BOUND)) {
- return ERROR_INVALID_PARAMETER;
- }
-
- if (!(handle->delayed_error)) {
- if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
- handle->delayed_error = WSAGetLastError();
- }
- }
- }
- }
-
- if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) {
- return WSAGetLastError();
- }
-
- handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
-
- return 0;
-}
-
-
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
if (handle->flags & UV_HANDLE_CONNECTION) {
return UV_EINVAL;
@@ -1346,8 +1336,8 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
uv_tcp_non_ifs_lsp_ipv4;
- /* If there are non-ifs LSPs then try to obtain a base handle for the */
- /* socket. This will always fail on Windows XP/3k. */
+ /* If there are non-ifs LSPs then try to obtain a base handle for the socket.
+ * This will always fail on Windows XP/3k. */
if (non_ifs_lsp) {
DWORD bytes;
if (WSAIoctl(socket,
@@ -1379,38 +1369,37 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
int close_socket = 1;
if (tcp->flags & UV_HANDLE_READ_PENDING) {
- /* In order for winsock to do a graceful close there must not be any */
- /* any pending reads, or the socket must be shut down for writing */
+ /* In order for winsock to do a graceful close there must not be any any
+ * pending reads, or the socket must be shut down for writing */
if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) {
/* Just do shutdown on non-shared sockets, which ensures graceful close. */
shutdown(tcp->socket, SD_SEND);
} else if (uv_tcp_try_cancel_io(tcp) == 0) {
- /* In case of a shared socket, we try to cancel all outstanding I/O, */
- /* If that works, don't close the socket yet - wait for the read req to */
- /* return and close the socket in uv_tcp_endgame. */
+ /* In case of a shared socket, we try to cancel all outstanding I/O,. If
+ * that works, don't close the socket yet - wait for the read req to
+ * return and close the socket in uv_tcp_endgame. */
close_socket = 0;
} else {
- /* When cancelling isn't possible - which could happen when an LSP is */
- /* present on an old Windows version, we will have to close the socket */
- /* with a read pending. That is not nice because trailing sent bytes */
- /* may not make it to the other side. */
+ /* When cancelling isn't possible - which could happen when an LSP is
+ * present on an old Windows version, we will have to close the socket
+ * with a read pending. That is not nice because trailing sent bytes may
+ * not make it to the other side. */
}
} else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
tcp->tcp.serv.accept_reqs != NULL) {
- /* Under normal circumstances closesocket() will ensure that all pending */
- /* accept reqs are canceled. However, when the socket is shared the */
- /* presence of another reference to the socket in another process will */
- /* keep the accept reqs going, so we have to ensure that these are */
- /* canceled. */
+ /* Under normal circumstances closesocket() will ensure that all pending
+ * accept reqs are canceled. However, when the socket is shared the
+ * presence of another reference to the socket in another process will keep
+ * the accept reqs going, so we have to ensure that these are canceled. */
if (uv_tcp_try_cancel_io(tcp) != 0) {
- /* When cancellation is not possible, there is another option: we can */
- /* close the incoming sockets, which will also cancel the accept */
- /* operations. However this is not cool because we might inadvertently */
- /* close a socket that just accepted a new connection, which will */
- /* cause the connection to be aborted. */
+ /* When cancellation is not possible, there is another option: we can
+ * close the incoming sockets, which will also cancel the accept
+ * operations. However this is not cool because we might inadvertently
+ * close a socket that just accepted a new connection, which will cause
+ * the connection to be aborted. */
unsigned int i;
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];
diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c
index 9eaad77cd0..3342fd7594 100644
--- a/deps/uv/src/win/thread.c
+++ b/deps/uv/src/win/thread.c
@@ -26,17 +26,6 @@
#include "uv.h"
#include "internal.h"
-
-#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL)
-
-static int uv_cond_fallback_init(uv_cond_t* cond);
-static void uv_cond_fallback_destroy(uv_cond_t* cond);
-static void uv_cond_fallback_signal(uv_cond_t* cond);
-static void uv_cond_fallback_broadcast(uv_cond_t* cond);
-static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex);
-static int uv_cond_fallback_timedwait(uv_cond_t* cond,
- uv_mutex_t* mutex, uint64_t timeout);
-
static int uv_cond_condvar_init(uv_cond_t* cond);
static void uv_cond_condvar_destroy(uv_cond_t* cond);
static void uv_cond_condvar_signal(uv_cond_t* cond);
@@ -69,8 +58,8 @@ static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
guard->ran = 1;
} else {
- /* We lost the race. Destroy the event we created and wait for the */
- /* existing one to become signaled. */
+ /* We lost the race. Destroy the event we created and wait for the existing
+ * one to become signaled. */
CloseHandle(created_event);
result = WaitForSingleObject(existing_event, INFINITE);
assert(result == WAIT_OBJECT_0);
@@ -377,220 +366,35 @@ int uv_sem_trywait(uv_sem_t* sem) {
}
-/* This condition variable implementation is based on the SetEvent solution
- * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
- * We could not use the SignalObjectAndWait solution (section 3.4) because
- * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
- * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
- */
-
-static int uv_cond_fallback_init(uv_cond_t* cond) {
- int err;
-
- /* Initialize the count to 0. */
- cond->fallback.waiters_count = 0;
-
- InitializeCriticalSection(&cond->fallback.waiters_count_lock);
-
- /* Create an auto-reset event. */
- cond->fallback.signal_event = CreateEvent(NULL, /* no security */
- FALSE, /* auto-reset event */
- FALSE, /* non-signaled initially */
- NULL); /* unnamed */
- if (!cond->fallback.signal_event) {
- err = GetLastError();
- goto error2;
- }
-
- /* Create a manual-reset event. */
- cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */
- TRUE, /* manual-reset */
- FALSE, /* non-signaled */
- NULL); /* unnamed */
- if (!cond->fallback.broadcast_event) {
- err = GetLastError();
- goto error;
- }
-
- return 0;
-
-error:
- CloseHandle(cond->fallback.signal_event);
-error2:
- DeleteCriticalSection(&cond->fallback.waiters_count_lock);
- return uv_translate_sys_error(err);
-}
-
-
-static int uv_cond_condvar_init(uv_cond_t* cond) {
- pInitializeConditionVariable(&cond->cond_var);
- return 0;
-}
-
-
int uv_cond_init(uv_cond_t* cond) {
- uv__once_init();
-
- if (HAVE_CONDVAR_API())
- return uv_cond_condvar_init(cond);
- else
- return uv_cond_fallback_init(cond);
-}
-
-
-static void uv_cond_fallback_destroy(uv_cond_t* cond) {
- if (!CloseHandle(cond->fallback.broadcast_event))
- abort();
- if (!CloseHandle(cond->fallback.signal_event))
- abort();
- DeleteCriticalSection(&cond->fallback.waiters_count_lock);
-}
-
-
-static void uv_cond_condvar_destroy(uv_cond_t* cond) {
- /* nothing to do */
+ InitializeConditionVariable(&cond->cond_var);
+ return 0;
}
void uv_cond_destroy(uv_cond_t* cond) {
- if (HAVE_CONDVAR_API())
- uv_cond_condvar_destroy(cond);
- else
- uv_cond_fallback_destroy(cond);
-}
-
-
-static void uv_cond_fallback_signal(uv_cond_t* cond) {
- int have_waiters;
-
- /* Avoid race conditions. */
- EnterCriticalSection(&cond->fallback.waiters_count_lock);
- have_waiters = cond->fallback.waiters_count > 0;
- LeaveCriticalSection(&cond->fallback.waiters_count_lock);
-
- if (have_waiters)
- SetEvent(cond->fallback.signal_event);
-}
-
-
-static void uv_cond_condvar_signal(uv_cond_t* cond) {
- pWakeConditionVariable(&cond->cond_var);
+ /* nothing to do */
+ UV__UNUSED(cond);
}
void uv_cond_signal(uv_cond_t* cond) {
- if (HAVE_CONDVAR_API())
- uv_cond_condvar_signal(cond);
- else
- uv_cond_fallback_signal(cond);
-}
-
-
-static void uv_cond_fallback_broadcast(uv_cond_t* cond) {
- int have_waiters;
-
- /* Avoid race conditions. */
- EnterCriticalSection(&cond->fallback.waiters_count_lock);
- have_waiters = cond->fallback.waiters_count > 0;
- LeaveCriticalSection(&cond->fallback.waiters_count_lock);
-
- if (have_waiters)
- SetEvent(cond->fallback.broadcast_event);
-}
-
-
-static void uv_cond_condvar_broadcast(uv_cond_t* cond) {
- pWakeAllConditionVariable(&cond->cond_var);
+ WakeConditionVariable(&cond->cond_var);
}
void uv_cond_broadcast(uv_cond_t* cond) {
- if (HAVE_CONDVAR_API())
- uv_cond_condvar_broadcast(cond);
- else
- uv_cond_fallback_broadcast(cond);
-}
-
-
-static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex,
- DWORD dwMilliseconds) {
- DWORD result;
- int last_waiter;
- HANDLE handles[2] = {
- cond->fallback.signal_event,
- cond->fallback.broadcast_event
- };
-
- /* Avoid race conditions. */
- EnterCriticalSection(&cond->fallback.waiters_count_lock);
- cond->fallback.waiters_count++;
- LeaveCriticalSection(&cond->fallback.waiters_count_lock);
-
- /* It's ok to release the <mutex> here since Win32 manual-reset events */
- /* maintain state when used with <SetEvent>. This avoids the "lost wakeup" */
- /* bug. */
- uv_mutex_unlock(mutex);
-
- /* Wait for either event to become signaled due to <uv_cond_signal> being */
- /* called or <uv_cond_broadcast> being called. */
- result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);
-
- EnterCriticalSection(&cond->fallback.waiters_count_lock);
- cond->fallback.waiters_count--;
- last_waiter = result == WAIT_OBJECT_0 + 1
- && cond->fallback.waiters_count == 0;
- LeaveCriticalSection(&cond->fallback.waiters_count_lock);
-
- /* Some thread called <pthread_cond_broadcast>. */
- if (last_waiter) {
- /* We're the last waiter to be notified or to stop waiting, so reset the */
- /* the manual-reset event. */
- ResetEvent(cond->fallback.broadcast_event);
- }
-
- /* Reacquire the <mutex>. */
- uv_mutex_lock(mutex);
-
- if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1)
- return 0;
-
- if (result == WAIT_TIMEOUT)
- return UV_ETIMEDOUT;
-
- abort();
- return -1; /* Satisfy the compiler. */
-}
-
-
-static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
- if (uv_cond_wait_helper(cond, mutex, INFINITE))
- abort();
-}
-
-
-static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
- if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
- abort();
+ WakeAllConditionVariable(&cond->cond_var);
}
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
- if (HAVE_CONDVAR_API())
- uv_cond_condvar_wait(cond, mutex);
- else
- uv_cond_fallback_wait(cond, mutex);
-}
-
-
-static int uv_cond_fallback_timedwait(uv_cond_t* cond,
- uv_mutex_t* mutex, uint64_t timeout) {
- return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6));
+ if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
+ abort();
}
-
-static int uv_cond_condvar_timedwait(uv_cond_t* cond,
- uv_mutex_t* mutex, uint64_t timeout) {
- if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
+int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
+ if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
return 0;
if (GetLastError() != ERROR_TIMEOUT)
abort();
@@ -598,15 +402,6 @@ static int uv_cond_condvar_timedwait(uv_cond_t* cond,
}
-int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
- uint64_t timeout) {
- if (HAVE_CONDVAR_API())
- return uv_cond_condvar_timedwait(cond, mutex, timeout);
- else
- return uv_cond_fallback_timedwait(cond, mutex, timeout);
-}
-
-
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
int err;
diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c
index 7e006fedfa..eda5c24f6e 100644
--- a/deps/uv/src/win/timer.c
+++ b/deps/uv/src/win/timer.c
@@ -24,7 +24,7 @@
#include "uv.h"
#include "internal.h"
-#include "tree.h"
+#include "uv/tree.h"
#include "handle-inl.h"
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index ecf7bc9b5b..ab4a648b2e 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -25,7 +25,7 @@
#include <stdlib.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "stdint-msvc2008.h"
+# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
@@ -205,8 +205,8 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
return uv_translate_sys_error(GetLastError());
}
- /* Obtain the the tty_output_lock because the virtual window state is */
- /* shared between all uv_tty_t handles. */
+ /* Obtain the tty_output_lock because the virtual window state is shared
+ * between all uv_tty_t handles. */
uv_sem_wait(&uv_tty_output_lock);
if (uv__vterm_state == UV_UNCHECKED)
@@ -484,8 +484,8 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
bytes = MAX_INPUT_BUFFER_LENGTH;
}
- /* At last, unicode! */
- /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */
+ /* At last, unicode! One utf-16 codeunit never takes more than 3 utf-8
+ * codeunits to encode. */
chars = bytes / 3;
status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS);
@@ -620,10 +620,10 @@ static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl,
}
switch (code) {
- /* These mappings are the same as Cygwin's. Unmodified and alt-modified */
- /* keypad keys comply with linux console, modifiers comply with xterm */
- /* modifier usage. F1..f12 and shift-f1..f10 comply with linux console, */
- /* f6..f12 with and without modifiers comply with rxvt. */
+ /* These mappings are the same as Cygwin's. Unmodified and alt-modified
+ * keypad keys comply with linux console, modifiers comply with xterm
+ * modifier usage. F1. f12 and shift-f1. f10 comply with linux console, f6.
+ * f12 with and without modifiers comply with rxvt. */
VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~")
VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~")
VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B")
@@ -706,8 +706,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
goto out;
}
- /* Windows sends a lot of events that we're not interested in, so buf */
- /* will be allocated on demand, when there's actually something to emit. */
+ /* Windows sends a lot of events that we're not interested in, so buf will be
+ * allocated on demand, when there's actually something to emit. */
buf = uv_null_buf_;
buf_used = 0;
@@ -733,16 +733,16 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
continue;
}
- /* Ignore keyup events, unless the left alt key was held and a valid */
- /* unicode character was emitted. */
+ /* Ignore keyup events, unless the left alt key was held and a valid
+ * unicode character was emitted. */
if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) ||
KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) {
continue;
}
- /* Ignore keypresses to numpad number keys if the left alt is held */
- /* because the user is composing a character, or windows simulating */
- /* this. */
+ /* Ignore keypresses to numpad number keys if the left alt is held
+ * because the user is composing a character, or windows simulating this.
+ */
if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) &&
!(KEV.dwControlKeyState & ENHANCED_KEY) &&
(KEV.wVirtualKeyCode == VK_INSERT ||
@@ -779,8 +779,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
continue;
}
- /* Prefix with \u033 if alt was held, but alt was not used as part */
- /* a compose sequence. */
+ /* Prefix with \u033 if alt was held, but alt was not used as part a
+ * compose sequence. */
if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
&& !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED |
RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) {
@@ -818,8 +818,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
/* Whatever happened, the last character wasn't a high surrogate. */
handle->tty.rd.last_utf16_high_surrogate = 0;
- /* If the utf16 character(s) couldn't be converted something must */
- /* be wrong. */
+ /* If the utf16 character(s) couldn't be converted something must be
+ * wrong. */
if (!char_len) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
@@ -950,8 +950,7 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
} else {
if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) {
- /* Read successful */
- /* TODO: read unicode, convert to utf-8 */
+ /* Read successful. TODO: read unicode, convert to utf-8 */
DWORD bytes = req->u.io.overlapped.InternalHigh;
handle->read_cb((uv_stream_t*) handle, bytes, &buf);
} else {
@@ -975,9 +974,9 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
assert(handle->type == UV_TTY);
assert(handle->flags & UV_HANDLE_TTY_READABLE);
- /* If the read_line_buffer member is zero, it must have been an raw read. */
- /* Otherwise it was a line-buffered read. */
- /* FIXME: This is quite obscure. Use a flag or something. */
+ /* If the read_line_buffer member is zero, it must have been an raw read.
+ * Otherwise it was a line-buffered read. FIXME: This is quite obscure. Use a
+ * flag or something. */
if (handle->tty.rd.read_line_buffer.len == 0) {
uv_process_tty_read_raw_req(loop, handle, req);
} else {
@@ -999,14 +998,14 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
handle->read_cb = read_cb;
handle->alloc_cb = alloc_cb;
- /* If reading was stopped and then started again, there could still be a */
- /* read request pending. */
+ /* If reading was stopped and then started again, there could still be a read
+ * request pending. */
if (handle->flags & UV_HANDLE_READ_PENDING) {
return 0;
}
- /* Maybe the user stopped reading half-way while processing key events. */
- /* Short-circuit if this could be the case. */
+ /* Maybe the user stopped reading half-way while processing key events.
+ * Short-circuit if this could be the case. */
if (handle->tty.rd.last_key_len > 0) {
SET_REQ_SUCCESS(&handle->read_req);
uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
@@ -1033,8 +1032,8 @@ int uv_tty_read_stop(uv_tty_t* handle) {
return 0;
if (handle->flags & UV_HANDLE_TTY_RAW) {
- /* Cancel raw read */
- /* Write some bullshit event to force the console wait to return. */
+ /* Cancel raw read. Write some bullshit event to force the console wait to
+ * return. */
memset(&record, 0, sizeof record);
if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {
return GetLastError();
@@ -1116,8 +1115,8 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
uv_tty_virtual_offset = info->dwCursorPosition.Y;
} else if (uv_tty_virtual_offset < info->dwCursorPosition.Y -
uv_tty_virtual_height + 1) {
- /* If suddenly find the cursor outside of the virtual window, it must */
- /* have somehow scrolled. Update the virtual window offset. */
+ /* If suddenly find the cursor outside of the virtual window, it must have
+ * somehow scrolled. Update the virtual window offset. */
uv_tty_virtual_offset = info->dwCursorPosition.Y -
uv_tty_virtual_height + 1;
}
@@ -1304,8 +1303,8 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
x2 = 0;
x2r = 1;
} else {
- /* Clear to end of row. We pretend the console is 65536 characters wide, */
- /* uv_tty_make_real_coord will clip it to the actual console width. */
+ /* Clear to end of row. We pretend the console is 65536 characters wide,
+ * uv_tty_make_real_coord will clip it to the actual console width. */
x2 = 0xffff;
x2r = 0;
}
@@ -1613,8 +1612,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
DWORD* error) {
- /* We can only write 8k characters at a time. Windows can't handle */
- /* much more characters in a single console write anyway. */
+ /* We can only write 8k characters at a time. Windows can't handle much more
+ * characters in a single console write anyway. */
WCHAR utf16_buf[MAX_CONSOLE_CHAR];
WCHAR* utf16_buffer;
DWORD utf16_buf_used = 0;
@@ -1650,9 +1649,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
unsigned char previous_eol = handle->tty.wr.previous_eol;
unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state;
- /* Store the error here. If we encounter an error, stop trying to do i/o */
- /* but keep parsing the buffer so we leave the parser in a consistent */
- /* state. */
+ /* Store the error here. If we encounter an error, stop trying to do i/o but
+ * keep parsing the buffer so we leave the parser in a consistent state. */
*error = ERROR_SUCCESS;
utf16_buffer = utf16_buf;
@@ -1700,9 +1698,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
for (j = 0; j < buf.len; j++) {
unsigned char c = buf.base[j];
- /* Run the character through the utf8 decoder We happily accept non */
- /* shortest form encodings and invalid code points - there's no real */
- /* harm that can be done. */
+ /* Run the character through the utf8 decoder We happily accept non
+ * shortest form encodings and invalid code points - there's no real harm
+ * that can be done. */
if (utf8_bytes_left == 0) {
/* Read utf-8 start byte */
DWORD first_zero_bit;
@@ -1742,8 +1740,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
/* Start byte where continuation was expected. */
utf8_bytes_left = 0;
utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
- /* Patch buf offset so this character will be parsed again as a */
- /* start byte. */
+ /* Patch buf offset so this character will be parsed again as a start
+ * byte. */
j--;
}
@@ -1776,8 +1774,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
case '_':
case 'P':
case ']':
- /* Not supported, but we'll have to parse until we see a stop */
- /* code, e.g. ESC \ or BEL. */
+ /* Not supported, but we'll have to parse until we see a stop code,
+ * e. g. ESC \ or BEL. */
ansi_parser_state = ANSI_ST_CONTROL;
continue;
@@ -1859,8 +1857,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
continue;
} else {
- /* If ANSI_IN_ARG is not set, add another argument and */
- /* default it to 0. */
+ /* If ANSI_IN_ARG is not set, add another argument and default it
+ * to 0. */
+
/* Check for too many arguments */
if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {
ansi_parser_state |= ANSI_IGNORE;
@@ -1874,9 +1873,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
} else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) &&
handle->tty.wr.ansi_csi_argc == 0) {
- /* Ignores '?' if it is the first character after CSI[ */
- /* This is an extension character from the VT100 codeset */
- /* that is supported and used by most ANSI terminals today. */
+ /* Ignores '?' if it is the first character after CSI[. This is an
+ * extension character from the VT100 codeset that is supported and
+ * used by most ANSI terminals today. */
continue;
} else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' &&
@@ -2006,8 +2005,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
continue;
} else {
- /* We don't support commands that use private mode characters or */
- /* intermediaries. Ignore the rest of the sequence. */
+ /* We don't support commands that use private mode characters or
+ * intermediaries. Ignore the rest of the sequence. */
ansi_parser_state |= ANSI_IGNORE;
continue;
}
@@ -2020,8 +2019,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
}
} else if (ansi_parser_state & ANSI_ST_CONTROL) {
- /* Unsupported control code */
- /* Ignore everything until we see BEL or ESC \ */
+ /* Unsupported control code.
+ * Ignore everything until we see `BEL` or `ESC \`. */
if (ansi_parser_state & ANSI_IN_STRING) {
if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) {
if (utf8_codepoint == '"') {
@@ -2055,9 +2054,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
abort();
}
- /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */
- /* windows console doesn't really support UTF-16, so just emit the */
- /* replacement character. */
+ /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the windows
+ * console doesn't really support UTF-16, so just emit the replacement
+ * character. */
if (utf8_codepoint > 0xffff) {
utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
}
@@ -2071,10 +2070,10 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
utf16_buf[utf16_buf_used++] = L'\r';
utf16_buf[utf16_buf_used++] = L'\n';
} else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) {
- /* \n was followed by \r; do not print the \r, since */
- /* the source was either \r\n\r (so the second \r is */
- /* redundant) or was \n\r (so the \n was processed */
- /* by the last case and an \r automatically inserted). */
+ /* \n was followed by \r; do not print the \r, since the source was
+ * either \r\n\r (so the second \r is redundant) or was \n\r (so the
+ * \n was processed by the last case and an \r automatically
+ * inserted). */
} else {
/* \r without \n; print \r as-is. */
ENSURE_BUFFER_SPACE(1);
@@ -2224,8 +2223,8 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
if (handle->flags & UV__HANDLE_CLOSING &&
handle->reqs_pending == 0) {
- /* The wait handle used for raw reading should be unregistered when the */
- /* wait callback runs. */
+ /* The wait handle used for raw reading should be unregistered when the
+ * wait callback runs. */
assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
handle->tty.rd.read_raw_wait == NULL);
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index cd1d0e07b2..e56282ae44 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -74,8 +74,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
return GetLastError();
}
- /* Associate it with the I/O completion port. */
- /* Use uv_handle_t pointer as completion key. */
+ /* Associate it with the I/O completion port. Use uv_handle_t pointer as
+ * completion key. */
if (CreateIoCompletionPort((HANDLE)socket,
loop->iocp,
(ULONG_PTR)socket,
@@ -83,31 +83,28 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
return GetLastError();
}
- if (pSetFileCompletionNotificationModes) {
- /* All known Windows that support SetFileCompletionNotificationModes */
- /* have a bug that makes it impossible to use this function in */
- /* conjunction with datagram sockets. We can work around that but only */
- /* if the user is using the default UDP driver (AFD) and has no other */
- /* LSPs stacked on top. Here we check whether that is the case. */
- opt_len = (int) sizeof info;
- if (getsockopt(socket,
- SOL_SOCKET,
- SO_PROTOCOL_INFOW,
- (char*) &info,
- &opt_len) == SOCKET_ERROR) {
- return GetLastError();
- }
+ /* All known Windows that support SetFileCompletionNotificationModes have a
+ * bug that makes it impossible to use this function in conjunction with
+ * datagram sockets. We can work around that but only if the user is using
+ * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here
+ * we check whether that is the case. */
+ opt_len = (int) sizeof info;
+ if (getsockopt(
+ socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) ==
+ SOCKET_ERROR) {
+ return GetLastError();
+ }
- if (info.ProtocolChain.ChainLen == 1) {
- if (pSetFileCompletionNotificationModes((HANDLE)socket,
- FILE_SKIP_SET_EVENT_ON_HANDLE |
- FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
- handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
- handle->func_wsarecv = uv_wsarecv_workaround;
- handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
- } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
- return GetLastError();
- }
+ if (info.ProtocolChain.ChainLen == 1) {
+ if (SetFileCompletionNotificationModes(
+ (HANDLE) socket,
+ FILE_SKIP_SET_EVENT_ON_HANDLE |
+ FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
+ handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
+ handle->func_wsarecv = uv_wsarecv_workaround;
+ handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
+ } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
+ return GetLastError();
}
}
@@ -245,12 +242,12 @@ static int uv_udp_maybe_bind(uv_udp_t* handle,
handle->flags |= UV_HANDLE_IPV6;
if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
- /* On windows IPV6ONLY is on by default. */
- /* If the user doesn't specify it libuv turns it off. */
+ /* On windows IPV6ONLY is on by default. If the user doesn't specify it
+ * libuv turns it off. */
- /* TODO: how to handle errors? This may fail if there is no ipv4 stack */
- /* available, or when run on XP/2003 which have no support for dualstack */
- /* sockets. For now we're silently ignoring the error. */
+ /* TODO: how to handle errors? This may fail if there is no ipv4 stack
+ * available, or when run on XP/2003 which have no support for dualstack
+ * sockets. For now we're silently ignoring the error. */
setsockopt(handle->socket,
IPPROTO_IPV6,
IPV6_V6ONLY,
@@ -386,8 +383,8 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
handle->recv_cb = recv_cb;
handle->alloc_cb = alloc_cb;
- /* If reading was stopped and then started again, there could still be a */
- /* recv request pending. */
+ /* If reading was stopped and then started again, there could still be a recv
+ * request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING))
uv_udp_queue_recv(loop, handle);
@@ -467,19 +464,19 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
if (!REQ_SUCCESS(req)) {
DWORD err = GET_REQ_SOCK_ERROR(req);
if (err == WSAEMSGSIZE) {
- /* Not a real error, it just indicates that the received packet */
- /* was bigger than the receive buffer. */
+ /* Not a real error, it just indicates that the received packet was
+ * bigger than the receive buffer. */
} else if (err == WSAECONNRESET || err == WSAENETRESET) {
- /* A previous sendto operation failed; ignore this error. If */
- /* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */
- /* MSG_PEEK flag to clear out the error queue. For nonzero reads, */
- /* immediately queue a new receive. */
+ /* A previous sendto operation failed; ignore this error. If zero-reading
+ * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to
+ * clear out the error queue. For nonzero reads, immediately queue a new
+ * receive. */
if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
goto done;
}
} else {
- /* A real error occurred. Report the error to the user only if we're */
- /* currently reading. */
+ /* A real error occurred. Report the error to the user only if we're
+ * currently reading. */
if (handle->flags & UV_HANDLE_READING) {
uv_udp_recv_stop(handle);
buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
@@ -503,8 +500,8 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
struct sockaddr_storage from;
int from_len;
- /* Do a nonblocking receive */
- /* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
+ /* Do a nonblocking receive.
+ * TODO: try to read multiple datagrams at once. FIONREAD maybe? */
buf = uv_buf_init(NULL, 0);
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
if (buf.base == NULL || buf.len == 0) {
@@ -741,7 +738,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
return UV_EINVAL;
}
- if (!(handle->flags & UV_HANDLE_BOUND))
+ if (handle->socket == INVALID_SOCKET)
return UV_EBADF;
if (addr_st.ss_family == AF_INET) {
@@ -772,7 +769,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
BOOL optval = (BOOL) value;
- if (!(handle->flags & UV_HANDLE_BOUND))
+ if (handle->socket == INVALID_SOCKET)
return UV_EBADF;
if (setsockopt(handle->socket,
@@ -818,7 +815,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
return UV_EINVAL; \
} \
\
- if (!(handle->flags & UV_HANDLE_BOUND)) \
+ if (handle->socket == INVALID_SOCKET) \
return UV_EBADF; \
\
if (!(handle->flags & UV_HANDLE_IPV6)) { \
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index 49b5bc7206..3e86ff1504 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -74,10 +74,6 @@
static char *process_title;
static CRITICAL_SECTION process_title_lock;
-/* Cached copy of the process id, written once. */
-static DWORD current_pid = 0;
-
-
/* Interval (in seconds) of the high-resolution clock. */
static double hrtime_interval_ = 0;
@@ -149,8 +145,8 @@ int uv_exepath(char* buffer, size_t* size_ptr) {
uv__free(utf16_buffer);
- /* utf8_len *does* include the terminating null at this point, but the */
- /* returned size shouldn't. */
+ /* utf8_len *does* include the terminating null at this point, but the
+ * returned size shouldn't. */
*size_ptr = utf8_len - 1;
return 0;
@@ -173,16 +169,16 @@ int uv_cwd(char* buffer, size_t* size) {
if (utf16_len == 0) {
return uv_translate_sys_error(GetLastError());
} else if (utf16_len > MAX_PATH) {
- /* This should be impossible; however the CRT has a code path to deal */
- /* with this scenario, so I added a check anyway. */
+ /* This should be impossible; however the CRT has a code path to deal with
+ * this scenario, so I added a check anyway. */
return UV_EIO;
}
/* utf16_len contains the length, *not* including the terminating null. */
utf16_buffer[utf16_len] = L'\0';
- /* The returned directory should not have a trailing slash, unless it */
- /* points at a drive root, like c:\. Remove it if needed.*/
+ /* The returned directory should not have a trailing slash, unless it points
+ * at a drive root, like c:\. Remove it if needed. */
if (utf16_buffer[utf16_len - 1] == L'\\' &&
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
utf16_len--;
@@ -239,9 +235,9 @@ int uv_chdir(const char* dir) {
utf16_buffer,
MAX_PATH) == 0) {
DWORD error = GetLastError();
- /* The maximum length of the current working directory is 260 chars, */
- /* including terminating null. If it doesn't fit, the path name must be */
- /* too long. */
+ /* The maximum length of the current working directory is 260 chars,
+ * including terminating null. If it doesn't fit, the path name must be too
+ * long. */
if (error == ERROR_INSUFFICIENT_BUFFER) {
return UV_ENAMETOOLONG;
} else {
@@ -253,9 +249,9 @@ int uv_chdir(const char* dir) {
return uv_translate_sys_error(GetLastError());
}
- /* Windows stores the drive-local path in an "hidden" environment variable, */
- /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */
- /* update this, so we'll have to do it. */
+ /* Windows stores the drive-local path in an "hidden" environment variable,
+ * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update
+ * this, so we'll have to do it. */
utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
if (utf16_len == 0) {
return uv_translate_sys_error(GetLastError());
@@ -263,8 +259,8 @@ int uv_chdir(const char* dir) {
return UV_EIO;
}
- /* The returned directory should not have a trailing slash, unless it */
- /* points at a drive root, like c:\. Remove it if needed. */
+ /* The returned directory should not have a trailing slash, unless it points
+ * at a drive root, like c:\. Remove it if needed. */
if (utf16_buffer[utf16_len - 1] == L'\\' &&
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
utf16_len--;
@@ -272,8 +268,8 @@ int uv_chdir(const char* dir) {
}
if (utf16_len < 2 || utf16_buffer[1] != L':') {
- /* Doesn't look like a drive letter could be there - probably an UNC */
- /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */
+ /* Doesn't look like a drive letter could be there - probably an UNC path.
+ * TODO: Need to handle win32 namespaces like \\?\C:\ ? */
drive_letter = 0;
} else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
drive_letter = utf16_buffer[0];
@@ -359,14 +355,6 @@ uv_pid_t uv_os_getppid(void) {
}
-int uv_current_pid(void) {
- if (current_pid == 0) {
- current_pid = GetCurrentProcessId();
- }
- return current_pid;
-}
-
-
char** uv_setup_args(int argc, char** argv) {
return argv;
}
@@ -842,17 +830,17 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
}
- /* Fetch the size of the adapters reported by windows, and then get the */
- /* list itself. */
+ /* Fetch the size of the adapters reported by windows, and then get the list
+ * itself. */
win_address_buf_size = 0;
win_address_buf = NULL;
for (;;) {
ULONG r;
- /* If win_address_buf is 0, then GetAdaptersAddresses will fail with */
- /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */
- /* win_address_buf_size. */
+ /* If win_address_buf is 0, then GetAdaptersAddresses will fail with.
+ * ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in
+ * win_address_buf_size. */
r = GetAdaptersAddresses(AF_UNSPEC,
flags,
NULL,
@@ -866,8 +854,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
switch (r) {
case ERROR_BUFFER_OVERFLOW:
- /* This happens when win_address_buf is NULL or too small to hold */
- /* all adapters. */
+ /* This happens when win_address_buf is NULL or too small to hold all
+ * adapters. */
win_address_buf = uv__malloc(win_address_buf_size);
if (win_address_buf == NULL)
return UV_ENOMEM;
@@ -901,15 +889,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
return UV_ENOBUFS;
default:
- /* Other (unspecified) errors can happen, but we don't have any */
- /* special meaning for them. */
+ /* Other (unspecified) errors can happen, but we don't have any special
+ * meaning for them. */
assert(r != ERROR_SUCCESS);
return uv_translate_sys_error(r);
}
}
- /* Count the number of enabled interfaces and compute how much space is */
- /* needed to store their info. */
+ /* Count the number of enabled interfaces and compute how much space is
+ * needed to store their info. */
count = 0;
uv_address_buf_size = 0;
@@ -919,9 +907,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
int name_size;
- /* Interfaces that are not 'up' should not be reported. Also skip */
- /* interfaces that have no associated unicast address, as to avoid */
- /* allocating space for the name for this interface. */
+ /* Interfaces that are not 'up' should not be reported. Also skip
+ * interfaces that have no associated unicast address, as to avoid
+ * allocating space for the name for this interface. */
if (adapter->OperStatus != IfOperStatusUp ||
adapter->FirstUnicastAddress == NULL)
continue;
@@ -941,8 +929,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
}
uv_address_buf_size += name_size;
- /* Count the number of addresses associated with this interface, and */
- /* compute the size. */
+ /* Count the number of addresses associated with this interface, and
+ * compute the size. */
for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
adapter->FirstUnicastAddress;
unicast_address != NULL;
@@ -959,8 +947,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
return UV_ENOMEM;
}
- /* Compute the start of the uv_interface_address_t array, and the place in */
- /* the buffer where the interface names will be stored. */
+ /* Compute the start of the uv_interface_address_t array, and the place in
+ * the buffer where the interface names will be stored. */
uv_address = uv_address_buf;
name_buf = (char*) (uv_address_buf + count);
@@ -1199,8 +1187,8 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
return UV_EIO;
}
- /* The returned directory should not have a trailing slash, unless it */
- /* points at a drive root, like c:\. Remove it if needed.*/
+ /* The returned directory should not have a trailing slash, unless it points
+ * at a drive root, like c:\. Remove it if needed. */
if (path[len - 1] == L'\\' &&
!(len == 3 && path[1] == L':')) {
len--;
diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c
index c330786142..0fd598eacb 100644
--- a/deps/uv/src/win/winapi.c
+++ b/deps/uv/src/win/winapi.c
@@ -34,37 +34,17 @@ sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
sNtQueryDirectoryFile pNtQueryDirectoryFile;
sNtQuerySystemInformation pNtQuerySystemInformation;
-
-/* Kernel32 function pointers */
-sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
-sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
-sCreateSymbolicLinkW pCreateSymbolicLinkW;
-sCancelIoEx pCancelIoEx;
-sInitializeConditionVariable pInitializeConditionVariable;
-sSleepConditionVariableCS pSleepConditionVariableCS;
-sSleepConditionVariableSRW pSleepConditionVariableSRW;
-sWakeAllConditionVariable pWakeAllConditionVariable;
-sWakeConditionVariable pWakeConditionVariable;
-sCancelSynchronousIo pCancelSynchronousIo;
-sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
-
-
/* Powrprof.dll function pointer */
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
/* User32.dll function pointer */
sSetWinEventHook pSetWinEventHook;
-/* iphlpapi.dll function pointer */
-sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid = NULL;
-sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW = NULL;
void uv_winapi_init(void) {
HMODULE ntdll_module;
- HMODULE kernel32_module;
HMODULE powrprof_module;
HMODULE user32_module;
- HMODULE iphlpapi_module;
ntdll_module = GetModuleHandleA("ntdll.dll");
if (ntdll_module == NULL) {
@@ -118,46 +98,6 @@ void uv_winapi_init(void) {
uv_fatal_error(GetLastError(), "GetProcAddress");
}
- kernel32_module = GetModuleHandleA("kernel32.dll");
- if (kernel32_module == NULL) {
- uv_fatal_error(GetLastError(), "GetModuleHandleA");
- }
-
- pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress(
- kernel32_module,
- "GetQueuedCompletionStatusEx");
-
- pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes)
- GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes");
-
- pCreateSymbolicLinkW = (sCreateSymbolicLinkW)
- GetProcAddress(kernel32_module, "CreateSymbolicLinkW");
-
- pCancelIoEx = (sCancelIoEx)
- GetProcAddress(kernel32_module, "CancelIoEx");
-
- pInitializeConditionVariable = (sInitializeConditionVariable)
- GetProcAddress(kernel32_module, "InitializeConditionVariable");
-
- pSleepConditionVariableCS = (sSleepConditionVariableCS)
- GetProcAddress(kernel32_module, "SleepConditionVariableCS");
-
- pSleepConditionVariableSRW = (sSleepConditionVariableSRW)
- GetProcAddress(kernel32_module, "SleepConditionVariableSRW");
-
- pWakeAllConditionVariable = (sWakeAllConditionVariable)
- GetProcAddress(kernel32_module, "WakeAllConditionVariable");
-
- pWakeConditionVariable = (sWakeConditionVariable)
- GetProcAddress(kernel32_module, "WakeConditionVariable");
-
- pCancelSynchronousIo = (sCancelSynchronousIo)
- GetProcAddress(kernel32_module, "CancelSynchronousIo");
-
- pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW)
- GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW");
-
-
powrprof_module = LoadLibraryA("powrprof.dll");
if (powrprof_module != NULL) {
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
@@ -170,11 +110,4 @@ void uv_winapi_init(void) {
GetProcAddress(user32_module, "SetWinEventHook");
}
- iphlpapi_module = LoadLibraryA("iphlpapi.dll");
- if (iphlpapi_module != NULL) {
- pConvertInterfaceIndexToLuid = (sConvertInterfaceIndexToLuid)
- GetProcAddress(iphlpapi_module, "ConvertInterfaceIndexToLuid");
- pConvertInterfaceLuidToNameW = (sConvertInterfaceLuidToNameW)
- GetProcAddress(iphlpapi_module, "ConvertInterfaceLuidToNameW");
- }
}
diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h
index 38570c2ffa..d0fcfd8e7a 100644
--- a/deps/uv/src/win/winapi.h
+++ b/deps/uv/src/win/winapi.h
@@ -4076,8 +4076,8 @@
# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L)
#endif
-/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the */
-/* DDK got it wrong! */
+/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the DDK
+ * got it wrong! */
#ifdef NTSTATUS_FROM_WIN32
# undef NTSTATUS_FROM_WIN32
#endif
@@ -4642,56 +4642,6 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
# define ERROR_MUI_FILE_NOT_LOADED 15105
#endif
-typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
- (HANDLE CompletionPort,
- LPOVERLAPPED_ENTRY lpCompletionPortEntries,
- ULONG ulCount,
- PULONG ulNumEntriesRemoved,
- DWORD dwMilliseconds,
- BOOL fAlertable);
-
-typedef BOOL (WINAPI* sSetFileCompletionNotificationModes)
- (HANDLE FileHandle,
- UCHAR Flags);
-
-typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW)
- (LPCWSTR lpSymlinkFileName,
- LPCWSTR lpTargetFileName,
- DWORD dwFlags);
-
-typedef BOOL (WINAPI* sCancelIoEx)
- (HANDLE hFile,
- LPOVERLAPPED lpOverlapped);
-
-typedef VOID (WINAPI* sInitializeConditionVariable)
- (PCONDITION_VARIABLE ConditionVariable);
-
-typedef BOOL (WINAPI* sSleepConditionVariableCS)
- (PCONDITION_VARIABLE ConditionVariable,
- PCRITICAL_SECTION CriticalSection,
- DWORD dwMilliseconds);
-
-typedef BOOL (WINAPI* sSleepConditionVariableSRW)
- (PCONDITION_VARIABLE ConditionVariable,
- PSRWLOCK SRWLock,
- DWORD dwMilliseconds,
- ULONG Flags);
-
-typedef VOID (WINAPI* sWakeAllConditionVariable)
- (PCONDITION_VARIABLE ConditionVariable);
-
-typedef VOID (WINAPI* sWakeConditionVariable)
- (PCONDITION_VARIABLE ConditionVariable);
-
-typedef BOOL (WINAPI* sCancelSynchronousIo)
- (HANDLE hThread);
-
-typedef DWORD (WINAPI* sGetFinalPathNameByHandleW)
- (HANDLE hFile,
- LPWSTR lpszFilePath,
- DWORD cchFilePath,
- DWORD dwFlags);
-
/* from powerbase.h */
#ifndef DEVICE_NOTIFY_CALLBACK
# define DEVICE_NOTIFY_CALLBACK 2
@@ -4754,40 +4704,10 @@ extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
extern sNtQuerySystemInformation pNtQuerySystemInformation;
-
-/* Kernel32 function pointers */
-extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
-extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
-extern sCreateSymbolicLinkW pCreateSymbolicLinkW;
-extern sCancelIoEx pCancelIoEx;
-extern sInitializeConditionVariable pInitializeConditionVariable;
-extern sSleepConditionVariableCS pSleepConditionVariableCS;
-extern sSleepConditionVariableSRW pSleepConditionVariableSRW;
-extern sWakeAllConditionVariable pWakeAllConditionVariable;
-extern sWakeConditionVariable pWakeConditionVariable;
-extern sCancelSynchronousIo pCancelSynchronousIo;
-extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
-
-
/* Powrprof.dll function pointer */
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
/* User32.dll function pointer */
extern sSetWinEventHook pSetWinEventHook;
-/* iphlpapi.dll function pointer */
-union _NET_LUID_LH;
-typedef DWORD (WINAPI *sConvertInterfaceIndexToLuid)(
- ULONG InterfaceIndex,
- union _NET_LUID_LH *InterfaceLuid);
-
-typedef DWORD (WINAPI *sConvertInterfaceLuidToNameW)(
- const union _NET_LUID_LH *InterfaceLuid,
- PWSTR InterfaceName,
- size_t Length);
-
-extern sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid;
-extern sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW;
-
-
#endif /* UV_WIN_WINAPI_H_ */
diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c
index 84188954d8..5e7da2a8f2 100644
--- a/deps/uv/src/win/winsock.c
+++ b/deps/uv/src/win/winsock.c
@@ -256,8 +256,8 @@ int uv_ntstatus_to_winsock_error(NTSTATUS status) {
default:
if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) &&
(status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) {
- /* It's a windows error that has been previously mapped to an */
- /* ntstatus code. */
+ /* It's a windows error that has been previously mapped to an ntstatus
+ * code. */
return (DWORD) (status & 0xffff);
} else {
/* The default fallback for unmappable ntstatus codes. */
@@ -519,8 +519,8 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
sizeof *info_out);
if (overlapped == NULL) {
- /* If this is a blocking operation, wait for the event to become */
- /* signaled, and then grab the real status from the io status block. */
+ /* If this is a blocking operation, wait for the event to become signaled,
+ * and then grab the real status from the io status block. */
if (status == STATUS_PENDING) {
DWORD r = WaitForSingleObject(event, INFINITE);
diff --git a/deps/uv/test/benchmark-async-pummel.c b/deps/uv/test/benchmark-async-pummel.c
index cca3de1062..119ae5eee5 100644
--- a/deps/uv/test/benchmark-async-pummel.c
+++ b/deps/uv/test/benchmark-async-pummel.c
@@ -41,7 +41,7 @@ static void async_cb(uv_async_t* handle) {
/* Tell the pummel thread to stop. */
ACCESS_ONCE(const char*, handle->data) = stop;
- /* Wait for for the pummel thread to acknowledge that it has stoppped. */
+ /* Wait for the pummel thread to acknowledge that it has stoppped. */
while (ACCESS_ONCE(const char*, handle->data) != stopped)
uv_sleep(0);
diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c
index da4ac82e43..9b8af04608 100644
--- a/deps/uv/test/run-tests.c
+++ b/deps/uv/test/run-tests.c
@@ -37,6 +37,7 @@
#include "test-list.h"
int ipc_helper(int listen_after_write);
+int ipc_helper_heavy_traffic_deadlock_bug(void);
int ipc_helper_tcp_connection(void);
int ipc_helper_closed_handle(void);
int ipc_send_recv_helper(void);
@@ -83,6 +84,10 @@ static int maybe_run_test(int argc, char **argv) {
return ipc_helper(1);
}
+ if (strcmp(argv[1], "ipc_helper_heavy_traffic_deadlock_bug") == 0) {
+ return ipc_helper_heavy_traffic_deadlock_bug();
+ }
+
if (strcmp(argv[1], "ipc_send_recv_helper") == 0) {
return ipc_send_recv_helper();
}
diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c
index 3167ed44bf..de0db0cc48 100644
--- a/deps/uv/test/runner-unix.c
+++ b/deps/uv/test/runner-unix.c
@@ -57,8 +57,8 @@ int platform_init(int argc, char **argv) {
}
-/* Invoke "argv[0] test-name [test-part]". Store process info in *p. */
-/* Make sure that all stdio output of the processes is buffered up. */
+/* Invoke "argv[0] test-name [test-part]". Store process info in *p. Make sure
+ * that all stdio output of the processes is buffered up. */
int process_start(char* name, char* part, process_info_t* p, int is_helper) {
FILE* stdout_file;
int stdout_fd;
@@ -161,9 +161,9 @@ static void* dowait(void* data) {
}
-/* Wait for all `n` processes in `vec` to terminate. */
-/* Time out after `timeout` msec, or never if timeout == -1 */
-/* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */
+/* Wait for all `n` processes in `vec` to terminate. Time out after `timeout`
+ * msec, or never if timeout == -1. Return 0 if all processes are terminated,
+ * -1 on error, -2 on timeout. */
int process_wait(process_info_t* vec, int n, int timeout) {
int i;
int r;
@@ -358,8 +358,7 @@ int process_terminate(process_info_t *p) {
}
-/* Return the exit code of process p. */
-/* On error, return -1. */
+/* Return the exit code of process p. On error, return -1. */
int process_reap(process_info_t *p) {
if (WIFEXITED(p->status)) {
return WEXITSTATUS(p->status);
diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c
index d86fda3c5d..ce97270547 100644
--- a/deps/uv/test/runner-win.c
+++ b/deps/uv/test/runner-win.c
@@ -165,8 +165,8 @@ error:
}
-/* Timeout is is msecs. Set timeout < 0 to never time out. */
-/* Returns 0 when all processes are terminated, -2 on timeout. */
+/* Timeout is in msecs. Set timeout < 0 to never time out. Returns 0 when all
+ * processes are terminated, -2 on timeout. */
int process_wait(process_info_t *vec, int n, int timeout) {
int i;
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
diff --git a/deps/uv/test/runner.h b/deps/uv/test/runner.h
index 555f2f8eb7..1a33950852 100644
--- a/deps/uv/test/runner.h
+++ b/deps/uv/test/runner.h
@@ -138,13 +138,13 @@ void print_lines(const char* buffer, size_t size, FILE* stream);
/* Do platform-specific initialization. */
int platform_init(int argc, char** argv);
-/* Invoke "argv[0] test-name [test-part]". Store process info in *p. */
-/* Make sure that all stdio output of the processes is buffered up. */
+/* Invoke "argv[0] test-name [test-part]". Store process info in *p. Make sure
+ * that all stdio output of the processes is buffered up. */
int process_start(char *name, char* part, process_info_t *p, int is_helper);
-/* Wait for all `n` processes in `vec` to terminate. */
-/* Time out after `timeout` msec, or never if timeout == -1 */
-/* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */
+/* Wait for all `n` processes in `vec` to terminate. Time out after `timeout`
+ * msec, or never if timeout == -1. Return 0 if all processes are terminated,
+ * -1 on error, -2 on timeout. */
int process_wait(process_info_t *vec, int n, int timeout);
/* Returns the number of bytes in the stdio output buffer for process `p`. */
@@ -164,8 +164,7 @@ char* process_get_name(process_info_t *p);
/* Terminate process `p`. */
int process_terminate(process_info_t *p);
-/* Return the exit code of process p. */
-/* On error, return -1. */
+/* Return the exit code of process p. On error, return -1. */
int process_reap(process_info_t *p);
/* Clean up after terminating process `p` (e.g. free the output buffer etc.). */
diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h
index af99d92fb4..92a90a540b 100644
--- a/deps/uv/test/task.h
+++ b/deps/uv/test/task.h
@@ -29,7 +29,7 @@
#include <stdlib.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "stdint-msvc2008.h"
+# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
diff --git a/deps/uv/test/test-callback-stack.c b/deps/uv/test/test-callback-stack.c
index 8855c0841b..1871e7e981 100644
--- a/deps/uv/test/test-callback-stack.c
+++ b/deps/uv/test/test-callback-stack.c
@@ -88,10 +88,9 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
bytes_received += nread;
- /* We call shutdown here because when bytes_received == sizeof MESSAGE */
- /* there will be no more data sent nor received, so here it would be */
- /* possible for a backend to to call shutdown_cb immediately and *not* */
- /* from a fresh stack. */
+ /* We call shutdown here because when bytes_received == sizeof MESSAGE there
+ * will be no more data sent nor received, so here it would be possible for a
+ * backend to call shutdown_cb immediately and *not* from a fresh stack. */
if (bytes_received == sizeof MESSAGE) {
nested++;
@@ -131,10 +130,10 @@ static void write_cb(uv_write_t* req, int status) {
puts("Data written. 500ms timeout...");
- /* After the data has been sent, we're going to wait for a while, then */
- /* start reading. This makes us certain that the message has been echoed */
- /* back to our receive buffer when we start reading. This maximizes the */
- /* temptation for the backend to use dirty stack for calling read_cb. */
+ /* After the data has been sent, we're going to wait for a while, then start
+ * reading. This makes us certain that the message has been echoed back to
+ * our receive buffer when we start reading. This maximizes the temptation
+ * for the backend to use dirty stack for calling read_cb. */
nested++;
r = uv_timer_init(uv_default_loop(), &timer);
ASSERT(r == 0);
diff --git a/deps/uv/test/test-connection-fail.c b/deps/uv/test/test-connection-fail.c
index 328bff46e7..8338cacdec 100644
--- a/deps/uv/test/test-connection-fail.c
+++ b/deps/uv/test/test-connection-fail.c
@@ -98,8 +98,8 @@ static void connection_fail(uv_connect_cb connect_cb) {
r = uv_tcp_init(uv_default_loop(), &tcp);
ASSERT(!r);
- /* We are never doing multiple reads/connects at a time anyway. */
- /* so these handles can be pre-initialized. */
+ /* We are never doing multiple reads/connects at a time anyway. so these
+ * handles can be pre-initialized. */
ASSERT(0 == uv_tcp_bind(&tcp, (const struct sockaddr*) &client_addr, 0));
r = uv_tcp_connect(&req,
diff --git a/deps/uv/test/test-delayed-accept.c b/deps/uv/test/test-delayed-accept.c
index 4a7998909c..513e69bd5b 100644
--- a/deps/uv/test/test-delayed-accept.c
+++ b/deps/uv/test/test-delayed-accept.c
@@ -138,8 +138,8 @@ static void connect_cb(uv_connect_t* req, int status) {
ASSERT(req != NULL);
ASSERT(status == 0);
- /* Not that the server will send anything, but otherwise we'll never know */
- /* when the server closes the connection. */
+ /* Not that the server will send anything, but otherwise we'll never know
+ * when the server closes the connection. */
r = uv_read_start((uv_stream_t*)(req->handle), alloc_cb, read_cb);
ASSERT(r == 0);
diff --git a/deps/uv/test/test-fork.c b/deps/uv/test/test-fork.c
index 39b59c8f20..2a1ddc497a 100644
--- a/deps/uv/test/test-fork.c
+++ b/deps/uv/test/test-fork.c
@@ -317,8 +317,7 @@ TEST_IMPL(fork_signal_to_child_closed) {
printf("Waiting for child in parent\n");
assert_wait_child(child_pid);
} else {
- /* child */
- /* Our signal handler should still be installed. */
+ /* Child. Our signal handler should still be installed. */
ASSERT(0 == uv_loop_fork(uv_default_loop()));
printf("Checking loop in child\n");
ASSERT(0 != uv_loop_alive(uv_default_loop()));
@@ -652,13 +651,11 @@ TEST_IMPL(fork_threadpool_queue_work_simple) {
ASSERT(child_pid != -1);
if (child_pid != 0) {
- /* parent */
- /* We can still run work. */
+ /* Parent. We can still run work. */
assert_run_work(uv_default_loop());
assert_wait_child(child_pid);
} else {
- /* child */
- /* We can work in a new loop. */
+ /* Child. We can work in a new loop. */
printf("Running child in %d\n", getpid());
uv_loop_init(&loop);
printf("Child first watch\n");
diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c
index 6cd43b4502..eadff542bc 100644
--- a/deps/uv/test/test-fs-copyfile.c
+++ b/deps/uv/test/test-fs-copyfile.c
@@ -179,7 +179,7 @@ TEST_IMPL(fs_copyfile) {
unlink(dst);
r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE_FORCE,
NULL);
- ASSERT(r == 0 || r == UV_ENOSYS || r == UV_ENOTSUP || r == UV_ENOTTY);
+ ASSERT(r == 0 || r == UV_ENOSYS || r == UV_ENOTSUP);
if (r == 0)
handle_result(&req);
diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c
index 000a151a64..57da39891a 100644
--- a/deps/uv/test/test-fs.c
+++ b/deps/uv/test/test-fs.c
@@ -84,6 +84,7 @@ static int chmod_cb_count;
static int fchmod_cb_count;
static int chown_cb_count;
static int fchown_cb_count;
+static int lchown_cb_count;
static int link_cb_count;
static int symlink_cb_count;
static int readlink_cb_count;
@@ -253,6 +254,13 @@ static void chown_cb(uv_fs_t* req) {
uv_fs_req_cleanup(req);
}
+static void lchown_cb(uv_fs_t* req) {
+ ASSERT(req->fs_type == UV_FS_LCHOWN);
+ ASSERT(req->result == 0);
+ lchown_cb_count++;
+ uv_fs_req_cleanup(req);
+}
+
static void chown_root_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_CHOWN);
#if defined(_WIN32) || defined(__MSYS__)
@@ -1540,6 +1548,7 @@ TEST_IMPL(fs_chown) {
/* Setup. */
unlink("test_file");
+ unlink("test_file_link");
loop = uv_default_loop();
@@ -1583,7 +1592,29 @@ TEST_IMPL(fs_chown) {
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(fchown_cb_count == 1);
- close(file);
+ /* sync link */
+ r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL);
+ ASSERT(r == 0);
+ ASSERT(req.result == 0);
+ uv_fs_req_cleanup(&req);
+
+ /* sync lchown */
+ r = uv_fs_lchown(NULL, &req, "test_file_link", -1, -1, NULL);
+ ASSERT(r == 0);
+ ASSERT(req.result == 0);
+ uv_fs_req_cleanup(&req);
+
+ /* async lchown */
+ r = uv_fs_lchown(loop, &req, "test_file_link", -1, -1, lchown_cb);
+ ASSERT(r == 0);
+ uv_run(loop, UV_RUN_DEFAULT);
+ ASSERT(lchown_cb_count == 1);
+
+ /* Close file */
+ r = uv_fs_close(NULL, &req, file, NULL);
+ ASSERT(r == 0);
+ ASSERT(req.result == 0);
+ uv_fs_req_cleanup(&req);
/*
* Run the loop just to check we don't have make any extraneous uv_ref()
@@ -1593,6 +1624,7 @@ TEST_IMPL(fs_chown) {
/* Cleanup. */
unlink("test_file");
+ unlink("test_file_link");
MAKE_VALGRIND_HAPPY();
return 0;
@@ -3230,3 +3262,138 @@ TEST_IMPL(fs_exclusive_sharing_mode) {
return 0;
}
#endif
+
+#ifdef _WIN32
+int call_icacls(const char* command, ...) {
+ char icacls_command[1024];
+ va_list args;
+
+ va_start(args, command);
+ vsnprintf(icacls_command, ARRAYSIZE(icacls_command), command, args);
+ va_end(args);
+ return system(icacls_command);
+}
+
+TEST_IMPL(fs_open_readonly_acl) {
+ uv_passwd_t pwd;
+ uv_fs_t req;
+ int r;
+
+ /*
+ Based on Node.js test from
+ https://github.com/nodejs/node/commit/3ba81e34e86a5c32658e218cb6e65b13e8326bc5
+
+ If anything goes wrong, you can delte the test_fle_icacls with:
+
+ icacls test_file_icacls /remove "%USERNAME%" /inheritance:e
+ attrib -r test_file_icacls
+ del test_file_icacls
+ */
+
+ /* Setup - clear the ACL and remove the file */
+ loop = uv_default_loop();
+ r = uv_os_get_passwd(&pwd);
+ ASSERT(r == 0);
+ call_icacls("icacls test_file_icacls /remove \"%s\" /inheritance:e",
+ pwd.username);
+ uv_fs_chmod(loop, &req, "test_file_icacls", S_IWUSR, NULL);
+ unlink("test_file_icacls");
+
+ /* Create the file */
+ r = uv_fs_open(loop,
+ &open_req1,
+ "test_file_icacls",
+ O_RDONLY | O_CREAT,
+ S_IRUSR,
+ NULL);
+ ASSERT(r >= 0);
+ ASSERT(open_req1.result >= 0);
+ uv_fs_req_cleanup(&open_req1);
+ r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ /* Set up ACL */
+ r = call_icacls("icacls test_file_icacls /inheritance:r /remove \"%s\"",
+ pwd.username);
+ if (r != 0) {
+ goto acl_cleanup;
+ }
+ r = call_icacls("icacls test_file_icacls /grant \"%s\":RX", pwd.username);
+ if (r != 0) {
+ goto acl_cleanup;
+ }
+
+ /* Try opening the file */
+ r = uv_fs_open(NULL, &open_req1, "test_file_icacls", O_RDONLY, 0, NULL);
+ if (r < 0) {
+ goto acl_cleanup;
+ }
+ uv_fs_req_cleanup(&open_req1);
+ r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
+ if (r != 0) {
+ goto acl_cleanup;
+ }
+ uv_fs_req_cleanup(&close_req);
+
+ acl_cleanup:
+ /* Cleanup */
+ call_icacls("icacls test_file_icacls /remove \"%s\" /inheritance:e",
+ pwd.username);
+ unlink("test_file_icacls");
+ uv_os_free_passwd(&pwd);
+ ASSERT(r == 0);
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+#endif
+
+#ifdef _WIN32
+TEST_IMPL(fs_fchmod_archive_readonly) {
+ uv_fs_t req;
+ uv_file file;
+ int r;
+ /* Test clearing read-only flag from files with Archive flag cleared */
+
+ /* Setup*/
+ unlink("test_file");
+ r = uv_fs_open(NULL,
+ &req,
+ "test_file",
+ O_WRONLY | O_CREAT,
+ S_IWUSR | S_IRUSR,
+ NULL);
+ ASSERT(r >= 0);
+ ASSERT(req.result >= 0);
+ file = req.result;
+ uv_fs_req_cleanup(&req);
+ r = uv_fs_close(NULL, &req, file, NULL);
+ ASSERT(r == 0);
+ uv_fs_req_cleanup(&req);
+ /* Make the file read-only and clear archive flag */
+ r = SetFileAttributes("test_file", FILE_ATTRIBUTE_READONLY);
+ ASSERT(r != 0);
+ check_permission("test_file", 0400);
+ /* Try fchmod */
+ r = uv_fs_open(NULL, &req, "test_file", O_RDONLY, 0, NULL);
+ ASSERT(r >= 0);
+ ASSERT(req.result >= 0);
+ file = req.result;
+ uv_fs_req_cleanup(&req);
+ r = uv_fs_fchmod(NULL, &req, file, S_IWUSR, NULL);
+ ASSERT(r == 0);
+ ASSERT(req.result == 0);
+ uv_fs_req_cleanup(&req);
+ r = uv_fs_close(NULL, &req, file, NULL);
+ ASSERT(r == 0);
+ uv_fs_req_cleanup(&req);
+ check_permission("test_file", S_IWUSR);
+
+ /* Restore Archive flag for rest of the tests */
+ r = SetFileAttributes("test_file", FILE_ATTRIBUTE_ARCHIVE);
+ ASSERT(r != 0);
+
+ return 0;
+}
+#endif
diff --git a/deps/uv/test/test-hrtime.c b/deps/uv/test/test-hrtime.c
index 72a4d4b181..fbe9a68bfc 100644
--- a/deps/uv/test/test-hrtime.c
+++ b/deps/uv/test/test-hrtime.c
@@ -43,9 +43,9 @@ TEST_IMPL(hrtime) {
/* printf("i= %d diff = %llu\n", i, (unsigned long long int) diff); */
- /* The windows Sleep() function has only a resolution of 10-20 ms. */
- /* Check that the difference between the two hrtime values is somewhat in */
- /* the range we expect it to be. */
+ /* The windows Sleep() function has only a resolution of 10-20 ms. Check
+ * that the difference between the two hrtime values is somewhat in the
+ * range we expect it to be. */
ASSERT(diff > (uint64_t) 25 * NANOSEC / MILLISEC);
ASSERT(diff < (uint64_t) 80 * NANOSEC / MILLISEC);
--i;
diff --git a/deps/uv/test/test-ipc-heavy-traffic-deadlock-bug.c b/deps/uv/test/test-ipc-heavy-traffic-deadlock-bug.c
new file mode 100644
index 0000000000..240fc64588
--- /dev/null
+++ b/deps/uv/test/test-ipc-heavy-traffic-deadlock-bug.c
@@ -0,0 +1,158 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "task.h"
+#include "uv.h"
+
+#include <string.h>
+
+/* See test-ipc.c */
+void spawn_helper(uv_pipe_t* channel,
+ uv_process_t* process,
+ const char* helper);
+
+#define NUM_WRITES 256
+#define BUFFERS_PER_WRITE 3
+#define BUFFER_SIZE 0x2000 /* 8 kb. */
+#define BUFFER_CONTENT 42
+
+#define XFER_SIZE (NUM_WRITES * BUFFERS_PER_WRITE * BUFFER_SIZE)
+
+struct write_info {
+ uv_write_t write_req;
+ char buffers[BUFFER_SIZE][BUFFERS_PER_WRITE];
+};
+
+static uv_shutdown_t shutdown_req;
+
+static size_t bytes_written;
+static size_t bytes_read;
+
+static void write_cb(uv_write_t* req, int status) {
+ struct write_info* write_info =
+ container_of(req, struct write_info, write_req);
+ ASSERT(status == 0);
+ bytes_written += BUFFERS_PER_WRITE * BUFFER_SIZE;
+ free(write_info);
+}
+
+static void shutdown_cb(uv_shutdown_t* req, int status) {
+ ASSERT(status == 0);
+ uv_close((uv_handle_t*) req->handle, NULL);
+}
+
+static void do_write(uv_stream_t* handle) {
+ struct write_info* write_info;
+ uv_buf_t bufs[BUFFERS_PER_WRITE];
+ size_t i;
+ int r;
+
+ write_info = malloc(sizeof *write_info);
+ ASSERT(write_info != NULL);
+
+ for (i = 0; i < BUFFERS_PER_WRITE; i++) {
+ memset(&write_info->buffers[i], BUFFER_CONTENT, BUFFER_SIZE);
+ bufs[i] = uv_buf_init(write_info->buffers[i], BUFFER_SIZE);
+ }
+
+ r = uv_write(
+ &write_info->write_req, handle, bufs, BUFFERS_PER_WRITE, write_cb);
+ ASSERT(r == 0);
+}
+
+static void alloc_cb(uv_handle_t* handle,
+ size_t suggested_size,
+ uv_buf_t* buf) {
+ buf->base = malloc(suggested_size);
+ buf->len = (int) suggested_size;
+}
+
+#ifndef _WIN32
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) {
+ ssize_t i;
+ int r;
+
+ ASSERT(nread >= 0);
+ bytes_read += nread;
+
+ for (i = 0; i < nread; i++)
+ ASSERT(buf->base[i] == BUFFER_CONTENT);
+ free(buf->base);
+
+ if (bytes_read >= XFER_SIZE) {
+ r = uv_read_stop(handle);
+ ASSERT(r == 0);
+ r = uv_shutdown(&shutdown_req, handle, shutdown_cb);
+ ASSERT(r == 0);
+ }
+}
+
+static void do_writes_and_reads(uv_stream_t* handle) {
+ size_t i;
+ int r;
+
+ bytes_written = 0;
+ bytes_read = 0;
+
+ for (i = 0; i < NUM_WRITES; i++) {
+ do_write(handle);
+ }
+
+ r = uv_read_start(handle, alloc_cb, read_cb);
+ ASSERT(r == 0);
+
+ r = uv_run(handle->loop, UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+
+ ASSERT(bytes_written == XFER_SIZE);
+ ASSERT(bytes_read == XFER_SIZE);
+}
+
+TEST_IMPL(ipc_heavy_traffic_deadlock_bug) {
+ uv_pipe_t pipe;
+ uv_process_t process;
+
+ spawn_helper(&pipe, &process, "ipc_helper_heavy_traffic_deadlock_bug");
+ do_writes_and_reads((uv_stream_t*) &pipe);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+int ipc_helper_heavy_traffic_deadlock_bug(void) {
+ uv_pipe_t pipe;
+ int r;
+
+ r = uv_pipe_init(uv_default_loop(), &pipe, 1);
+ ASSERT(r == 0);
+ r = uv_pipe_open(&pipe, 0);
+ ASSERT(r == 0);
+
+ do_writes_and_reads((uv_stream_t*) &pipe);
+ uv_sleep(100);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-ipc-send-recv.c b/deps/uv/test/test-ipc-send-recv.c
index 917744cbae..3dedc86b8b 100644
--- a/deps/uv/test/test-ipc-send-recv.c
+++ b/deps/uv/test/test-ipc-send-recv.c
@@ -25,7 +25,7 @@
#include <stdio.h>
#include <string.h>
-/* See test-ipc.ctx */
+/* See test-ipc.c */
void spawn_helper(uv_pipe_t* channel,
uv_process_t* process,
const char* helper);
@@ -149,6 +149,7 @@ static void connect_cb(uv_connect_t* req, int status) {
&ctx.send.stream,
NULL);
ASSERT(r == 0);
+ ASSERT(ctx.write_req.send_handle == &ctx.send.stream);
/* Perform two writes to the same pipe to make sure that on Windows we are
* not running into issue 505:
@@ -160,6 +161,7 @@ static void connect_cb(uv_connect_t* req, int status) {
&ctx.send2.stream,
NULL);
ASSERT(r == 0);
+ ASSERT(ctx.write_req2.send_handle == &ctx.send2.stream);
r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb);
ASSERT(r == 0);
@@ -344,6 +346,7 @@ static void read_cb(uv_stream_t* handle,
&recv->stream,
write2_cb);
ASSERT(r == 0);
+ ASSERT(write_req->send_handle == &recv->stream);
} while (uv_pipe_pending_count(pipe) > 0);
}
diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c
index 88d63d4dc6..200f68d600 100644
--- a/deps/uv/test/test-ipc.c
+++ b/deps/uv/test/test-ipc.c
@@ -281,7 +281,7 @@ void spawn_helper(uv_pipe_t* channel,
char exepath[1024];
char* args[3];
int r;
- uv_stdio_container_t stdio[1];
+ uv_stdio_container_t stdio[3];
r = uv_pipe_init(uv_default_loop(), channel, 1);
ASSERT(r == 0);
@@ -300,12 +300,15 @@ void spawn_helper(uv_pipe_t* channel,
options.file = exepath;
options.args = args;
options.exit_cb = exit_cb;
-
options.stdio = stdio;
- options.stdio[0].flags = UV_CREATE_PIPE |
- UV_READABLE_PIPE | UV_WRITABLE_PIPE;
- options.stdio[0].data.stream = (uv_stream_t*)channel;
- options.stdio_count = 1;
+ options.stdio_count = ARRAY_SIZE(stdio);
+
+ stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE;
+ stdio[0].data.stream = (uv_stream_t*) channel;
+ stdio[1].flags = UV_INHERIT_FD;
+ stdio[1].data.fd = 1;
+ stdio[2].flags = UV_INHERIT_FD;
+ stdio[2].data.fd = 2;
r = uv_spawn(uv_default_loop(), process, &options);
ASSERT(r == 0);
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index b89930d709..e59c6b6551 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -57,6 +57,7 @@ TEST_DECLARE (tty_pty)
TEST_DECLARE (stdio_over_pipes)
TEST_DECLARE (ip6_pton)
TEST_DECLARE (connect_unspecified)
+TEST_DECLARE (ipc_heavy_traffic_deadlock_bug)
TEST_DECLARE (ipc_listen_before_write)
TEST_DECLARE (ipc_listen_after_write)
#ifndef _WIN32
@@ -71,8 +72,11 @@ TEST_DECLARE (ipc_closed_handle)
#endif
TEST_DECLARE (tcp_alloc_cb_fail)
TEST_DECLARE (tcp_ping_pong)
-TEST_DECLARE (tcp_ping_pong_v6)
+TEST_DECLARE (tcp_ping_pong_vec)
+TEST_DECLARE (tcp6_ping_pong)
+TEST_DECLARE (tcp6_ping_pong_vec)
TEST_DECLARE (pipe_ping_pong)
+TEST_DECLARE (pipe_ping_pong_vec)
TEST_DECLARE (delayed_accept)
TEST_DECLARE (multiple_listen)
#ifndef _WIN32
@@ -337,6 +341,8 @@ TEST_DECLARE (fs_file_pos_after_op_with_offset)
TEST_DECLARE (fs_null_req)
#ifdef _WIN32
TEST_DECLARE (fs_exclusive_sharing_mode)
+TEST_DECLARE (fs_open_readonly_acl)
+TEST_DECLARE (fs_fchmod_archive_readonly)
#endif
TEST_DECLARE (threadpool_queue_work_simple)
TEST_DECLARE (threadpool_queue_work_einval)
@@ -479,6 +485,7 @@ TASK_LIST_START
TEST_ENTRY (stdio_over_pipes)
TEST_ENTRY (ip6_pton)
TEST_ENTRY (connect_unspecified)
+ TEST_ENTRY (ipc_heavy_traffic_deadlock_bug)
TEST_ENTRY (ipc_listen_before_write)
TEST_ENTRY (ipc_listen_after_write)
#ifndef _WIN32
@@ -497,12 +504,21 @@ TASK_LIST_START
TEST_ENTRY (tcp_ping_pong)
TEST_HELPER (tcp_ping_pong, tcp4_echo_server)
- TEST_ENTRY (tcp_ping_pong_v6)
- TEST_HELPER (tcp_ping_pong_v6, tcp6_echo_server)
+ TEST_ENTRY (tcp_ping_pong_vec)
+ TEST_HELPER (tcp_ping_pong_vec, tcp4_echo_server)
+
+ TEST_ENTRY (tcp6_ping_pong)
+ TEST_HELPER (tcp6_ping_pong, tcp6_echo_server)
+
+ TEST_ENTRY (tcp6_ping_pong_vec)
+ TEST_HELPER (tcp6_ping_pong_vec, tcp6_echo_server)
TEST_ENTRY (pipe_ping_pong)
TEST_HELPER (pipe_ping_pong, pipe_echo_server)
+ TEST_ENTRY (pipe_ping_pong_vec)
+ TEST_HELPER (pipe_ping_pong_vec, pipe_echo_server)
+
TEST_ENTRY (delayed_accept)
TEST_ENTRY (multiple_listen)
@@ -708,7 +724,7 @@ TASK_LIST_START
TEST_ENTRY (hrtime)
TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
- TEST_ENTRY (getaddrinfo_fail_sync)
+ TEST_ENTRY_CUSTOM (getaddrinfo_fail_sync, 0, 0, 10000)
TEST_ENTRY (getaddrinfo_basic)
TEST_ENTRY (getaddrinfo_basic_sync)
@@ -869,6 +885,8 @@ TASK_LIST_START
TEST_ENTRY (fs_null_req)
#ifdef _WIN32
TEST_ENTRY (fs_exclusive_sharing_mode)
+ TEST_ENTRY (fs_open_readonly_acl)
+ TEST_ENTRY (fs_fchmod_archive_readonly)
#endif
TEST_ENTRY (get_osfhandle_valid_handle)
TEST_ENTRY (threadpool_queue_work_simple)
diff --git a/deps/uv/test/test-loop-handles.c b/deps/uv/test/test-loop-handles.c
index c3e8498ae9..6471cd08b3 100644
--- a/deps/uv/test/test-loop-handles.c
+++ b/deps/uv/test/test-loop-handles.c
@@ -228,8 +228,8 @@ static void check_cb(uv_check_t* handle) {
uv_close((uv_handle_t*)&idle_1_handles[i], idle_1_close_cb);
}
- /* This handle is closed/recreated every time, close it only if it is */
- /* active.*/
+ /* This handle is closed/recreated every time, close it only if it is
+ * active. */
if (idle_2_is_active) {
uv_close((uv_handle_t*)&idle_2_handle, idle_2_close_cb);
}
@@ -246,10 +246,10 @@ static void prepare_2_cb(uv_prepare_t* handle) {
fflush(stderr);
ASSERT(handle == &prepare_2_handle);
- /* prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), */
- /* and it stops itself immediately. A started watcher is not queued */
- /* until the next round, so when this callback is made */
- /* (loop_iteration % 2 == 0) cannot be true. */
+ /* Prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), and it
+ * stops itself immediately. A started watcher is not queued until the next
+ * round, so when this callback is made (loop_iteration % 2 == 0) cannot be
+ * true. */
ASSERT(loop_iteration % 2 != 0);
r = uv_prepare_stop((uv_prepare_t*)handle);
@@ -304,8 +304,8 @@ TEST_IMPL(loop_handles) {
/* don't init or start idle_2, both is done by idle_1_cb */
- /* the timer callback is there to keep the event loop polling */
- /* unref it as it is not supposed to keep the loop alive */
+ /* The timer callback is there to keep the event loop polling unref it as it
+ * is not supposed to keep the loop alive */
r = uv_timer_init(uv_default_loop(), &timer_handle);
ASSERT(r == 0);
r = uv_timer_start(&timer_handle, timer_cb, TIMEOUT, TIMEOUT);
diff --git a/deps/uv/test/test-ping-pong.c b/deps/uv/test/test-ping-pong.c
index 508f0db67b..c86a3f4a66 100644
--- a/deps/uv/test/test-ping-pong.c
+++ b/deps/uv/test/test-ping-pong.c
@@ -22,8 +22,8 @@
#include "uv.h"
#include "task.h"
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
static int completed_pingers = 0;
@@ -41,6 +41,7 @@ static int pinger_on_connect_count;
typedef struct {
+ int vectored_writes;
int pongs;
int state;
union {
@@ -77,15 +78,26 @@ static void pinger_after_write(uv_write_t *req, int status) {
static void pinger_write_ping(pinger_t* pinger) {
uv_write_t *req;
- uv_buf_t buf;
-
- buf = uv_buf_init(PING, sizeof(PING) - 1);
+ uv_buf_t bufs[sizeof PING - 1];
+ int i, nbufs;
+
+ if (!pinger->vectored_writes) {
+ /* Write a single buffer. */
+ nbufs = 1;
+ bufs[0] = uv_buf_init(PING, sizeof PING - 1);
+ } else {
+ /* Write multiple buffers, each with one byte in them. */
+ nbufs = sizeof PING - 1;
+ for (i = 0; i < nbufs; i++) {
+ bufs[i] = uv_buf_init(&PING[i], 1);
+ }
+ }
req = malloc(sizeof(*req));
if (uv_write(req,
(uv_stream_t*) &pinger->stream.tcp,
- &buf,
- 1,
+ bufs,
+ nbufs,
pinger_after_write)) {
FATAL("uv_write failed");
}
@@ -154,7 +166,7 @@ static void pinger_on_connect(uv_connect_t *req, int status) {
/* same ping-pong test, but using IPv6 connection */
-static void tcp_pinger_v6_new(void) {
+static void tcp_pinger_v6_new(int vectored_writes) {
int r;
struct sockaddr_in6 server_addr;
pinger_t *pinger;
@@ -163,6 +175,7 @@ static void tcp_pinger_v6_new(void) {
ASSERT(0 ==uv_ip6_addr("::1", TEST_PORT, &server_addr));
pinger = malloc(sizeof(*pinger));
ASSERT(pinger != NULL);
+ pinger->vectored_writes = vectored_writes;
pinger->state = 0;
pinger->pongs = 0;
@@ -171,8 +184,8 @@ static void tcp_pinger_v6_new(void) {
pinger->stream.tcp.data = pinger;
ASSERT(!r);
- /* We are never doing multiple reads/connects at a time anyway. */
- /* so these handles can be pre-initialized. */
+ /* We are never doing multiple reads/connects at a time anyway, so these
+ * handles can be pre-initialized. */
r = uv_tcp_connect(&pinger->connect_req,
&pinger->stream.tcp,
(const struct sockaddr*) &server_addr,
@@ -184,7 +197,7 @@ static void tcp_pinger_v6_new(void) {
}
-static void tcp_pinger_new(void) {
+static void tcp_pinger_new(int vectored_writes) {
int r;
struct sockaddr_in server_addr;
pinger_t *pinger;
@@ -192,6 +205,7 @@ static void tcp_pinger_new(void) {
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
pinger = malloc(sizeof(*pinger));
ASSERT(pinger != NULL);
+ pinger->vectored_writes = vectored_writes;
pinger->state = 0;
pinger->pongs = 0;
@@ -200,8 +214,8 @@ static void tcp_pinger_new(void) {
pinger->stream.tcp.data = pinger;
ASSERT(!r);
- /* We are never doing multiple reads/connects at a time anyway. */
- /* so these handles can be pre-initialized. */
+ /* We are never doing multiple reads/connects at a time anyway, so these
+ * handles can be pre-initialized. */
r = uv_tcp_connect(&pinger->connect_req,
&pinger->stream.tcp,
(const struct sockaddr*) &server_addr,
@@ -213,12 +227,13 @@ static void tcp_pinger_new(void) {
}
-static void pipe_pinger_new(void) {
+static void pipe_pinger_new(int vectored_writes) {
int r;
pinger_t *pinger;
pinger = (pinger_t*)malloc(sizeof(*pinger));
ASSERT(pinger != NULL);
+ pinger->vectored_writes = vectored_writes;
pinger->state = 0;
pinger->pongs = 0;
@@ -227,9 +242,8 @@ static void pipe_pinger_new(void) {
pinger->stream.pipe.data = pinger;
ASSERT(!r);
- /* We are never doing multiple reads/connects at a time anyway. */
- /* so these handles can be pre-initialized. */
-
+ /* We are never doing multiple reads/connects at a time anyway, so these
+ * handles can be pre-initialized. */
uv_pipe_connect(&pinger->connect_req, &pinger->stream.pipe, TEST_PIPENAME,
pinger_on_connect);
@@ -238,10 +252,8 @@ static void pipe_pinger_new(void) {
}
-TEST_IMPL(tcp_ping_pong) {
- tcp_pinger_new();
+static int run_ping_pong_test(void) {
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
-
ASSERT(completed_pingers == 1);
MAKE_VALGRIND_HAPPY();
@@ -249,26 +261,41 @@ TEST_IMPL(tcp_ping_pong) {
}
-TEST_IMPL(tcp_ping_pong_v6) {
+TEST_IMPL(tcp_ping_pong) {
+ tcp_pinger_new(0);
+ return run_ping_pong_test();
+}
+
+
+TEST_IMPL(tcp_ping_pong_vec) {
+ tcp_pinger_new(1);
+ return run_ping_pong_test();
+}
+
+
+TEST_IMPL(tcp6_ping_pong) {
if (!can_ipv6())
RETURN_SKIP("IPv6 not supported");
+ tcp_pinger_v6_new(0);
+ return run_ping_pong_test();
+}
- tcp_pinger_v6_new();
- uv_run(uv_default_loop(), UV_RUN_DEFAULT);
- ASSERT(completed_pingers == 1);
-
- MAKE_VALGRIND_HAPPY();
- return 0;
+TEST_IMPL(tcp6_ping_pong_vec) {
+ if (!can_ipv6())
+ RETURN_SKIP("IPv6 not supported");
+ tcp_pinger_v6_new(1);
+ return run_ping_pong_test();
}
TEST_IMPL(pipe_ping_pong) {
- pipe_pinger_new();
- uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+ pipe_pinger_new(0);
+ return run_ping_pong_test();
+}
- ASSERT(completed_pingers == 1);
- MAKE_VALGRIND_HAPPY();
- return 0;
+TEST_IMPL(pipe_ping_pong_vec) {
+ pipe_pinger_new(1);
+ return run_ping_pong_test();
}
diff --git a/deps/uv/test/test-pipe-set-fchmod.c b/deps/uv/test/test-pipe-set-fchmod.c
index de4932dc1a..91e476652e 100644
--- a/deps/uv/test/test-pipe-set-fchmod.c
+++ b/deps/uv/test/test-pipe-set-fchmod.c
@@ -39,8 +39,8 @@ TEST_IMPL(pipe_set_chmod) {
r = uv_pipe_bind(&pipe_handle, TEST_PIPENAME);
ASSERT(r == 0);
- /* No easy way to test if this works, we will only make sure that */
- /* the call is successful. */
+ /* No easy way to test if this works, we will only make sure that the call is
+ * successful. */
r = uv_pipe_chmod(&pipe_handle, UV_READABLE);
if (r == UV_EPERM) {
MAKE_VALGRIND_HAPPY();
diff --git a/deps/uv/test/test-process-title-threadsafe.c b/deps/uv/test/test-process-title-threadsafe.c
index d986576ed9..cc3fd41a13 100644
--- a/deps/uv/test/test-process-title-threadsafe.c
+++ b/deps/uv/test/test-process-title-threadsafe.c
@@ -26,7 +26,7 @@
#include <string.h>
#ifdef __APPLE__
-# define NUM_ITERATIONS 20
+# define NUM_ITERATIONS 10
#else
# define NUM_ITERATIONS 50
#endif
diff --git a/deps/uv/test/test-signal-multiple-loops.c b/deps/uv/test/test-signal-multiple-loops.c
index 1272d4576f..79242fc9fa 100644
--- a/deps/uv/test/test-signal-multiple-loops.c
+++ b/deps/uv/test/test-signal-multiple-loops.c
@@ -249,7 +249,7 @@ TEST_IMPL(signal_multiple_loops) {
uv_sem_wait(&sem);
/* Block all signals to this thread, so we are sure that from here the signal
- * handler runs in another thread. This is is more likely to catch thread and
+ * handler runs in another thread. This is more likely to catch thread and
* signal safety issues if there are any.
*/
sigfillset(&sigset);
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index 4a2869a18a..1ab6e78807 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/test/test-spawn.c
@@ -1637,8 +1637,8 @@ TEST_IMPL(spawn_reads_child_path) {
static const char dyld_path_var[] = "LD_LIBRARY_PATH";
#endif
- /* Set up the process, but make sure that the file to run is relative and */
- /* requires a lookup into PATH */
+ /* Set up the process, but make sure that the file to run is relative and
+ * requires a lookup into PATH. */
init_process_options("spawn_helper1", exit_cb);
/* Set up the PATH env variable */
@@ -1805,8 +1805,8 @@ TEST_IMPL(spawn_quoted_path) {
options.args = args;
options.exit_cb = exit_cb;
options.flags = 0;
- /* We test if search_path works correctly with semicolons in quoted path. */
- /* We will use invalid drive, so we are sure no executable is spawned */
+ /* We test if search_path works correctly with semicolons in quoted path. We
+ * will use an invalid drive, so we are sure no executable is spawned. */
quoted_path_env[0] = "PATH=\"xyz:\\test;\";xyz:\\other";
quoted_path_env[1] = NULL;
options.env = quoted_path_env;
diff --git a/deps/uv/test/test-tcp-open.c b/deps/uv/test/test-tcp-open.c
index cb74c50e2c..f5d8f136b1 100644
--- a/deps/uv/test/test-tcp-open.c
+++ b/deps/uv/test/test-tcp-open.c
@@ -181,6 +181,20 @@ TEST_IMPL(tcp_open) {
connect_cb);
ASSERT(r == 0);
+#ifndef _WIN32
+ {
+ uv_tcp_t client2;
+
+ r = uv_tcp_init(uv_default_loop(), &client2);
+ ASSERT(r == 0);
+
+ r = uv_tcp_open(&client2, sock);
+ ASSERT(r == UV_EEXIST);
+
+ uv_close((uv_handle_t*) &client2, NULL);
+ }
+#endif /* !_WIN32 */
+
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(shutdown_cb_called == 1);
diff --git a/deps/uv/test/test-timer-again.c b/deps/uv/test/test-timer-again.c
index f93c509be5..e87d2edf18 100644
--- a/deps/uv/test/test-timer-again.c
+++ b/deps/uv/test/test-timer-again.c
@@ -58,8 +58,8 @@ static void repeat_1_cb(uv_timer_t* handle) {
if (repeat_1_cb_called == 10) {
uv_close((uv_handle_t*)handle, close_cb);
- /* We're not calling uv_timer_again on repeat_2 any more, so after this */
- /* timer_2_cb is expected. */
+ /* We're not calling uv_timer_again on repeat_2 any more, so after this
+ * timer_2_cb is expected. */
repeat_2_cb_allowed = 1;
return;
}
diff --git a/deps/uv/test/test-udp-alloc-cb-fail.c b/deps/uv/test/test-udp-alloc-cb-fail.c
index 05b871e921..0cee09c942 100644
--- a/deps/uv/test/test-udp-alloc-cb-fail.c
+++ b/deps/uv/test/test-udp-alloc-cb-fail.c
@@ -120,8 +120,7 @@ static void sv_recv_cb(uv_udp_t* handle,
}
if (nread == 0) {
- /* Returning unused buffer */
- /* Don't count towards sv_recv_cb_called */
+ /* Returning unused buffer. Don't count towards sv_recv_cb_called */
ASSERT(addr == NULL);
return;
}
diff --git a/deps/uv/test/test-udp-multicast-join.c b/deps/uv/test/test-udp-multicast-join.c
index 6110a8d922..053d2f7914 100644
--- a/deps/uv/test/test-udp-multicast-join.c
+++ b/deps/uv/test/test-udp-multicast-join.c
@@ -81,8 +81,7 @@ static void cl_recv_cb(uv_udp_t* handle,
}
if (nread == 0) {
- /* Returning unused buffer */
- /* Don't count towards cl_recv_cb_called */
+ /* Returning unused buffer. Don't count towards cl_recv_cb_called */
ASSERT(addr == NULL);
return;
}
diff --git a/deps/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c
index cf316e107a..bda5e20ea7 100644
--- a/deps/uv/test/test-udp-multicast-join6.c
+++ b/deps/uv/test/test-udp-multicast-join6.c
@@ -82,8 +82,7 @@ static void cl_recv_cb(uv_udp_t* handle,
}
if (nread == 0) {
- /* Returning unused buffer */
- /* Don't count towards cl_recv_cb_called */
+ /* Returning unused buffer. Don't count towards cl_recv_cb_called */
ASSERT(addr == NULL);
return;
}
diff --git a/deps/uv/test/test-udp-open.c b/deps/uv/test/test-udp-open.c
index 4d77f45d36..ee04c99f61 100644
--- a/deps/uv/test/test-udp-open.c
+++ b/deps/uv/test/test-udp-open.c
@@ -106,8 +106,7 @@ static void recv_cb(uv_udp_t* handle,
}
if (nread == 0) {
- /* Returning unused buffer */
- /* Don't count towards sv_recv_cb_called */
+ /* Returning unused buffer. Don't count towards sv_recv_cb_called */
ASSERT(addr == NULL);
return;
}
@@ -165,6 +164,20 @@ TEST_IMPL(udp_open) {
send_cb);
ASSERT(r == 0);
+#ifndef _WIN32
+ {
+ uv_udp_t client2;
+
+ r = uv_udp_init(uv_default_loop(), &client2);
+ ASSERT(r == 0);
+
+ r = uv_udp_open(&client2, sock);
+ ASSERT(r == UV_EEXIST);
+
+ uv_close((uv_handle_t*) &client2, NULL);
+ }
+#endif /* !_WIN32 */
+
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(send_cb_called == 1);
diff --git a/deps/uv/test/test-udp-options.c b/deps/uv/test/test-udp-options.c
index 8f91367590..d8c9d68d81 100644
--- a/deps/uv/test/test-udp-options.c
+++ b/deps/uv/test/test-udp-options.c
@@ -114,9 +114,11 @@ TEST_IMPL(udp_options6) {
TEST_IMPL(udp_no_autobind) {
uv_loop_t* loop;
uv_udp_t h;
+ uv_udp_t h2;
loop = uv_default_loop();
+ /* Test a lazy initialized socket. */
ASSERT(0 == uv_udp_init(loop, &h));
ASSERT(UV_EBADF == uv_udp_set_multicast_ttl(&h, 32));
ASSERT(UV_EBADF == uv_udp_set_broadcast(&h, 1));
@@ -130,6 +132,23 @@ TEST_IMPL(udp_no_autobind) {
uv_close((uv_handle_t*) &h, NULL);
+ /* Test a non-lazily initialized socket. */
+ ASSERT(0 == uv_udp_init_ex(loop, &h2, AF_INET));
+ ASSERT(0 == uv_udp_set_multicast_ttl(&h2, 32));
+ ASSERT(0 == uv_udp_set_broadcast(&h2, 1));
+
+#if defined(__MVS__)
+ /* zOS only supports setting ttl for IPv6 sockets. */
+ ASSERT(UV_ENOTSUP == uv_udp_set_ttl(&h2, 1));
+#else
+ ASSERT(0 == uv_udp_set_ttl(&h2, 1));
+#endif
+
+ ASSERT(0 == uv_udp_set_multicast_loop(&h2, 1));
+ ASSERT(0 == uv_udp_set_multicast_interface(&h2, "0.0.0.0"));
+
+ uv_close((uv_handle_t*) &h2, NULL);
+
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
MAKE_VALGRIND_HAPPY();
diff --git a/deps/uv/test/test-udp-send-and-recv.c b/deps/uv/test/test-udp-send-and-recv.c
index 633a16727b..1f01188b27 100644
--- a/deps/uv/test/test-udp-send-and-recv.c
+++ b/deps/uv/test/test-udp-send-and-recv.c
@@ -72,8 +72,7 @@ static void cl_recv_cb(uv_udp_t* handle,
}
if (nread == 0) {
- /* Returning unused buffer */
- /* Don't count towards cl_recv_cb_called */
+ /* Returning unused buffer. Don't count towards cl_recv_cb_called */
ASSERT(addr == NULL);
return;
}
@@ -128,8 +127,7 @@ static void sv_recv_cb(uv_udp_t* handle,
}
if (nread == 0) {
- /* Returning unused buffer */
- /* Don't count towards sv_recv_cb_called */
+ /* Returning unused buffer. Don't count towards sv_recv_cb_called */
ASSERT(addr == NULL);
return;
}
diff --git a/deps/uv/test/test-udp-send-immediate.c b/deps/uv/test/test-udp-send-immediate.c
index 215f722572..1011aa467e 100644
--- a/deps/uv/test/test-udp-send-immediate.c
+++ b/deps/uv/test/test-udp-send-immediate.c
@@ -74,8 +74,7 @@ static void sv_recv_cb(uv_udp_t* handle,
}
if (nread == 0) {
- /* Returning unused buffer */
- /* Don't count towards sv_recv_cb_called */
+ /* Returning unused buffer. Don't count towards sv_recv_cb_called */
ASSERT(addr == NULL);
return;
}
diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp
index 480e5a26c4..917533618b 100644
--- a/deps/uv/test/test.gyp
+++ b/deps/uv/test/test.gyp
@@ -47,8 +47,9 @@
'test-hrtime.c',
'test-idle.c',
'test-ip6-addr.c',
- 'test-ipc.c',
+ 'test-ipc-heavy-traffic-deadlock-bug.c',
'test-ipc-send-recv.c',
+ 'test-ipc.c',
'test-list.h',
'test-loop-handles.c',
'test-loop-alive.c',
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index e41f9ff5dc..8aaf541b99 100644
--- a/deps/uv/uv.gyp
+++ b/deps/uv/uv.gyp
@@ -64,10 +64,10 @@
'sources': [
'common.gypi',
'include/uv.h',
- 'include/tree.h',
- 'include/uv-errno.h',
- 'include/uv-threadpool.h',
- 'include/uv-version.h',
+ 'include/uv/tree.h',
+ 'include/uv/errno.h',
+ 'include/uv/threadpool.h',
+ 'include/uv/version.h',
'src/fs-poll.c',
'src/heap-inl.h',
'src/inet.c',
@@ -95,7 +95,7 @@
'_GNU_SOURCE',
],
'sources': [
- 'include/uv-win.h',
+ 'include/uv/win.h',
'src/win/async.c',
'src/win/atomicops-inl.h',
'src/win/core.c',
@@ -144,12 +144,12 @@
},
}, { # Not Windows i.e. POSIX
'sources': [
- 'include/uv-unix.h',
- 'include/uv-linux.h',
- 'include/uv-sunos.h',
- 'include/uv-darwin.h',
- 'include/uv-bsd.h',
- 'include/uv-aix.h',
+ 'include/uv/unix.h',
+ 'include/uv/linux.h',
+ 'include/uv/sunos.h',
+ 'include/uv/darwin.h',
+ 'include/uv/bsd.h',
+ 'include/uv/aix.h',
'src/unix/async.c',
'src/unix/atomic-ops.h',
'src/unix/core.c',
@@ -199,7 +199,7 @@
['uv_library=="shared_library" and OS!="mac" and OS!="zos"', {
# This will cause gyp to set soname
# Must correspond with UV_VERSION_MAJOR
- # in include/uv-version.h
+ # in include/uv/version.h
'product_extension': 'so.1',
}],
],