summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2020-03-11 12:36:48 -0400
committercjihrig <cjihrig@gmail.com>2020-03-14 11:44:25 -0400
commit907bcad8757534b2a3cfe9bf6b8325313f01050d (patch)
tree7736d92d9e677fd31a3ac93311012708753bf1e0 /deps
parentec204d86b06e4cc9259c1308e365a3e104212a16 (diff)
downloadnode-new-907bcad8757534b2a3cfe9bf6b8325313f01050d.tar.gz
deps: upgrade to libuv 1.35.0
Notable changes: - The UV_UDP_MMSG_CHUNK UDP flag has been added. - Support has been dropped for FreeBSD < 10. - The FreeBSD and Linux system call logic has been simplified to assume the presence of features covered by libuv's minimum system requirements. - Listening on IPC pipes is no longer allowed. - Fix iOS and Android builds. PR-URL: https://github.com/nodejs/node/pull/32204 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps')
-rw-r--r--deps/uv/AUTHORS5
-rw-r--r--deps/uv/CMakeLists.txt428
-rw-r--r--deps/uv/CONTRIBUTING.md4
-rw-r--r--deps/uv/ChangeLog101
-rw-r--r--deps/uv/MAINTAINERS.md2
-rw-r--r--deps/uv/Makefile.am1
-rw-r--r--deps/uv/README.md7
-rw-r--r--deps/uv/configure.ac2
-rw-r--r--deps/uv/docs/src/misc.rst9
-rw-r--r--deps/uv/docs/src/pipe.rst6
-rw-r--r--deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpgbin19328 -> 14413 bytes
-rw-r--r--deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpgbin12655 -> 8284 bytes
-rw-r--r--deps/uv/docs/src/tcp.rst5
-rw-r--r--deps/uv/docs/src/udp.rst13
-rw-r--r--deps/uv/include/uv.h8
-rw-r--r--deps/uv/include/uv/version.h4
-rw-r--r--deps/uv/include/uv/win.h2
-rw-r--r--deps/uv/src/timer.c2
-rw-r--r--deps/uv/src/unix/async.c84
-rw-r--r--deps/uv/src/unix/core.c143
-rw-r--r--deps/uv/src/unix/freebsd.c25
-rw-r--r--deps/uv/src/unix/ibmi.c17
-rw-r--r--deps/uv/src/unix/internal.h31
-rw-r--r--deps/uv/src/unix/linux-inotify.c67
-rw-r--r--deps/uv/src/unix/linux-syscalls.c191
-rw-r--r--deps/uv/src/unix/linux-syscalls.h79
-rw-r--r--deps/uv/src/unix/openbsd.c10
-rw-r--r--deps/uv/src/unix/os390-syscalls.c31
-rw-r--r--deps/uv/src/unix/pipe.c6
-rw-r--r--deps/uv/src/unix/process.c78
-rw-r--r--deps/uv/src/unix/proctitle.c65
-rw-r--r--deps/uv/src/unix/signal.c23
-rw-r--r--deps/uv/src/unix/tcp.c12
-rw-r--r--deps/uv/src/unix/udp.c216
-rw-r--r--deps/uv/src/win/pipe.c151
-rw-r--r--deps/uv/src/win/tcp.c23
-rw-r--r--deps/uv/src/win/tty.c337
-rw-r--r--deps/uv/test/benchmark-list.h1
-rw-r--r--deps/uv/test/benchmark-multi-accept.c8
-rw-r--r--deps/uv/test/benchmark-ping-udp.c163
-rw-r--r--deps/uv/test/echo-server.c55
-rw-r--r--deps/uv/test/run-tests.c11
-rw-r--r--deps/uv/test/runner.c19
-rw-r--r--deps/uv/test/test-fs-copyfile.c3
-rw-r--r--deps/uv/test/test-fs-event.c10
-rw-r--r--deps/uv/test/test-fs.c11
-rw-r--r--deps/uv/test/test-get-memory.c11
-rw-r--r--deps/uv/test/test-get-passwd.c2
-rw-r--r--deps/uv/test/test-list.h40
-rw-r--r--deps/uv/test/test-poll.c37
-rw-r--r--deps/uv/test/test-process-title.c59
-rw-r--r--deps/uv/test/test-signal-pending-on-close.c27
-rw-r--r--deps/uv/test/test-spawn.c22
-rw-r--r--deps/uv/test/test-stdio-over-pipes.c135
-rw-r--r--deps/uv/test/test-tty-escape-sequence-processing.c1621
-rw-r--r--deps/uv/test/test-udp-connect.c4
-rw-r--r--deps/uv/test/test-udp-ipv6.c59
-rw-r--r--deps/uv/test/test-watcher-cross-stop.c3
-rw-r--r--deps/uv/test/test.gyp2
-rw-r--r--deps/uv/uv.gyp1
60 files changed, 3390 insertions, 1102 deletions
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index f829778a21..491eded73d 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -413,3 +413,8 @@ Carl Lei <xecycle@gmail.com>
Stefan Bender <stefan.bender@ntnu.no>
nia <nia@NetBSD.org>
virtualyw <virtualyw@gmail.com>
+Witold Kręcicki <wpk@isc.org>
+Dominique Dumont <dod@debian.org>
+Manuel BACHMANN <tarnyko@tarnyko.net>
+Marek Vavrusa <marek@vavrusa.com>
+TK-one <tk5641@naver.com>
diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt
index 2ab6d17edd..03d889cf1d 100644
--- a/deps/uv/CMakeLists.txt
+++ b/deps/uv/CMakeLists.txt
@@ -2,22 +2,55 @@
cmake_minimum_required(VERSION 3.4)
project(libuv LANGUAGES C)
+cmake_policy(SET CMP0057 NEW) # Enable IN_LIST operator
+cmake_policy(SET CMP0064 NEW) # Support if (TEST) operator
+
+list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
+
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
+include(CheckCCompilerFlag)
include(GNUInstallDirs)
include(CTest)
+set(CMAKE_C_VISIBILITY_PRESET hidden)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+set(CMAKE_C_EXTENSIONS ON)
+set(CMAKE_C_STANDARD 90)
+
cmake_dependent_option(LIBUV_BUILD_TESTS
"Build the unit tests when BUILD_TESTING is enabled and we are the root project" ON
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
+cmake_dependent_option(LIBUV_BUILD_BENCH
+ "Build the benchmarks when building unit tests and we are the root project" ON
+ "LIBUV_BUILD_TESTS" OFF)
-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()
+# Compiler check
+string(CONCAT is-msvc $<OR:
+ $<C_COMPILER_ID:MSVC>,
+ $<STREQUAL:${CMAKE_C_COMPILER_FRONTEND_VARIANT},MSVC>
+>)
+
+check_c_compiler_flag(/W4 UV_LINT_W4)
+check_c_compiler_flag(-Wall UV_LINT_WALL) # DO NOT use this under MSVC
+
+# TODO: Place these into its own function
+check_c_compiler_flag(-Wno-unused-parameter UV_LINT_NO_UNUSED_PARAMETER)
+check_c_compiler_flag(-Wstrict-prototypes UV_LINT_STRICT_PROTOTYPES)
+check_c_compiler_flag(-Wextra UV_LINT_EXTRA)
+
+set(lint-no-unused-parameter $<$<BOOL:${UV_LINT_NO_UNUSED_PARAMETER}>:-Wno-unused-parameter>)
+set(lint-strict-prototypes $<$<BOOL:${UV_LINT_STRICT_PROTOTYPES}>:-Wstrict-prototypes>)
+set(lint-extra $<$<BOOL:${UV_LINT_EXTRA}>:-Wextra>)
+set(lint-w4 $<$<BOOL:${UV_LINT_W4}>:/W4>)
+# Unfortunately, this one is complicated because MSVC and clang-cl support -Wall
+# but using it is like calling -Weverything
+string(CONCAT lint-default $<
+ $<AND:$<BOOL:${UV_LINT_WALL}>,$<NOT:${is-msvc}>>:-Wall
+>)
+
+list(APPEND uv_cflags ${lint-strict-prototypes} ${lint-extra} ${lint-default} ${lint-w4})
+list(APPEND uv_cflags ${lint-no-unused-parameter})
set(uv_sources
src/fs-poll.c
@@ -31,172 +64,24 @@ set(uv_sources
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-fs-readdir.c
- test/test-fs-fd-hash.c
- test/test-fs-open-flags.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-gettimeofday.c
- test/test-handle-fileno.c
- test/test-homedir.c
- test/test-hrtime.c
- test/test-idle.c
- test/test-idna.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-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-priority.c
- test/test-process-title-threadsafe.c
- test/test-process-title.c
- test/test-queue-foreach-delete.c
- test/test-random.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-pending-on-close.c
- test/test-signal.c
- test/test-socket-buffer-size.c
- test/test-spawn.c
- test/test-stdio-over-pipes.c
- test/test-strscpy.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-close-reset.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-try-write-error.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-duplicate-key.c
- test/test-tty.c
- test/test-udp-alloc-cb-fail.c
- test/test-udp-bind.c
- test/test-udp-connect.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-uname.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)
+ if (CMAKE_SYSTEM_VERSION VERSION_GREATER 10) # Windows 10
+ set(windows-version 0x0A00)
+ elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.3) # Windows 8.1
+ set(windows-version 0x0603)
+ elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.2) # Windows 8
+ set(windows-version 0x0602)
+ elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.1) # Windows 7
+ set(windows-version 0x0601)
+ elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.0) # Windows Vista
+ set(windows-version 0x0600)
+ else()
+ message(FATAL_ERROR "Windows Vista is the minimum version supported")
+ endif()
+ list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=${windows-version})
list(APPEND uv_libraries
- advapi32
+ $<$<STREQUAL:${windows-version},0x0600>:psapi>
iphlpapi
- psapi
- shell32
- user32
userenv
ws2_32)
list(APPEND uv_sources
@@ -230,6 +115,7 @@ if(WIN32)
else()
list(APPEND uv_defines _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE)
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
+ # TODO: This should be replaced with find_package(Threads) if possible
# Android has pthread as part of its c library, not as a separate
# libpthread.so.
list(APPEND uv_libraries pthread)
@@ -275,6 +161,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
src/unix/linux-syscalls.c
src/unix/procfs-exepath.c
src/unix/pthread-fixes.c
+ src/unix/random-getentropy.c
src/unix/random-getrandom.c
src/unix/random-sysctl-linux.c
src/unix/sysinfo-loadavg.c)
@@ -367,19 +254,191 @@ endif()
add_library(uv SHARED ${uv_sources})
target_compile_definitions(uv
- INTERFACE USING_UV_SHARED=1
- PRIVATE ${uv_defines} BUILDING_UV_SHARED=1)
+ INTERFACE
+ USING_UV_SHARED=1
+ PRIVATE
+ BUILDING_UV_SHARED=1
+ ${uv_defines})
target_compile_options(uv PRIVATE ${uv_cflags})
-target_include_directories(uv PUBLIC include PRIVATE src)
+target_include_directories(uv
+ PUBLIC
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ PRIVATE
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/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 PUBLIC include PRIVATE src)
+target_include_directories(uv_a
+ PUBLIC
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ PRIVATE
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
target_link_libraries(uv_a ${uv_libraries})
if(LIBUV_BUILD_TESTS)
+ list(APPEND 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-fs-readdir.c
+ test/test-fs-fd-hash.c
+ test/test-fs-open-flags.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-gettimeofday.c
+ test/test-handle-fileno.c
+ test/test-homedir.c
+ test/test-hrtime.c
+ test/test-idle.c
+ test/test-idna.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-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-priority.c
+ test/test-process-title-threadsafe.c
+ test/test-process-title.c
+ test/test-queue-foreach-delete.c
+ test/test-random.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-pending-on-close.c
+ test/test-signal.c
+ test/test-socket-buffer-size.c
+ test/test-spawn.c
+ test/test-stdio-over-pipes.c
+ test/test-strscpy.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-close-reset.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-try-write-error.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-duplicate-key.c
+ test/test-tty-escape-sequence-processing.c
+ test/test-tty.c
+ test/test-udp-alloc-cb-fail.c
+ test/test-udp-bind.c
+ test/test-udp-connect.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-uname.c
+ test/test-walk-handles.c
+ test/test-watcher-cross-stop.c)
+
add_executable(uv_run_tests ${uv_test_sources})
target_compile_definitions(uv_run_tests
PRIVATE ${uv_defines} USING_UV_SHARED=1)
@@ -399,23 +458,26 @@ endif()
if(UNIX)
# Now for some gibbering horrors from beyond the stars...
- foreach(x ${uv_libraries})
- set(LIBS "${LIBS} -l${x}")
- endforeach(x)
+ foreach(lib IN LISTS uv_libraries)
+ list(APPEND LIBS "-l${lib}")
+ endforeach()
+ string(REPLACE ";" " " LIBS "${LIBS}")
+ # Consider setting project version via project() call?
file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
- string(REGEX MATCH [0-9]+[.][0-9]+[.][0-9]+ PACKAGE_VERSION "${configure_ac}")
- string(REGEX MATCH ^[0-9]+ UV_VERSION_MAJOR "${PACKAGE_VERSION}")
+ string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}")
+ set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}")
# The version in the filename is mirroring the behaviour of autotools.
- set_target_properties(uv PROPERTIES VERSION ${UV_VERSION_MAJOR}.0.0
- SOVERSION ${UV_VERSION_MAJOR})
+ set_target_properties(uv PROPERTIES
+ VERSION ${UV_VERSION_MAJOR}.0.0
+ SOVERSION ${UV_VERSION_MAJOR})
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)
+ configure_file(libuv.pc.in libuv.pc @ONLY)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc
+ install(FILES ${PROJECT_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})
diff --git a/deps/uv/CONTRIBUTING.md b/deps/uv/CONTRIBUTING.md
index f22e124e3b..6f8c45affb 100644
--- a/deps/uv/CONTRIBUTING.md
+++ b/deps/uv/CONTRIBUTING.md
@@ -48,11 +48,11 @@ the [Google C/C++ style guide]. Some of the key points, as well as some
additional guidelines, are enumerated below.
* Code that is specific to unix-y platforms should be placed in `src/unix`, and
- declarations go into `include/uv-unix.h`.
+ declarations go into `include/uv/unix.h`.
* Source code that is Windows-specific goes into `src/win`, and related
publicly exported types, functions and macro declarations should generally
- be declared in `include/uv-win.h`.
+ be declared in `include/uv/win.h`.
* Names should be descriptive and concise.
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index 9c2146dab9..f45ba985e5 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,3 +1,104 @@
+2020.03.12, Version 1.35.0 (Stable), e45f1ec38db882f8dc17b51f51a6684027034609
+
+Changes since version 1.34.2:
+
+* src: android build fix (David Carlier)
+
+* build: make code compilable for iOS on Xcode (ssrlive)
+
+* ibmi: skip unsupported fs test cases (Xu Meng)
+
+* ibmi: ensure that pipe backlog is not zero (Xu Meng)
+
+* test,udp6: fix udp_ipv6 test flakiness (Jameson Nash)
+
+* test: fix fs_event_watch_dir_recursive flakiness (Santiago Gimeno)
+
+* pipe: disallow listening on an IPC pipe (Witold Kręcicki)
+
+* build,cmake: improve buil experience (Isabella Muerte)
+
+* unix: remove support for FreeBSD < 10 (Saúl Ibarra Corretgé)
+
+* linux: simplify uv__accept() (Ben Noordhuis)
+
+* linux: assume presence of SOCK_CLOEXEC flag (Ben Noordhuis)
+
+* linux: simplify uv__dup2_cloexec() (Ben Noordhuis)
+
+* freebsd,linux: simplify uv__make_socketpair() (Ben Noordhuis)
+
+* unix: fix error handling in uv__make_socketpair() (Ben Noordhuis)
+
+* freebsd,linux: simplify uv__make_pipe() (Ben Noordhuis)
+
+* unix: fix error handling in uv__make_pipe() (Ben Noordhuis)
+
+* linux: simplify uv__async_eventfd() (Ben Noordhuis)
+
+* linux: assume the presence of inotify system calls (Ben Noordhuis)
+
+* doc: strip ICC profile from 2 jpg files (Dominique Dumont)
+
+* unix: make uv_tcp_keepalive predictable (Manuel BACHMANN)
+
+* docs: uv_setup_args() may take ownership of argv (Ben Noordhuis)
+
+* unix: fix error path in uv_setup_args() (Ben Noordhuis)
+
+* unix: fix size check in uv_get_process_title() (Ben Noordhuis)
+
+* doc: add erw7 to maintainers (erw7)
+
+* test: fixed udp4_echo_server implementation (Marek Vavrusa)
+
+* test: added udp ping benchmark (1,10,100 pingers) (Marek Vavrusa)
+
+* freebsd,linux: add recvmmsg() + sendmmsg() udp implementation (Marek Vavrusa)
+
+* win,pipe: DRY/simplify some code paths (Jameson Nash)
+
+* win: address some style nits (Jameson Nash)
+
+* win,pipe: ensure `req->event_handle` is defined (Elliot Saba)
+
+* win,pipe: consolidate overlapped initialization (Elliot Saba)
+
+* win,pipe: erase event_handle after deleting pointer (Jameson Nash)
+
+* build: fix android cmake build, build missing file (Ben Noordhuis)
+
+* test: skip some UDP tests on IBMi (Xu Meng)
+
+* test: skip some spawn test cases on IBMi (Xu Meng)
+
+* src: fix wrong method name in comment (TK-one)
+
+* test: add UV_TIMEOUT_MULTIPLIER environment var (Ben Noordhuis)
+
+* unix: fix uv_cpu_info always returning UV_ENOTDIR on OpenBSD (Ben Davies)
+
+* test: skip the pwd_shell test on IBMi (Xu Meng)
+
+* win,tty: Change to restore cursor shape with uv_tty_reset() (erw7)
+
+* win,tty: Added set cursor style to CSI sequences (erw7)
+
+* test: handle EINTR, fix EOF check in poll test (Ben Noordhuis)
+
+* unix: use socklen_t instead of size_t (Ben Noordhuis)
+
+* doc: fix header file location (TK-one)
+
+* unix: fix signal handle closing deferral (Ben Noordhuis)
+
+* ibmi: set the amount of memory in use to zero (Xu Meng)
+
+* zos: return on realloc failure in scandir() (Milad Farazmand)
+
+* zos: fix scandir() error path NULL pointer deref (Ben Noordhuis)
+
+
2020.01.24, Version 1.34.2 (Stable), f868c9ab0c307525a16fff99fd21e32a6ebc3837
Changes since version 1.34.1:
diff --git a/deps/uv/MAINTAINERS.md b/deps/uv/MAINTAINERS.md
index 0870b88eb6..268251e615 100644
--- a/deps/uv/MAINTAINERS.md
+++ b/deps/uv/MAINTAINERS.md
@@ -17,6 +17,8 @@ libuv is currently managed by the following individuals:
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
* **Jameson Nash** ([@vtjnash](https://github.com/vtjnash))
* **John Barboza** ([@jbarz](https://github.com/jbarz))
+* **Kaoru Takanashi** ([@erw7](https://github.com/erw7))
+ - GPG Key: 5804 F999 8A92 2AFB A398 47A0 7183 5090 6134 887F (pubkey-erw7)
* **Richard Lau** ([@richardlau](https://github.com/richardlau))
- GPG key: C82F A3AE 1CBE DC6B E46B 9360 C43C EC45 C17A B93C (pubkey-richardlau)
* **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno))
diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am
index 9a06b9ce4a..68bef4c507 100644
--- a/deps/uv/Makefile.am
+++ b/deps/uv/Makefile.am
@@ -286,6 +286,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-timer.c \
test/test-tmpdir.c \
test/test-tty-duplicate-key.c \
+ test/test-tty-escape-sequence-processing.c \
test/test-tty.c \
test/test-udp-alloc-cb-fail.c \
test/test-udp-bind.c \
diff --git a/deps/uv/README.md b/deps/uv/README.md
index c040b4c18c..9c785da842 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -347,6 +347,13 @@ $ make -C out
$ ./out/Debug/run-tests
```
+Some tests are timing sensitive. Relaxing test timeouts may be necessary
+on slow or overloaded machines:
+
+```bash
+$ env UV_TEST_TIMEOUT_MULTIPLIER=2 ./out/Debug/run-tests # 10s instead of 5s
+```
+
#### Run one test
The list of all tests is in `test/test-list.h`.
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index fba960b6b3..d05ec8726b 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.34.2], [https://github.com/libuv/libuv/issues])
+AC_INIT([libuv], [1.35.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/misc.rst b/deps/uv/docs/src/misc.rst
index 7cfac85f57..d9bf3aef01 100644
--- a/deps/uv/docs/src/misc.rst
+++ b/deps/uv/docs/src/misc.rst
@@ -244,6 +244,15 @@ API
.. c:function:: char** uv_setup_args(int argc, char** argv)
Store the program arguments. Required for getting / setting the process title.
+ Libuv may take ownership of the memory that `argv` points to. This function
+ should be called exactly once, at program start-up.
+
+ Example:
+
+ ::
+
+ argv = uv_setup_args(argc, argv); /* May return a copy of argv. */
+
.. c:function:: int uv_get_process_title(char* buffer, size_t size)
diff --git a/deps/uv/docs/src/pipe.rst b/deps/uv/docs/src/pipe.rst
index 5eac1b6df4..6437a9d994 100644
--- a/deps/uv/docs/src/pipe.rst
+++ b/deps/uv/docs/src/pipe.rst
@@ -24,6 +24,8 @@ Public members
.. c:member:: int uv_pipe_t.ipc
Whether this pipe is suitable for handle passing between processes.
+ Only a connected pipe that will be passing the handles should have this flag
+ set, not the listening pipe that uv_accept is called on.
.. seealso:: The :c:type:`uv_stream_t` members also apply.
@@ -35,7 +37,9 @@ API
Initialize a pipe handle. The `ipc` argument is a boolean to indicate if
this pipe will be used for handle passing between processes (which may
- change the bytes on the wire).
+ change the bytes on the wire). Only a connected pipe that will be
+ passing the handles should have this flag set, not the listening pipe
+ that uv_accept is called on.
.. c:function:: int uv_pipe_open(uv_pipe_t* handle, uv_file file)
diff --git a/deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpg b/deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpg
index 439f581093..08f23a90b6 100644
--- a/deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpg
+++ b/deps/uv/docs/src/static/diagrams.key/Data/st0-311.jpg
Binary files differ
diff --git a/deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpg b/deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpg
index ffb21ff224..26e676a71a 100644
--- a/deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpg
+++ b/deps/uv/docs/src/static/diagrams.key/Data/st1-475.jpg
Binary files differ
diff --git a/deps/uv/docs/src/tcp.rst b/deps/uv/docs/src/tcp.rst
index bcb163ea0f..3cc8efaac1 100644
--- a/deps/uv/docs/src/tcp.rst
+++ b/deps/uv/docs/src/tcp.rst
@@ -60,6 +60,11 @@ API
Enable / disable TCP keep-alive. `delay` is the initial delay in seconds,
ignored when `enable` is zero.
+ After `delay` has been reached, 10 successive probes, each spaced 1 second
+ from the previous one, will still happen. If the connection is still lost
+ at the end of this procedure, then the handle is destroyed with a
+ ``UV_ETIMEDOUT`` error passed to the corresponding callback.
+
.. c:function:: int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable)
Enable / disable simultaneous asynchronous accept requests that are
diff --git a/deps/uv/docs/src/udp.rst b/deps/uv/docs/src/udp.rst
index 53b1fea493..2ca0736bc6 100644
--- a/deps/uv/docs/src/udp.rst
+++ b/deps/uv/docs/src/udp.rst
@@ -42,6 +42,12 @@ Data types
* any traffic, in effect "stealing" the port from the previous listener.
*/
UV_UDP_REUSEADDR = 4
+ /*
+ * Indicates that the message was received by recvmmsg and that it's not at
+ * the beginning of the buffer allocated by alloc_cb - so the buffer provided
+ * must not be freed by the recv_cb callback.
+ */
+ UV_UDP_MMSG_CHUNK = 8
};
.. c:type:: void (*uv_udp_send_cb)(uv_udp_send_t* req, int status)
@@ -62,12 +68,13 @@ Data types
* `buf`: :c:type:`uv_buf_t` with the received data.
* `addr`: ``struct sockaddr*`` containing the address of the sender.
Can be NULL. Valid for the duration of the callback only.
- * `flags`: One or more or'ed UV_UDP_* constants. Right now only
- ``UV_UDP_PARTIAL`` is used.
+ * `flags`: One or more or'ed UV_UDP_* constants.
The callee is responsible for freeing the buffer, libuv does not reuse it.
The buffer may be a null buffer (where `buf->base` == NULL and `buf->len` == 0)
- on error.
+ on error. Don't free the buffer when the UV_UDP_MMSG_CHUNK flag is set.
+ The final callback receives the whole buffer (containing the first chunk)
+ with the UV_UDP_MMSG_CHUNK flag cleared.
.. note::
The receive callback will be called with `nread` == 0 and `addr` == NULL when there is
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index 626cebabd8..defc0ac44b 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -605,7 +605,13 @@ enum uv_udp_flags {
* (provided they all set the flag) but only the last one to bind will receive
* any traffic, in effect "stealing" the port from the previous listener.
*/
- UV_UDP_REUSEADDR = 4
+ UV_UDP_REUSEADDR = 4,
+ /*
+ * Indicates that the message was received by recvmmsg and that it's not at
+ * the beginning of the buffer allocated by alloc_cb - so the buffer provided
+ * must not be freed by the recv_cb callback.
+ */
+ UV_UDP_MMSG_CHUNK = 8
};
typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h
index 623ca3ef2c..78a2115bb0 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 34
-#define UV_VERSION_PATCH 2
+#define UV_VERSION_MINOR 35
+#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 9793eee3e1..f5f1d3a3cc 100644
--- a/deps/uv/include/uv/win.h
+++ b/deps/uv/include/uv/win.h
@@ -517,7 +517,7 @@ typedef struct {
/* eol conversion state */ \
unsigned char previous_eol; \
/* ansi parser state */ \
- unsigned char ansi_parser_state; \
+ unsigned short ansi_parser_state; \
unsigned char ansi_csi_argc; \
unsigned short ansi_csi_argv[4]; \
COORD saved_position; \
diff --git a/deps/uv/src/timer.c b/deps/uv/src/timer.c
index 8fce7f6472..9da513fc0c 100644
--- a/deps/uv/src/timer.c
+++ b/deps/uv/src/timer.c
@@ -87,7 +87,7 @@ int uv_timer_start(uv_timer_t* handle,
handle->timer_cb = cb;
handle->timeout = clamped_timeout;
handle->repeat = repeat;
- /* start_id is the second index to be compared in uv__timer_cmp() */
+ /* start_id is the second index to be compared in timer_less_than() */
handle->start_id = handle->loop->timer_counter++;
heap_insert(timer_heap(handle->loop),
diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c
index a5c47bca05..26d337e0a4 100644
--- a/deps/uv/src/unix/async.c
+++ b/deps/uv/src/unix/async.c
@@ -33,9 +33,12 @@
#include <string.h>
#include <unistd.h>
+#ifdef __linux__
+#include <sys/eventfd.h>
+#endif
+
static void uv__async_send(uv_loop_t* loop);
static int uv__async_start(uv_loop_t* loop);
-static int uv__async_eventfd(void);
int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
@@ -190,36 +193,18 @@ static int uv__async_start(uv_loop_t* loop) {
if (loop->async_io_watcher.fd != -1)
return 0;
- err = uv__async_eventfd();
- if (err >= 0) {
- pipefd[0] = err;
- pipefd[1] = -1;
- }
- else if (err == UV_ENOSYS) {
- err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
-#if defined(__linux__)
- /* Save a file descriptor by opening one of the pipe descriptors as
- * read/write through the procfs. That file descriptor can then
- * function as both ends of the pipe.
- */
- if (err == 0) {
- char buf[32];
- int fd;
-
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", pipefd[0]);
- fd = uv__open_cloexec(buf, O_RDWR);
- if (fd >= 0) {
- uv__close(pipefd[0]);
- uv__close(pipefd[1]);
- pipefd[0] = fd;
- pipefd[1] = fd;
- }
- }
-#endif
- }
+#ifdef __linux__
+ err = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
+ if (err < 0)
+ return UV__ERR(errno);
+ pipefd[0] = err;
+ pipefd[1] = -1;
+#else
+ err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
if (err < 0)
return err;
+#endif
uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]);
uv__io_start(loop, &loop->async_io_watcher, POLLIN);
@@ -253,46 +238,3 @@ void uv__async_stop(uv_loop_t* loop) {
uv__close(loop->async_io_watcher.fd);
loop->async_io_watcher.fd = -1;
}
-
-
-static int uv__async_eventfd(void) {
-#if defined(__linux__)
- static int no_eventfd2;
- static int no_eventfd;
- int fd;
-
- if (no_eventfd2)
- goto skip_eventfd2;
-
- fd = uv__eventfd2(0, UV__EFD_CLOEXEC | UV__EFD_NONBLOCK);
- if (fd != -1)
- return fd;
-
- if (errno != ENOSYS)
- return UV__ERR(errno);
-
- no_eventfd2 = 1;
-
-skip_eventfd2:
-
- if (no_eventfd)
- goto skip_eventfd;
-
- fd = uv__eventfd(0);
- if (fd != -1) {
- uv__cloexec(fd, 1);
- uv__nonblock(fd, 1);
- return fd;
- }
-
- if (errno != ENOSYS)
- return UV__ERR(errno);
-
- no_eventfd = 1;
-
-skip_eventfd:
-
-#endif
-
- return UV_ENOSYS;
-}
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 04999dce36..6d0063513c 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -71,20 +71,12 @@ extern char** environ;
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
-# if defined(__FreeBSD__) && __FreeBSD__ >= 10
+# if defined(__FreeBSD__) || defined(__linux__)
# define uv__accept4 accept4
# endif
# if defined(__NetBSD__)
# define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d))
# endif
-# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
- defined(__NetBSD__) || defined(__OpenBSD__)
-# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
-# define UV__SOCK_CLOEXEC SOCK_CLOEXEC
-# endif
-# if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC)
-# define F_DUP2FD_CLOEXEC _F_DUP2FD_CLOEXEC
-# endif
#endif
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
@@ -179,9 +171,7 @@ 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. */
- return;
+ break;
default:
assert(0);
@@ -246,6 +236,8 @@ int uv__getiovmax(void) {
static void uv__finish_close(uv_handle_t* handle) {
+ uv_signal_t* sh;
+
/* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still
* possible for it to be active in the sense that uv__is_active() returns
* true.
@@ -268,7 +260,20 @@ static void uv__finish_close(uv_handle_t* handle) {
case UV_FS_EVENT:
case UV_FS_POLL:
case UV_POLL:
+ break;
+
case UV_SIGNAL:
+ /* If there are any caught signals "trapped" in the signal pipe,
+ * we can't call the close callback yet. Reinserting the handle
+ * into the closing queue makes the event loop spin but that's
+ * okay because we only need to deliver the pending events.
+ */
+ sh = (uv_signal_t*) handle;
+ if (sh->caught_signals > sh->dispatched_signals) {
+ handle->flags ^= UV_HANDLE_CLOSED;
+ uv__make_close_pending(handle); /* Back into the queue. */
+ return;
+ }
break;
case UV_NAMED_PIPE:
@@ -472,52 +477,32 @@ int uv__accept(int sockfd) {
int peerfd;
int err;
+ (void) &err;
assert(sockfd >= 0);
- while (1) {
-#if defined(__linux__) || \
- (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
- defined(__NetBSD__)
- static int no_accept4;
-
- if (no_accept4)
- goto skip;
-
- peerfd = uv__accept4(sockfd,
- NULL,
- NULL,
- UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC);
- if (peerfd != -1)
- return peerfd;
-
- if (errno == EINTR)
- continue;
-
- if (errno != ENOSYS)
- return UV__ERR(errno);
-
- no_accept4 = 1;
-skip:
-#endif
-
+ do
+#ifdef uv__accept4
+ peerfd = uv__accept4(sockfd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+#else
peerfd = accept(sockfd, NULL, NULL);
- if (peerfd == -1) {
- if (errno == EINTR)
- continue;
- return UV__ERR(errno);
- }
+#endif
+ while (peerfd == -1 && errno == EINTR);
- err = uv__cloexec(peerfd, 1);
- if (err == 0)
- err = uv__nonblock(peerfd, 1);
+ if (peerfd == -1)
+ return UV__ERR(errno);
- if (err) {
- uv__close(peerfd);
- return err;
- }
+#ifndef uv__accept4
+ err = uv__cloexec(peerfd, 1);
+ if (err == 0)
+ err = uv__nonblock(peerfd, 1);
- return peerfd;
+ if (err != 0) {
+ uv__close(peerfd);
+ return err;
}
+#endif
+
+ return peerfd;
}
@@ -533,7 +518,7 @@ int uv__close_nocancel(int fd) {
#if defined(__APPLE__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
-#if defined(__LP64__)
+#if defined(__LP64__) || defined(TARGET_OS_IPHONE)
extern int close$NOCANCEL(int);
return close$NOCANCEL(fd);
#else
@@ -1031,54 +1016,30 @@ int uv__open_cloexec(const char* path, int flags) {
int uv__dup2_cloexec(int oldfd, int newfd) {
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__)
int r;
-#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
+
r = dup3(oldfd, newfd, O_CLOEXEC);
if (r == -1)
return UV__ERR(errno);
+
return r;
-#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
- r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
- if (r != -1)
- return r;
- if (errno != EINVAL)
- return UV__ERR(errno);
- /* Fall through. */
-#elif defined(__linux__)
- static int no_dup3;
- if (!no_dup3) {
- do
- r = uv__dup3(oldfd, newfd, O_CLOEXEC);
- while (r == -1 && errno == EBUSY);
- if (r != -1)
- return r;
- if (errno != ENOSYS)
- return UV__ERR(errno);
- /* Fall through. */
- no_dup3 = 1;
- }
-#endif
- {
- int err;
- do
- r = dup2(oldfd, newfd);
-#if defined(__linux__)
- while (r == -1 && errno == EBUSY);
#else
- while (0); /* Never retry. */
-#endif
-
- if (r == -1)
- return UV__ERR(errno);
+ int err;
+ int r;
- err = uv__cloexec(newfd, 1);
- if (err) {
- uv__close(newfd);
- return err;
- }
+ r = dup2(oldfd, newfd); /* Never retry. */
+ if (r == -1)
+ return UV__ERR(errno);
- return r;
+ err = uv__cloexec(newfd, 1);
+ if (err != 0) {
+ uv__close(newfd);
+ return err;
}
+
+ return r;
+#endif
}
diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c
index 57bd04e240..ef77e127c2 100644
--- a/deps/uv/src/unix/freebsd.c
+++ b/deps/uv/src/unix/freebsd.c
@@ -288,3 +288,28 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uv__free(cp_times);
return 0;
}
+
+
+int uv__sendmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags) {
+#if __FreeBSD__ >= 11
+ return sendmmsg(fd, mmsg, vlen, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__recvmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags,
+ struct timespec* timeout) {
+#if __FreeBSD__ >= 11
+ return recvmmsg(fd, mmsg, vlen, flags, timeout);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
diff --git a/deps/uv/src/unix/ibmi.c b/deps/uv/src/unix/ibmi.c
index 4dd8bb6e37..ff300ea5f8 100644
--- a/deps/uv/src/unix/ibmi.c
+++ b/deps/uv/src/unix/ibmi.c
@@ -225,22 +225,7 @@ uint64_t uv_get_free_memory(void) {
if (get_ibmi_system_status(&rcvr))
return 0;
- /* The amount of main storage, in kilobytes, in the system. */
- uint64_t main_storage_size = rcvr.main_storage_size;
-
- /* The current amount of storage in use for temporary objects.
- * in millions (M) of bytes.
- */
- uint64_t current_unprotected_storage_used =
- rcvr.current_unprotected_storage_used * 1024ULL;
-
- /* Current unprotected storage includes the storage used for memory
- * and disks so it is possible to exceed the amount of main storage.
- */
- if (main_storage_size <= current_unprotected_storage_used)
- return 0ULL;
-
- return (main_storage_size - current_unprotected_storage_used) * 1024ULL;
+ return (uint64_t)rcvr.main_storage_size * 1024ULL;
}
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 47f220000d..598554b607 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -28,9 +28,10 @@
#include <limits.h> /* _POSIX_PATH_MAX, PATH_MAX */
#include <stdlib.h> /* abort */
#include <string.h> /* strrchr */
-#include <fcntl.h> /* O_CLOEXEC, may be */
+#include <fcntl.h> /* O_CLOEXEC and O_NONBLOCK, if supported. */
#include <stdio.h>
#include <errno.h>
+#include <sys/socket.h>
#if defined(__STRICT_ANSI__)
# define inline __inline
@@ -284,13 +285,12 @@ int uv___stream_fd(const uv_stream_t* handle);
#define uv__stream_fd(handle) ((handle)->io_watcher.fd)
#endif /* defined(__APPLE__) */
-#ifdef UV__O_NONBLOCK
-# define UV__F_NONBLOCK UV__O_NONBLOCK
+#ifdef O_NONBLOCK
+# define UV__F_NONBLOCK O_NONBLOCK
#else
# define UV__F_NONBLOCK 1
#endif
-int uv__make_socketpair(int fds[2], int flags);
int uv__make_pipe(int fds[2], int flags);
#if defined(__APPLE__)
@@ -328,4 +328,27 @@ int uv__getsockpeername(const uv_handle_t* handle,
struct sockaddr* name,
int* namelen);
+#if defined(__linux__) || \
+ defined(__FreeBSD__) || \
+ defined(__FreeBSD_kernel__)
+#define HAVE_MMSG 1
+struct uv__mmsghdr {
+ struct msghdr msg_hdr;
+ unsigned int msg_len;
+};
+
+int uv__recvmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags,
+ struct timespec* timeout);
+int uv__sendmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags);
+#else
+#define HAVE_MMSG 0
+#endif
+
+
#endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c
index 9b26202fb3..42b601adbf 100644
--- a/deps/uv/src/unix/linux-inotify.c
+++ b/deps/uv/src/unix/linux-inotify.c
@@ -29,6 +29,7 @@
#include <assert.h>
#include <errno.h>
+#include <sys/inotify.h>
#include <sys/types.h>
#include <unistd.h>
@@ -64,45 +65,17 @@ static void uv__inotify_read(uv_loop_t* loop,
static void maybe_free_watcher_list(struct watcher_list* w,
uv_loop_t* loop);
-static int new_inotify_fd(void) {
- int err;
- int fd;
-
- fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC);
- if (fd != -1)
- return fd;
-
- if (errno != ENOSYS)
- return UV__ERR(errno);
-
- fd = uv__inotify_init();
- if (fd == -1)
- return UV__ERR(errno);
-
- err = uv__cloexec(fd, 1);
- if (err == 0)
- err = uv__nonblock(fd, 1);
-
- if (err) {
- uv__close(fd);
- return err;
- }
-
- return fd;
-}
-
-
static int init_inotify(uv_loop_t* loop) {
- int err;
+ int fd;
if (loop->inotify_fd != -1)
return 0;
- err = new_inotify_fd();
- if (err < 0)
- return err;
+ fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ if (fd < 0)
+ return UV__ERR(errno);
- loop->inotify_fd = err;
+ loop->inotify_fd = fd;
uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd);
uv__io_start(loop, &loop->inotify_read_watcher, POLLIN);
@@ -186,7 +159,7 @@ static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) {
if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) {
/* No watchers left for this path. Clean up. */
RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w);
- uv__inotify_rm_watch(loop->inotify_fd, w->wd);
+ inotify_rm_watch(loop->inotify_fd, w->wd);
uv__free(w);
}
}
@@ -194,7 +167,7 @@ static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) {
static void uv__inotify_read(uv_loop_t* loop,
uv__io_t* dummy,
unsigned int events) {
- const struct uv__inotify_event* e;
+ const struct inotify_event* e;
struct watcher_list* w;
uv_fs_event_t* h;
QUEUE queue;
@@ -219,12 +192,12 @@ static void uv__inotify_read(uv_loop_t* loop,
/* Now we have one or more inotify_event structs. */
for (p = buf; p < buf + size; p += sizeof(*e) + e->len) {
- e = (const struct uv__inotify_event*)p;
+ e = (const struct inotify_event*) p;
events = 0;
- if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY))
+ if (e->mask & (IN_ATTRIB|IN_MODIFY))
events |= UV_CHANGE;
- if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY))
+ if (e->mask & ~(IN_ATTRIB|IN_MODIFY))
events |= UV_RENAME;
w = find_watcher(loop, e->wd);
@@ -290,16 +263,16 @@ int uv_fs_event_start(uv_fs_event_t* handle,
if (err)
return err;
- events = UV__IN_ATTRIB
- | UV__IN_CREATE
- | UV__IN_MODIFY
- | UV__IN_DELETE
- | UV__IN_DELETE_SELF
- | UV__IN_MOVE_SELF
- | UV__IN_MOVED_FROM
- | UV__IN_MOVED_TO;
+ events = IN_ATTRIB
+ | IN_CREATE
+ | IN_MODIFY
+ | IN_DELETE
+ | IN_DELETE_SELF
+ | IN_MOVE_SELF
+ | IN_MOVED_FROM
+ | IN_MOVED_TO;
- wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events);
+ wd = inotify_add_watch(handle->loop->inotify_fd, path, events);
if (wd == -1)
return UV__ERR(errno);
diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c
index 950387860f..742f26ada8 100644
--- a/deps/uv/src/unix/linux-syscalls.c
+++ b/deps/uv/src/unix/linux-syscalls.c
@@ -26,19 +26,6 @@
#include <sys/types.h>
#include <errno.h>
-#if defined(__has_feature)
-# if __has_feature(memory_sanitizer)
-# define MSAN_ACTIVE 1
-# include <sanitizer/msan_interface.h>
-# endif
-#endif
-
-#if defined(__i386__)
-# ifndef __NR_socketcall
-# define __NR_socketcall 102
-# endif
-#endif
-
#if defined(__arm__)
# if defined(__thumb__) || defined(__ARM_EABI__)
# define UV_SYSCALL_BASE 0
@@ -47,86 +34,6 @@
# endif
#endif /* __arm__ */
-#ifndef __NR_accept4
-# if defined(__x86_64__)
-# define __NR_accept4 288
-# elif defined(__i386__)
- /* Nothing. Handled through socketcall(). */
-# elif defined(__arm__)
-# define __NR_accept4 (UV_SYSCALL_BASE + 366)
-# endif
-#endif /* __NR_accept4 */
-
-#ifndef __NR_eventfd
-# if defined(__x86_64__)
-# define __NR_eventfd 284
-# elif defined(__i386__)
-# define __NR_eventfd 323
-# elif defined(__arm__)
-# define __NR_eventfd (UV_SYSCALL_BASE + 351)
-# endif
-#endif /* __NR_eventfd */
-
-#ifndef __NR_eventfd2
-# if defined(__x86_64__)
-# define __NR_eventfd2 290
-# elif defined(__i386__)
-# define __NR_eventfd2 328
-# elif defined(__arm__)
-# define __NR_eventfd2 (UV_SYSCALL_BASE + 356)
-# endif
-#endif /* __NR_eventfd2 */
-
-#ifndef __NR_inotify_init
-# if defined(__x86_64__)
-# define __NR_inotify_init 253
-# elif defined(__i386__)
-# define __NR_inotify_init 291
-# elif defined(__arm__)
-# define __NR_inotify_init (UV_SYSCALL_BASE + 316)
-# endif
-#endif /* __NR_inotify_init */
-
-#ifndef __NR_inotify_init1
-# if defined(__x86_64__)
-# define __NR_inotify_init1 294
-# elif defined(__i386__)
-# define __NR_inotify_init1 332
-# elif defined(__arm__)
-# define __NR_inotify_init1 (UV_SYSCALL_BASE + 360)
-# endif
-#endif /* __NR_inotify_init1 */
-
-#ifndef __NR_inotify_add_watch
-# if defined(__x86_64__)
-# define __NR_inotify_add_watch 254
-# elif defined(__i386__)
-# define __NR_inotify_add_watch 292
-# elif defined(__arm__)
-# define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317)
-# endif
-#endif /* __NR_inotify_add_watch */
-
-#ifndef __NR_inotify_rm_watch
-# if defined(__x86_64__)
-# define __NR_inotify_rm_watch 255
-# elif defined(__i386__)
-# define __NR_inotify_rm_watch 293
-# elif defined(__arm__)
-# define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318)
-# endif
-#endif /* __NR_inotify_rm_watch */
-
-#ifndef __NR_pipe2
-# if defined(__x86_64__)
-# define __NR_pipe2 293
-# elif defined(__i386__)
-# define __NR_pipe2 331
-# elif defined(__arm__)
-# define __NR_pipe2 (UV_SYSCALL_BASE + 359)
-# endif
-#endif /* __NR_pipe2 */
-
#ifndef __NR_recvmmsg
# if defined(__x86_64__)
# define __NR_recvmmsg 299
@@ -219,103 +126,7 @@
# endif
#endif /* __NR_getrandom */
-int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
-#if defined(__i386__)
- unsigned long args[4];
- int r;
-
- args[0] = (unsigned long) fd;
- args[1] = (unsigned long) addr;
- args[2] = (unsigned long) addrlen;
- args[3] = (unsigned long) flags;
-
- r = syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args);
-
- /* socketcall() raises EINVAL when SYS_ACCEPT4 is not supported but so does
- * a bad flags argument. Try to distinguish between the two cases.
- */
- if (r == -1)
- if (errno == EINVAL)
- if ((flags & ~(UV__SOCK_CLOEXEC|UV__SOCK_NONBLOCK)) == 0)
- errno = ENOSYS;
-
- return r;
-#elif defined(__NR_accept4)
- return syscall(__NR_accept4, fd, addr, addrlen, flags);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__eventfd(unsigned int count) {
-#if defined(__NR_eventfd)
- return syscall(__NR_eventfd, count);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__eventfd2(unsigned int count, int flags) {
-#if defined(__NR_eventfd2)
- return syscall(__NR_eventfd2, count, flags);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_init(void) {
-#if defined(__NR_inotify_init)
- return syscall(__NR_inotify_init);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_init1(int flags) {
-#if defined(__NR_inotify_init1)
- return syscall(__NR_inotify_init1, flags);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_add_watch(int fd, const char* path, uint32_t mask) {
-#if defined(__NR_inotify_add_watch)
- return syscall(__NR_inotify_add_watch, fd, path, mask);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_rm_watch(int fd, int32_t wd) {
-#if defined(__NR_inotify_rm_watch)
- return syscall(__NR_inotify_rm_watch, fd, wd);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__pipe2(int pipefd[2], int flags) {
-#if defined(__NR_pipe2)
- int result;
- result = syscall(__NR_pipe2, pipefd, flags);
-#if MSAN_ACTIVE
- if (!result)
- __msan_unpoison(pipefd, sizeof(int[2]));
-#endif
- return result;
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
+struct uv__mmsghdr;
int uv__sendmmsg(int fd,
struct uv__mmsghdr* mmsg,
diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h
index b7729b82ae..2e8fa2a519 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -31,55 +31,6 @@
#include <sys/time.h>
#include <sys/socket.h>
-#if defined(__alpha__)
-# define UV__O_CLOEXEC 0x200000
-#elif defined(__hppa__)
-# define UV__O_CLOEXEC 0x200000
-#elif defined(__sparc__)
-# define UV__O_CLOEXEC 0x400000
-#else
-# define UV__O_CLOEXEC 0x80000
-#endif
-
-#if defined(__alpha__)
-# define UV__O_NONBLOCK 0x4
-#elif defined(__hppa__)
-# define UV__O_NONBLOCK O_NONBLOCK
-#elif defined(__mips__)
-# define UV__O_NONBLOCK 0x80
-#elif defined(__sparc__)
-# define UV__O_NONBLOCK 0x4000
-#else
-# define UV__O_NONBLOCK 0x800
-#endif
-
-#define UV__EFD_CLOEXEC UV__O_CLOEXEC
-#define UV__EFD_NONBLOCK UV__O_NONBLOCK
-
-#define UV__IN_CLOEXEC UV__O_CLOEXEC
-#define UV__IN_NONBLOCK UV__O_NONBLOCK
-
-#define UV__SOCK_CLOEXEC UV__O_CLOEXEC
-#if defined(SOCK_NONBLOCK)
-# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
-#else
-# define UV__SOCK_NONBLOCK UV__O_NONBLOCK
-#endif
-
-/* inotify flags */
-#define UV__IN_ACCESS 0x001
-#define UV__IN_MODIFY 0x002
-#define UV__IN_ATTRIB 0x004
-#define UV__IN_CLOSE_WRITE 0x008
-#define UV__IN_CLOSE_NOWRITE 0x010
-#define UV__IN_OPEN 0x020
-#define UV__IN_MOVED_FROM 0x040
-#define UV__IN_MOVED_TO 0x080
-#define UV__IN_CREATE 0x100
-#define UV__IN_DELETE 0x200
-#define UV__IN_DELETE_SELF 0x400
-#define UV__IN_MOVE_SELF 0x800
-
struct uv__statx_timestamp {
int64_t tv_sec;
uint32_t tv_nsec;
@@ -110,36 +61,6 @@ struct uv__statx {
uint64_t unused1[14];
};
-struct uv__inotify_event {
- int32_t wd;
- uint32_t mask;
- uint32_t cookie;
- uint32_t len;
- /* char name[0]; */
-};
-
-struct uv__mmsghdr {
- struct msghdr msg_hdr;
- unsigned int msg_len;
-};
-
-int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
-int uv__eventfd(unsigned int count);
-int uv__eventfd2(unsigned int count, int flags);
-int uv__inotify_init(void);
-int uv__inotify_init1(int flags);
-int uv__inotify_add_watch(int fd, const char* path, uint32_t mask);
-int uv__inotify_rm_watch(int fd, int32_t wd);
-int uv__pipe2(int pipefd[2], int flags);
-int uv__recvmmsg(int fd,
- struct uv__mmsghdr* mmsg,
- unsigned int vlen,
- unsigned int flags,
- struct timespec* timeout);
-int uv__sendmmsg(int fd,
- struct uv__mmsghdr* mmsg,
- unsigned int vlen,
- unsigned int flags);
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
int uv__dup3(int oldfd, int newfd, int flags);
diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c
index 5ba0db022e..713b6c6608 100644
--- a/deps/uv/src/unix/openbsd.c
+++ b/deps/uv/src/unix/openbsd.c
@@ -185,7 +185,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
char model[512];
int numcpus = 1;
int which[] = {CTL_HW,HW_MODEL};
- int percpu[] = {CTL_HW,HW_CPUSPEED,0};
+ int percpu[] = {CTL_KERN,KERN_CPTIME2,0};
size_t size;
int i, j;
uv_cpu_info_t* cpu_info;
@@ -206,17 +206,15 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
i = 0;
*count = numcpus;
+ which[1] = HW_CPUSPEED;
size = sizeof(cpuspeed);
- if (sysctl(which, ARRAY_SIZE(percpu), &cpuspeed, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &cpuspeed, &size, NULL, 0))
goto error;
size = sizeof(info);
- percpu[0] = CTL_KERN;
- percpu[1] = KERN_CPTIME2;
for (i = 0; i < numcpus; i++) {
percpu[2] = i;
- size = sizeof(info);
- if (sysctl(which, ARRAY_SIZE(percpu), &info, &size, NULL, 0))
+ if (sysctl(percpu, ARRAY_SIZE(percpu), &info, &size, NULL, 0))
goto error;
cpu_info = &(*cpu_infos)[i];
diff --git a/deps/uv/src/unix/os390-syscalls.c b/deps/uv/src/unix/os390-syscalls.c
index d9abdebaee..4a926c767c 100644
--- a/deps/uv/src/unix/os390-syscalls.c
+++ b/deps/uv/src/unix/os390-syscalls.c
@@ -43,6 +43,7 @@ int scandir(const char* maindir, struct dirent*** namelist,
int (*compar)(const struct dirent**,
const struct dirent **)) {
struct dirent** nl;
+ struct dirent** nl_copy;
struct dirent* dirent;
unsigned count;
size_t allocated;
@@ -62,19 +63,17 @@ int scandir(const char* maindir, struct dirent*** namelist,
if (!filter || filter(dirent)) {
struct dirent* copy;
copy = uv__malloc(sizeof(*copy));
- if (!copy) {
- while (count) {
- dirent = nl[--count];
- uv__free(dirent);
- }
- uv__free(nl);
- closedir(mdir);
- errno = ENOMEM;
- return -1;
- }
+ if (!copy)
+ goto error;
memcpy(copy, dirent, sizeof(*copy));
- nl = uv__realloc(nl, sizeof(*copy) * (count + 1));
+ nl_copy = uv__realloc(nl, sizeof(*copy) * (count + 1));
+ if (nl_copy == NULL) {
+ uv__free(copy);
+ goto error;
+ }
+
+ nl = nl_copy;
nl[count++] = copy;
}
}
@@ -86,6 +85,16 @@ int scandir(const char* maindir, struct dirent*** namelist,
*namelist = nl;
return count;
+
+error:
+ while (count > 0) {
+ dirent = nl[--count];
+ uv__free(dirent);
+ }
+ uv__free(nl);
+ closedir(mdir);
+ errno = ENOMEM;
+ return -1;
}
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index cdf24fa976..040d57817f 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -95,8 +95,12 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
if (uv__stream_fd(handle) == -1)
return UV_EINVAL;
-#if defined(__MVS__)
+ if (handle->ipc)
+ return UV_EINVAL;
+
+#if defined(__MVS__) || defined(__PASE__)
/* On zOS, backlog=0 has undefined behaviour */
+ /* On IBMi PASE, backlog=0 leads to "Connection refused" error */
if (backlog == 0)
backlog = 1;
else if (backlog < 0)
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
index bb6b76c9fa..b021aaeba8 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -112,72 +112,64 @@ static void uv__chld(uv_signal_t* handle, int signum) {
}
-int uv__make_socketpair(int fds[2], int flags) {
-#if defined(__linux__)
- static int no_cloexec;
-
- if (no_cloexec)
- goto skip;
-
- if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0)
- return 0;
-
- /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported.
- * Anything else is a genuine error.
- */
- if (errno != EINVAL)
+static int uv__make_socketpair(int fds[2]) {
+#if defined(__FreeBSD__) || defined(__linux__)
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds))
return UV__ERR(errno);
- no_cloexec = 1;
-
-skip:
-#endif
+ return 0;
+#else
+ int err;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
return UV__ERR(errno);
- uv__cloexec(fds[0], 1);
- uv__cloexec(fds[1], 1);
+ err = uv__cloexec(fds[0], 1);
+ if (err == 0)
+ err = uv__cloexec(fds[1], 1);
- if (flags & UV__F_NONBLOCK) {
- uv__nonblock(fds[0], 1);
- uv__nonblock(fds[1], 1);
+ if (err != 0) {
+ uv__close(fds[0]);
+ uv__close(fds[1]);
+ return UV__ERR(errno);
}
return 0;
+#endif
}
int uv__make_pipe(int fds[2], int flags) {
-#if defined(__linux__)
- static int no_pipe2;
-
- if (no_pipe2)
- goto skip;
-
- if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0)
- return 0;
-
- if (errno != ENOSYS)
+#if defined(__FreeBSD__) || defined(__linux__)
+ if (pipe2(fds, flags | O_CLOEXEC))
return UV__ERR(errno);
- no_pipe2 = 1;
-
-skip:
-#endif
-
+ return 0;
+#else
if (pipe(fds))
return UV__ERR(errno);
- uv__cloexec(fds[0], 1);
- uv__cloexec(fds[1], 1);
+ if (uv__cloexec(fds[0], 1))
+ goto fail;
+
+ if (uv__cloexec(fds[1], 1))
+ goto fail;
if (flags & UV__F_NONBLOCK) {
- uv__nonblock(fds[0], 1);
- uv__nonblock(fds[1], 1);
+ if (uv__nonblock(fds[0], 1))
+ goto fail;
+
+ if (uv__nonblock(fds[1], 1))
+ goto fail;
}
return 0;
+
+fail:
+ uv__close(fds[0]);
+ uv__close(fds[1]);
+ return UV__ERR(errno);
+#endif
}
@@ -200,7 +192,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
if (container->data.stream->type != UV_NAMED_PIPE)
return UV_EINVAL;
else
- return uv__make_socketpair(fds, 0);
+ return uv__make_socketpair(fds);
case UV_INHERIT_FD:
case UV_INHERIT_STREAM:
diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c
index 1a8c7a7090..d124d3c7fc 100644
--- a/deps/uv/src/unix/proctitle.c
+++ b/deps/uv/src/unix/proctitle.c
@@ -24,17 +24,19 @@
#include <stdlib.h>
#include <string.h>
+struct uv__process_title {
+ char* str;
+ size_t len; /* Length of the current process title. */
+ size_t cap; /* Maximum capacity. Computed once in uv_setup_args(). */
+};
+
extern void uv__set_process_title(const char* title);
static uv_mutex_t process_title_mutex;
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
+static struct uv__process_title process_title;
static void* args_mem;
-static struct {
- char* str;
- size_t len;
-} process_title;
-
static void init_process_title_mutex_once(void) {
uv_mutex_init(&process_title_mutex);
@@ -42,6 +44,7 @@ static void init_process_title_mutex_once(void) {
char** uv_setup_args(int argc, char** argv) {
+ struct uv__process_title pt;
char** new_argv;
size_t size;
char* s;
@@ -50,53 +53,69 @@ char** uv_setup_args(int argc, char** argv) {
if (argc <= 0)
return argv;
+ pt.str = argv[0];
+ pt.len = strlen(argv[0]);
+ pt.cap = pt.len + 1;
+
/* Calculate how much memory we need for the argv strings. */
- size = 0;
- for (i = 0; i < argc; i++)
+ size = pt.cap;
+ for (i = 1; i < argc; i++)
size += strlen(argv[i]) + 1;
-#if defined(__MVS__)
- /* argv is not adjacent. So just use argv[0] */
- process_title.str = argv[0];
- process_title.len = strlen(argv[0]);
-#else
- process_title.str = argv[0];
- process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0];
- assert(process_title.len + 1 == size); /* argv memory should be adjacent. */
-#endif
-
/* Add space for the argv pointers. */
size += (argc + 1) * sizeof(char*);
new_argv = uv__malloc(size);
if (new_argv == NULL)
return argv;
- args_mem = new_argv;
/* Copy over the strings and set up the pointer table. */
+ i = 0;
s = (char*) &new_argv[argc + 1];
- for (i = 0; i < argc; i++) {
+ size = pt.cap;
+ goto loop;
+
+ for (/* empty */; i < argc; i++) {
size = strlen(argv[i]) + 1;
+ loop:
memcpy(s, argv[i], size);
new_argv[i] = s;
s += size;
}
new_argv[i] = NULL;
+ /* argv is not adjacent on z/os, we use just argv[0] on that platform. */
+#ifndef __MVS__
+ pt.cap = argv[i - 1] + size - argv[0];
+#endif
+
+ args_mem = new_argv;
+ process_title = pt;
+
return new_argv;
}
int uv_set_process_title(const char* title) {
+ struct uv__process_title* pt;
+ size_t len;
+
+ pt = &process_title;
+ len = strlen(title);
+
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
- if (process_title.len != 0) {
- /* No need to terminate, byte after is always '\0'. */
- strncpy(process_title.str, title, process_title.len);
- uv__set_process_title(title);
+ if (len >= pt->cap) {
+ len = 0;
+ if (pt->cap > 0)
+ len = pt->cap - 1;
}
+ memcpy(pt->str, title, len);
+ memset(pt->str + len, '\0', pt->cap - len);
+ pt->len = len;
+
uv_mutex_unlock(&process_title_mutex);
return 0;
diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c
index ba8fcc204f..1e7e8ac574 100644
--- a/deps/uv/src/unix/signal.c
+++ b/deps/uv/src/unix/signal.c
@@ -331,16 +331,7 @@ int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
void uv__signal_close(uv_signal_t* handle) {
-
uv__signal_stop(handle);
-
- /* If there are any caught signals "trapped" in the signal pipe, we can't
- * call the close callback yet. Otherwise, add the handle to the finish_close
- * queue.
- */
- if (handle->caught_signals == handle->dispatched_signals) {
- uv__make_close_pending((uv_handle_t*) handle);
- }
}
@@ -472,17 +463,6 @@ static void uv__signal_event(uv_loop_t* loop,
if (handle->flags & UV_SIGNAL_ONE_SHOT)
uv__signal_stop(handle);
-
- /* If uv_close was called while there were caught signals that were not
- * yet dispatched, the uv__finish_close was deferred. Make close pending
- * now if this has happened.
- */
- if (handle->caught_signals == handle->dispatched_signals) {
- if (handle->signum == 0)
- uv__handle_stop(handle);
- if (handle->flags & UV_HANDLE_CLOSING)
- uv__make_close_pending((uv_handle_t*) handle);
- }
}
bytes -= end;
@@ -572,6 +552,5 @@ static void uv__signal_stop(uv_signal_t* handle) {
uv__signal_unlock_and_unblock(&saved_sigmask);
handle->signum = 0;
- if (handle->caught_signals == handle->dispatched_signals)
- uv__handle_stop(handle);
+ uv__handle_stop(handle);
}
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index fa660f1381..d47e9433db 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -379,8 +379,16 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
return UV__ERR(errno);
#ifdef TCP_KEEPIDLE
- if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
- return UV__ERR(errno);
+ if (on) {
+ int intvl = 1; /* 1 second; same as default on Win32 */
+ int cnt = 10; /* 10 retries; same as hardcoded on Win32 */
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
+ return UV__ERR(errno);
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
+ return UV__ERR(errno);
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
+ return UV__ERR(errno);
+ }
#endif
/* Solaris/SmartOS, if you don't support keep-alive,
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index 98215f7e1d..eb4b8f4ce7 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -32,6 +32,8 @@
#endif
#include <sys/un.h>
+#define UV__UDP_DGRAM_MAXSIZE (64 * 1024)
+
#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
@@ -49,6 +51,36 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
int domain,
unsigned int flags);
+#if HAVE_MMSG
+
+#define UV__MMSG_MAXWIDTH 20
+
+static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf);
+static void uv__udp_sendmmsg(uv_udp_t* handle);
+
+static int uv__recvmmsg_avail;
+static int uv__sendmmsg_avail;
+static uv_once_t once = UV_ONCE_INIT;
+
+static void uv__udp_mmsg_init(void) {
+ int ret;
+ int s;
+ s = uv__socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return;
+ ret = uv__sendmmsg(s, NULL, 0, 0);
+ if (ret == 0 || errno != ENOSYS) {
+ uv__sendmmsg_avail = 1;
+ uv__recvmmsg_avail = 1;
+ } else {
+ ret = uv__recvmmsg(s, NULL, 0, 0, NULL);
+ if (ret == 0 || errno != ENOSYS)
+ uv__recvmmsg_avail = 1;
+ }
+ uv__close(s);
+}
+
+#endif
void uv__udp_close(uv_udp_t* handle) {
uv__io_close(handle->loop, &handle->io_watcher);
@@ -148,6 +180,60 @@ static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) {
}
}
+#if HAVE_MMSG
+static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) {
+ struct sockaddr_in6 peers[UV__MMSG_MAXWIDTH];
+ struct iovec iov[UV__MMSG_MAXWIDTH];
+ struct uv__mmsghdr msgs[UV__MMSG_MAXWIDTH];
+ ssize_t nread;
+ uv_buf_t chunk_buf;
+ size_t chunks;
+ int flags;
+ size_t k;
+
+ /* prepare structures for recvmmsg */
+ chunks = buf->len / UV__UDP_DGRAM_MAXSIZE;
+ if (chunks > ARRAY_SIZE(iov))
+ chunks = ARRAY_SIZE(iov);
+ for (k = 0; k < chunks; ++k) {
+ iov[k].iov_base = buf->base + k * UV__UDP_DGRAM_MAXSIZE;
+ iov[k].iov_len = UV__UDP_DGRAM_MAXSIZE;
+ msgs[k].msg_hdr.msg_iov = iov + k;
+ msgs[k].msg_hdr.msg_iovlen = 1;
+ msgs[k].msg_hdr.msg_name = peers + k;
+ msgs[k].msg_hdr.msg_namelen = sizeof(peers[0]);
+ }
+
+ do
+ nread = uv__recvmmsg(handle->io_watcher.fd, msgs, chunks, 0, NULL);
+ while (nread == -1 && errno == EINTR);
+
+ if (nread < 1) {
+ if (nread == 0 || errno == EAGAIN || errno == EWOULDBLOCK)
+ handle->recv_cb(handle, 0, buf, NULL, 0);
+ else
+ handle->recv_cb(handle, UV__ERR(errno), buf, NULL, 0);
+ } else {
+ /* count to zero, so the buffer base comes last */
+ for (k = nread; k > 0 && handle->recv_cb != NULL;) {
+ k--;
+ flags = 0;
+ if (msgs[k].msg_hdr.msg_flags & MSG_TRUNC)
+ flags |= UV_UDP_PARTIAL;
+ if (k != 0)
+ flags |= UV_UDP_MMSG_CHUNK;
+
+ chunk_buf = uv_buf_init(iov[k].iov_base, iov[k].iov_len);
+ handle->recv_cb(handle,
+ msgs[k].msg_len,
+ &chunk_buf,
+ msgs[k].msg_hdr.msg_name,
+ flags);
+ }
+ }
+ return nread;
+}
+#endif
static void uv__udp_recvmsg(uv_udp_t* handle) {
struct sockaddr_storage peer;
@@ -167,13 +253,27 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
do {
buf = uv_buf_init(NULL, 0);
- handle->alloc_cb((uv_handle_t*) handle, 64 * 1024, &buf);
+ handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf);
if (buf.base == NULL || buf.len == 0) {
handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
return;
}
assert(buf.base != NULL);
+#if HAVE_MMSG
+ uv_once(&once, uv__udp_mmsg_init);
+ if (uv__recvmmsg_avail) {
+ /* Returned space for more than 1 datagram, use it to receive
+ * multiple datagrams. */
+ if (buf.len >= 2 * UV__UDP_DGRAM_MAXSIZE) {
+ nread = uv__udp_recvmmsg(handle, &buf);
+ if (nread > 0)
+ count -= nread;
+ continue;
+ }
+ }
+#endif
+
memset(&h, 0, sizeof(h));
memset(&peer, 0, sizeof(peer));
h.msg_name = &peer;
@@ -199,21 +299,120 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
handle->recv_cb(handle, nread, &buf, (const struct sockaddr*) &peer, flags);
}
+ count--;
}
/* recv_cb callback may decide to pause or close the handle */
while (nread != -1
- && count-- > 0
+ && count > 0
&& handle->io_watcher.fd != -1
&& handle->recv_cb != NULL);
}
+#if HAVE_MMSG
+static void uv__udp_sendmmsg(uv_udp_t* handle) {
+ uv_udp_send_t* req;
+ struct uv__mmsghdr h[UV__MMSG_MAXWIDTH];
+ struct uv__mmsghdr *p;
+ QUEUE* q;
+ ssize_t npkts;
+ size_t pkts;
+ size_t i;
+
+ if (QUEUE_EMPTY(&handle->write_queue))
+ return;
+
+write_queue_drain:
+ for (pkts = 0, q = QUEUE_HEAD(&handle->write_queue);
+ pkts < UV__MMSG_MAXWIDTH && q != &handle->write_queue;
+ ++pkts, q = QUEUE_HEAD(q)) {
+ assert(q != NULL);
+ req = QUEUE_DATA(q, uv_udp_send_t, queue);
+ assert(req != NULL);
+
+ p = &h[pkts];
+ memset(p, 0, sizeof(*p));
+ if (req->addr.ss_family == AF_UNSPEC) {
+ p->msg_hdr.msg_name = NULL;
+ p->msg_hdr.msg_namelen = 0;
+ } else {
+ p->msg_hdr.msg_name = &req->addr;
+ if (req->addr.ss_family == AF_INET6)
+ p->msg_hdr.msg_namelen = sizeof(struct sockaddr_in6);
+ else if (req->addr.ss_family == AF_INET)
+ p->msg_hdr.msg_namelen = sizeof(struct sockaddr_in);
+ else if (req->addr.ss_family == AF_UNIX)
+ p->msg_hdr.msg_namelen = sizeof(struct sockaddr_un);
+ else {
+ assert(0 && "unsupported address family");
+ abort();
+ }
+ }
+ h[pkts].msg_hdr.msg_iov = (struct iovec*) req->bufs;
+ h[pkts].msg_hdr.msg_iovlen = req->nbufs;
+ }
+
+ do
+ npkts = uv__sendmmsg(handle->io_watcher.fd, h, pkts, 0);
+ while (npkts == -1 && errno == EINTR);
+
+ if (npkts < 1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
+ return;
+ for (i = 0, q = QUEUE_HEAD(&handle->write_queue);
+ i < pkts && q != &handle->write_queue;
+ ++i, q = QUEUE_HEAD(q)) {
+ assert(q != NULL);
+ req = QUEUE_DATA(q, uv_udp_send_t, queue);
+ assert(req != NULL);
+
+ req->status = UV__ERR(errno);
+ QUEUE_REMOVE(&req->queue);
+ QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
+ }
+ uv__io_feed(handle->loop, &handle->io_watcher);
+ return;
+ }
+
+ for (i = 0, q = QUEUE_HEAD(&handle->write_queue);
+ i < pkts && q != &handle->write_queue;
+ ++i, q = QUEUE_HEAD(&handle->write_queue)) {
+ assert(q != NULL);
+ req = QUEUE_DATA(q, uv_udp_send_t, queue);
+ assert(req != NULL);
+
+ req->status = req->bufs[0].len;
+
+ /* Sending a datagram is an atomic operation: either all data
+ * is written or nothing is (and EMSGSIZE is raised). That is
+ * why we don't handle partial writes. Just pop the request
+ * off the write queue and onto the completed queue, done.
+ */
+ QUEUE_REMOVE(&req->queue);
+ QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
+ }
+
+ /* couldn't batch everything, continue sending (jump to avoid stack growth) */
+ if (!QUEUE_EMPTY(&handle->write_queue))
+ goto write_queue_drain;
+ uv__io_feed(handle->loop, &handle->io_watcher);
+ return;
+}
+#endif
static void uv__udp_sendmsg(uv_udp_t* handle) {
uv_udp_send_t* req;
- QUEUE* q;
struct msghdr h;
+ QUEUE* q;
ssize_t size;
+#if HAVE_MMSG
+ uv_once(&once, uv__udp_mmsg_init);
+ if (uv__sendmmsg_avail) {
+ uv__udp_sendmmsg(handle);
+ return;
+ }
+#endif
+
while (!QUEUE_EMPTY(&handle->write_queue)) {
q = QUEUE_HEAD(&handle->write_queue);
assert(q != NULL);
@@ -263,7 +462,6 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
}
}
-
/* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional
* refinements for programs that use multicast.
*
@@ -653,7 +851,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
}
-#if !defined(__OpenBSD__) && !defined(__NetBSD__)
+#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__ANDROID__)
static int uv__udp_set_source_membership4(uv_udp_t* handle,
const struct sockaddr_in* multicast_addr,
const char* interface_addr,
@@ -842,7 +1040,7 @@ int uv_udp_set_source_membership(uv_udp_t* handle,
const char* interface_addr,
const char* source_addr,
uv_membership membership) {
-#if !defined(__OpenBSD__) && !defined(__NetBSD__)
+#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__ANDROID__)
int err;
struct sockaddr_storage mcast_addr;
struct sockaddr_in* mcast_addr4;
@@ -870,7 +1068,7 @@ int uv_udp_set_source_membership(uv_udp_t* handle,
src_addr6,
membership);
}
-
+
err = uv_ip4_addr(source_addr, 0, src_addr4);
if (err)
return err;
@@ -889,7 +1087,7 @@ static int uv__setsockopt(uv_udp_t* handle,
int option4,
int option6,
const void* val,
- size_t size) {
+ socklen_t size) {
int r;
if (handle->flags & UV_HANDLE_IPV6)
@@ -1012,7 +1210,7 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
* and use the general uv__setsockopt_maybe_char call otherwise.
*/
#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
- defined(__MVS__)
+ defined(__MVS__)
if (handle->flags & UV_HANDLE_IPV6)
return uv__setsockopt(handle,
IP_MULTICAST_LOOP,
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index 277f6497a2..fc0112a33c 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -264,8 +264,9 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
DWORD current_mode = 0;
DWORD err = 0;
- if (!(handle->flags & UV_HANDLE_PIPESERVER) &&
- handle->handle != INVALID_HANDLE_VALUE)
+ if (handle->flags & UV_HANDLE_PIPESERVER)
+ return UV_EINVAL;
+ if (handle->handle != INVALID_HANDLE_VALUE)
return UV_EBUSY;
if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
@@ -312,7 +313,7 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
/* Overlapped pipe. Try to associate with IOCP. */
if (CreateIoCompletionPort(pipeHandle,
loop->iocp,
- (ULONG_PTR)handle,
+ (ULONG_PTR) handle,
0) == NULL) {
handle->flags |= UV_HANDLE_EMULATE_IOCP;
}
@@ -326,6 +327,38 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
}
+static int pipe_alloc_accept(uv_loop_t* loop, uv_pipe_t* handle,
+ uv_pipe_accept_t* req, BOOL firstInstance) {
+ assert(req->pipeHandle == INVALID_HANDLE_VALUE);
+
+ req->pipeHandle =
+ CreateNamedPipeW(handle->name,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC |
+ (firstInstance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0),
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
+
+ if (req->pipeHandle == INVALID_HANDLE_VALUE) {
+ return 0;
+ }
+
+ /* Associate it with IOCP so we can get events. */
+ if (CreateIoCompletionPort(req->pipeHandle,
+ loop->iocp,
+ (ULONG_PTR) handle,
+ 0) == NULL) {
+ uv_fatal_error(GetLastError(), "CreateIoCompletionPort");
+ }
+
+ /* Stash a handle in the server object for use from places such as
+ * getsockname and chmod. As we transfer ownership of these to client
+ * objects, we'll allocate new ones here. */
+ handle->handle = req->pipeHandle;
+
+ return 1;
+}
+
+
static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {
uv_loop_t* loop;
uv_pipe_t* handle;
@@ -458,7 +491,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
UnregisterWait(handle->read_req.wait_handle);
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
}
- if (handle->read_req.event_handle) {
+ if (handle->read_req.event_handle != NULL) {
CloseHandle(handle->read_req.event_handle);
handle->read_req.event_handle = NULL;
}
@@ -540,13 +573,10 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
* Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
* If this fails then there's already a pipe server for the given pipe name.
*/
- handle->pipe.serv.accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
- FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
- PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
-
- if (handle->pipe.serv.accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) {
+ if (!pipe_alloc_accept(loop,
+ handle,
+ &handle->pipe.serv.accept_reqs[0],
+ TRUE)) {
err = GetLastError();
if (err == ERROR_ACCESS_DENIED) {
err = WSAEADDRINUSE; /* Translates to UV_EADDRINUSE. */
@@ -556,15 +586,6 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
goto error;
}
- if (uv_set_pipe_handle(loop,
- handle,
- handle->pipe.serv.accept_reqs[0].pipeHandle,
- -1,
- 0)) {
- err = GetLastError();
- goto error;
- }
-
handle->pipe.serv.pending_accepts = NULL;
handle->flags |= UV_HANDLE_PIPESERVER;
handle->flags |= UV_HANDLE_BOUND;
@@ -577,11 +598,6 @@ error:
handle->name = NULL;
}
- if (handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) {
- CloseHandle(handle->pipe.serv.accept_reqs[0].pipeHandle);
- handle->pipe.serv.accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE;
- }
-
return uv_translate_sys_error(err);
}
@@ -827,29 +843,11 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
uv_pipe_accept_t* req, BOOL firstInstance) {
assert(handle->flags & UV_HANDLE_LISTENING);
- if (!firstInstance) {
- assert(req->pipeHandle == INVALID_HANDLE_VALUE);
-
- req->pipeHandle = CreateNamedPipeW(handle->name,
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC,
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
- PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
-
- if (req->pipeHandle == INVALID_HANDLE_VALUE) {
- SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*) req);
- handle->reqs_pending++;
- return;
- }
-
- if (uv_set_pipe_handle(loop, handle, req->pipeHandle, -1, 0)) {
- CloseHandle(req->pipeHandle);
- req->pipeHandle = INVALID_HANDLE_VALUE;
- SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*) req);
- handle->reqs_pending++;
- return;
- }
+ if (!firstInstance && !pipe_alloc_accept(loop, handle, req, FALSE)) {
+ SET_REQ_ERROR(req, GetLastError());
+ uv_insert_pending_req(loop, (uv_req_t*) req);
+ handle->reqs_pending++;
+ return;
}
assert(req->pipeHandle != INVALID_HANDLE_VALUE);
@@ -904,7 +902,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
uv__free(item);
} else {
- pipe_client = (uv_pipe_t*)client;
+ pipe_client = (uv_pipe_t*) client;
/* Find a connection instance that has been connected, but not yet
* accepted. */
@@ -925,6 +923,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
req->next_pending = NULL;
req->pipeHandle = INVALID_HANDLE_VALUE;
+ server->handle = INVALID_HANDLE_VALUE;
if (!(server->flags & UV_HANDLE_CLOSING)) {
uv_pipe_queue_accept(loop, server, req, FALSE);
}
@@ -955,6 +954,10 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
return ERROR_NOT_SUPPORTED;
}
+ if (handle->ipc) {
+ return WSAEINVAL;
+ }
+
handle->flags |= UV_HANDLE_LISTENING;
INCREASE_ACTIVE_COUNT(loop, handle);
handle->stream.serv.connection_cb = cb;
@@ -1131,6 +1134,7 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
} else {
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
+ assert(req->event_handle != NULL);
req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1);
}
@@ -1148,15 +1152,9 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
}
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
- if (!req->event_handle) {
- req->event_handle = CreateEvent(NULL, 0, 0, NULL);
- if (!req->event_handle) {
- uv_fatal_error(GetLastError(), "CreateEvent");
- }
- }
if (req->wait_handle == INVALID_HANDLE_VALUE) {
if (!RegisterWaitForSingleObject(&req->wait_handle,
- req->u.io.overlapped.hEvent, post_completion_read_wait, (void*) req,
+ req->event_handle, post_completion_read_wait, (void*) req,
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
goto error;
@@ -1190,8 +1188,16 @@ int uv_pipe_read_start(uv_pipe_t* handle,
/* 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_READ_PENDING)) {
+ if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
+ handle->read_req.event_handle == NULL) {
+ handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL);
+ if (handle->read_req.event_handle == NULL) {
+ uv_fatal_error(GetLastError(), "CreateEvent");
+ }
+ }
uv_pipe_queue_read(loop, handle);
+ }
return 0;
}
@@ -1326,7 +1332,16 @@ static int uv__pipe_write_data(uv_loop_t* loop,
req->coalesced = 0;
req->event_handle = NULL;
req->wait_handle = INVALID_HANDLE_VALUE;
+
+ /* Prepare the overlapped structure. */
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
+ if (handle->flags & (UV_HANDLE_EMULATE_IOCP | UV_HANDLE_BLOCKING_WRITES)) {
+ req->event_handle = CreateEvent(NULL, 0, 0, NULL);
+ if (req->event_handle == NULL) {
+ uv_fatal_error(GetLastError(), "CreateEvent");
+ }
+ req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1);
+ }
req->write_buffer = uv_null_buf_;
if (nbufs == 0) {
@@ -1375,11 +1390,6 @@ static int uv__pipe_write_data(uv_loop_t* loop,
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 */
- req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL);
- if (!req->u.io.overlapped.hEvent) {
- uv_fatal_error(GetLastError(), "CreateEvent");
- }
-
result = WriteFile(handle->handle,
write_buf.base,
write_buf.len,
@@ -1388,7 +1398,8 @@ static int uv__pipe_write_data(uv_loop_t* loop,
if (!result && GetLastError() != ERROR_IO_PENDING) {
err = GetLastError();
- CloseHandle(req->u.io.overlapped.hEvent);
+ CloseHandle(req->event_handle);
+ req->event_handle = NULL;
return err;
}
@@ -1399,14 +1410,16 @@ static int uv__pipe_write_data(uv_loop_t* loop,
/* Request queued by the kernel. */
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) !=
+ if (WaitForSingleObject(req->event_handle, INFINITE) !=
WAIT_OBJECT_0) {
err = GetLastError();
- CloseHandle(req->u.io.overlapped.hEvent);
+ CloseHandle(req->event_handle);
+ req->event_handle = NULL;
return err;
}
}
- CloseHandle(req->u.io.overlapped.hEvent);
+ CloseHandle(req->event_handle);
+ req->event_handle = NULL;
REGISTER_HANDLE_REQ(loop, handle, req);
handle->reqs_pending++;
@@ -1433,12 +1446,8 @@ static int uv__pipe_write_data(uv_loop_t* loop,
}
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
- req->event_handle = CreateEvent(NULL, 0, 0, NULL);
- if (!req->event_handle) {
- uv_fatal_error(GetLastError(), "CreateEvent");
- }
if (!RegisterWaitForSingleObject(&req->wait_handle,
- req->u.io.overlapped.hEvent, post_completion_write_wait, (void*) req,
+ req->event_handle, post_completion_write_wait, (void*) req,
INFINITE, WT_EXECUTEINWAITTHREAD)) {
return GetLastError();
}
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index fd34c623d8..941c8010d3 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -251,7 +251,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
UnregisterWait(req->wait_handle);
req->wait_handle = INVALID_HANDLE_VALUE;
}
- if (req->event_handle) {
+ if (req->event_handle != NULL) {
CloseHandle(req->event_handle);
req->event_handle = NULL;
}
@@ -268,7 +268,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
UnregisterWait(handle->read_req.wait_handle);
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
}
- if (handle->read_req.event_handle) {
+ if (handle->read_req.event_handle != NULL) {
CloseHandle(handle->read_req.event_handle);
handle->read_req.event_handle = NULL;
}
@@ -428,6 +428,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
/* Prepare the overlapped structure. */
memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
+ assert(req->event_handle != NULL);
req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
}
@@ -466,7 +467,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
closesocket(accept_socket);
/* Destroy the event handle */
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
- CloseHandle(req->u.io.overlapped.hEvent);
+ CloseHandle(req->event_handle);
req->event_handle = NULL;
}
}
@@ -509,7 +510,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
/* Prepare the overlapped structure. */
memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
- assert(req->event_handle);
+ assert(req->event_handle != NULL);
req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
}
@@ -612,8 +613,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1
: uv_simultaneous_server_accepts;
- if(!handle->tcp.serv.accept_reqs) {
- handle->tcp.serv.accept_reqs = (uv_tcp_accept_t*)
+ if (handle->tcp.serv.accept_reqs == NULL) {
+ handle->tcp.serv.accept_reqs =
uv__malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));
if (!handle->tcp.serv.accept_reqs) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
@@ -628,7 +629,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
req->wait_handle = INVALID_HANDLE_VALUE;
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
req->event_handle = CreateEvent(NULL, 0, 0, NULL);
- if (!req->event_handle) {
+ if (req->event_handle == NULL) {
uv_fatal_error(GetLastError(), "CreateEvent");
}
} else {
@@ -737,9 +738,9 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
* request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING)) {
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
- !handle->read_req.event_handle) {
+ handle->read_req.event_handle == NULL) {
handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL);
- if (!handle->read_req.event_handle) {
+ if (handle->read_req.event_handle == NULL) {
uv_fatal_error(GetLastError(), "CreateEvent");
}
}
@@ -862,7 +863,7 @@ int uv_tcp_write(uv_loop_t* loop,
memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
req->event_handle = CreateEvent(NULL, 0, 0, NULL);
- if (!req->event_handle) {
+ if (req->event_handle == NULL) {
uv_fatal_error(GetLastError(), "CreateEvent");
}
req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
@@ -1080,7 +1081,7 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
UnregisterWait(req->wait_handle);
req->wait_handle = INVALID_HANDLE_VALUE;
}
- if (req->event_handle) {
+ if (req->event_handle != NULL) {
CloseHandle(req->event_handle);
req->event_handle = NULL;
}
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index 517aa4af79..488d9b2a14 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -46,14 +46,16 @@
#define UNICODE_REPLACEMENT_CHARACTER (0xfffd)
-#define ANSI_NORMAL 0x00
-#define ANSI_ESCAPE_SEEN 0x02
-#define ANSI_CSI 0x04
-#define ANSI_ST_CONTROL 0x08
-#define ANSI_IGNORE 0x10
-#define ANSI_IN_ARG 0x20
-#define ANSI_IN_STRING 0x40
-#define ANSI_BACKSLASH_SEEN 0x80
+#define ANSI_NORMAL 0x0000
+#define ANSI_ESCAPE_SEEN 0x0002
+#define ANSI_CSI 0x0004
+#define ANSI_ST_CONTROL 0x0008
+#define ANSI_IGNORE 0x0010
+#define ANSI_IN_ARG 0x0020
+#define ANSI_IN_STRING 0x0040
+#define ANSI_BACKSLASH_SEEN 0x0080
+#define ANSI_EXTENSION 0x0100
+#define ANSI_DECSCUSR 0x0200
#define MAX_INPUT_BUFFER_LENGTH 8192
#define MAX_CONSOLE_CHAR 8192
@@ -62,7 +64,12 @@
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
-static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info);
+#define CURSOR_SIZE_SMALL 25
+#define CURSOR_SIZE_LARGE 100
+
+static void uv_tty_capture_initial_style(
+ CONSOLE_SCREEN_BUFFER_INFO* screen_buffer_info,
+ CONSOLE_CURSOR_INFO* cursor_info);
static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info);
static int uv__cancel_read_console(uv_tty_t* handle);
@@ -149,6 +156,8 @@ static char uv_tty_default_fg_bright = 0;
static char uv_tty_default_bg_bright = 0;
static char uv_tty_default_inverse = 0;
+static CONSOLE_CURSOR_INFO uv_tty_default_cursor_info;
+
/* Determine whether or not ANSI support is enabled. */
static BOOL uv__need_check_vterm_state = TRUE;
static uv_tty_vtermstate_t uv__vterm_state = UV_TTY_UNSUPPORTED;
@@ -183,6 +192,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
DWORD NumberOfEvents;
HANDLE handle;
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
+ CONSOLE_CURSOR_INFO cursor_info;
(void)unused;
uv__once_init();
@@ -215,6 +225,11 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
return uv_translate_sys_error(GetLastError());
}
+ /* Obtain the cursor info with the output handle. */
+ if (!GetConsoleCursorInfo(handle, &cursor_info)) {
+ return uv_translate_sys_error(GetLastError());
+ }
+
/* 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);
@@ -222,8 +237,8 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
if (uv__need_check_vterm_state)
uv__determine_vterm_state(handle);
- /* Remember the original console text attributes. */
- uv_tty_capture_initial_style(&screen_buffer_info);
+ /* Remember the original console text attributes and cursor info. */
+ uv_tty_capture_initial_style(&screen_buffer_info, &cursor_info);
uv_tty_update_virtual_window(&screen_buffer_info);
@@ -274,7 +289,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
/* Set the default console text attributes based on how the console was
* configured when libuv started.
*/
-static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) {
+static void uv_tty_capture_initial_style(
+ CONSOLE_SCREEN_BUFFER_INFO* screen_buffer_info,
+ CONSOLE_CURSOR_INFO* cursor_info) {
static int style_captured = 0;
/* Only do this once.
@@ -283,7 +300,7 @@ static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) {
return;
/* Save raw win32 attributes. */
- uv_tty_default_text_attributes = info->wAttributes;
+ uv_tty_default_text_attributes = screen_buffer_info->wAttributes;
/* Convert black text on black background to use white text. */
if (uv_tty_default_text_attributes == 0)
@@ -323,6 +340,9 @@ static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) {
if (uv_tty_default_text_attributes & COMMON_LVB_REVERSE_VIDEO)
uv_tty_default_inverse = 1;
+ /* Save the cursor size and the cursor state. */
+ uv_tty_default_cursor_info = *cursor_info;
+
style_captured = 1;
}
@@ -1230,7 +1250,7 @@ static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,
static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
const COORD origin = {0, 0};
const WORD char_attrs = uv_tty_default_text_attributes;
- CONSOLE_SCREEN_BUFFER_INFO info;
+ CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
DWORD count, written;
if (*error != ERROR_SUCCESS) {
@@ -1251,12 +1271,12 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
/* Clear the screen buffer. */
retry:
- if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
- *error = GetLastError();
- return -1;
+ if (!GetConsoleScreenBufferInfo(handle->handle, &screen_buffer_info)) {
+ *error = GetLastError();
+ return -1;
}
- count = info.dwSize.X * info.dwSize.Y;
+ count = screen_buffer_info.dwSize.X * screen_buffer_info.dwSize.Y;
if (!(FillConsoleOutputCharacterW(handle->handle,
L'\x20',
@@ -1279,7 +1299,13 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
/* Move the virtual window up to the top. */
uv_tty_virtual_offset = 0;
- uv_tty_update_virtual_window(&info);
+ uv_tty_update_virtual_window(&screen_buffer_info);
+
+ /* Reset the cursor size and the cursor state. */
+ if (!SetConsoleCursorInfo(handle->handle, &uv_tty_default_cursor_info)) {
+ *error = GetLastError();
+ return -1;
+ }
return 0;
}
@@ -1618,6 +1644,31 @@ static int uv_tty_set_cursor_visibility(uv_tty_t* handle,
return 0;
}
+static int uv_tty_set_cursor_shape(uv_tty_t* handle, int style, DWORD* error) {
+ CONSOLE_CURSOR_INFO cursor_info;
+
+ if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) {
+ *error = GetLastError();
+ return -1;
+ }
+
+ if (style == 0) {
+ cursor_info.dwSize = uv_tty_default_cursor_info.dwSize;
+ } else if (style <= 2) {
+ cursor_info.dwSize = CURSOR_SIZE_LARGE;
+ } else {
+ cursor_info.dwSize = CURSOR_SIZE_SMALL;
+ }
+
+ if (!SetConsoleCursorInfo(handle->handle, &cursor_info)) {
+ *error = GetLastError();
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int uv_tty_write_bufs(uv_tty_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
@@ -1645,7 +1696,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
unsigned char utf8_bytes_left = handle->tty.wr.utf8_bytes_left;
unsigned int utf8_codepoint = handle->tty.wr.utf8_codepoint;
unsigned char previous_eol = handle->tty.wr.previous_eol;
- unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state;
+ unsigned short 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. */
@@ -1761,7 +1812,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
ansi_parser_state = ANSI_NORMAL;
continue;
- case '8':
+ case '8':
/* Restore the cursor position and text attributes */
FLUSH_TEXT();
uv_tty_restore_state(handle, 1, error);
@@ -1779,121 +1830,193 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
}
}
+ } else if (ansi_parser_state == ANSI_IGNORE) {
+ /* We're ignoring this command. Stop only on command character. */
+ if (utf8_codepoint >= '@' && utf8_codepoint <= '~') {
+ ansi_parser_state = ANSI_NORMAL;
+ }
+ continue;
+
+ } else if (ansi_parser_state == ANSI_DECSCUSR) {
+ /* So far we've the sequence `ESC [ arg space`, and we're waiting for
+ * the final command byte. */
+ if (utf8_codepoint >= '@' && utf8_codepoint <= '~') {
+ /* Command byte */
+ if (utf8_codepoint == 'q') {
+ /* Change the cursor shape */
+ int style = handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 1;
+ if (style >= 0 && style <= 6) {
+ FLUSH_TEXT();
+ uv_tty_set_cursor_shape(handle, style, error);
+ }
+ }
+
+ /* Sequence ended - go back to normal state. */
+ ansi_parser_state = ANSI_NORMAL;
+ continue;
+ }
+ /* Unexpected character, but sequence hasn't ended yet. Ignore the rest
+ * of the sequence. */
+ ansi_parser_state = ANSI_IGNORE;
+
} else if (ansi_parser_state & ANSI_CSI) {
- if (!(ansi_parser_state & ANSI_IGNORE)) {
- if (utf8_codepoint >= '0' && utf8_codepoint <= '9') {
- /* Parsing a numerical argument */
-
- if (!(ansi_parser_state & ANSI_IN_ARG)) {
- /* We were not currently parsing a number */
-
- /* 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;
- continue;
- }
-
- ansi_parser_state |= ANSI_IN_ARG;
- handle->tty.wr.ansi_csi_argc++;
- handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] =
- (unsigned short) utf8_codepoint - '0';
+ /* So far we've seen `ESC [`, and we may or may not have already parsed
+ * some of the arguments that follow. */
+
+ if (utf8_codepoint >= '0' && utf8_codepoint <= '9') {
+ /* Parse a numerical argument. */
+ if (!(ansi_parser_state & ANSI_IN_ARG)) {
+ /* We were not currently parsing a number, add a new one. */
+ /* Check for that there are too many arguments. */
+ if (handle->tty.wr.ansi_csi_argc >=
+ ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {
+ ansi_parser_state = ANSI_IGNORE;
continue;
- } else {
- /* We were already parsing a number. Parse next digit. */
- uint32_t value = 10 *
- handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1];
-
- /* Check for overflow. */
- if (value > UINT16_MAX) {
- ansi_parser_state |= ANSI_IGNORE;
- continue;
- }
-
- handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] =
- (unsigned short) value + (utf8_codepoint - '0');
- continue;
}
+ ansi_parser_state |= ANSI_IN_ARG;
+ handle->tty.wr.ansi_csi_argc++;
+ handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] =
+ (unsigned short) utf8_codepoint - '0';
+ continue;
+
+ } else {
+ /* We were already parsing a number. Parse next digit. */
+ uint32_t value = 10 *
+ handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1];
- } else if (utf8_codepoint == ';') {
- /* Denotes the end of an argument. */
- if (ansi_parser_state & ANSI_IN_ARG) {
- ansi_parser_state &= ~ANSI_IN_ARG;
+ /* Check for overflow. */
+ if (value > UINT16_MAX) {
+ ansi_parser_state = ANSI_IGNORE;
continue;
+ }
- } else {
- /* If ANSI_IN_ARG is not set, add another argument and default it
- * to 0. */
+ handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] =
+ (unsigned short) value + (utf8_codepoint - '0');
+ continue;
+ }
- /* 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;
- continue;
- }
+ } else if (utf8_codepoint == ';') {
+ /* Denotes the end of an argument. */
+ if (ansi_parser_state & ANSI_IN_ARG) {
+ ansi_parser_state &= ~ANSI_IN_ARG;
+ continue;
+
+ } else {
+ /* If ANSI_IN_ARG is not set, add another argument and default
+ * it to 0. */
- handle->tty.wr.ansi_csi_argc++;
- handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = 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;
continue;
}
- } 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. */
+ handle->tty.wr.ansi_csi_argc++;
+ handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = 0;
continue;
+ }
- } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' &&
- (handle->tty.wr.ansi_csi_argc > 0 || utf8_codepoint != '[')) {
- int x, y, d;
+ } else if (utf8_codepoint == '?' &&
+ !(ansi_parser_state & ANSI_IN_ARG) &&
+ !(ansi_parser_state & ANSI_EXTENSION) &&
+ handle->tty.wr.ansi_csi_argc == 0) {
+ /* Pass through '?' 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. */
+ ansi_parser_state |= ANSI_EXTENSION;
+ continue;
+
+ } else if (utf8_codepoint == ' ' &&
+ !(ansi_parser_state & ANSI_EXTENSION)) {
+ /* We expect a command byte to follow after this space. The only
+ * command that we current support is 'set cursor style'. */
+ ansi_parser_state = ANSI_DECSCUSR;
+ continue;
+
+ } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~') {
+ /* Command byte */
+ if (ansi_parser_state & ANSI_EXTENSION) {
+ /* Sequence is `ESC [ ? args command`. */
+ switch (utf8_codepoint) {
+ case 'l':
+ /* Hide the cursor */
+ if (handle->tty.wr.ansi_csi_argc == 1 &&
+ handle->tty.wr.ansi_csi_argv[0] == 25) {
+ FLUSH_TEXT();
+ uv_tty_set_cursor_visibility(handle, 0, error);
+ }
+ break;
+
+ case 'h':
+ /* Show the cursor */
+ if (handle->tty.wr.ansi_csi_argc == 1 &&
+ handle->tty.wr.ansi_csi_argv[0] == 25) {
+ FLUSH_TEXT();
+ uv_tty_set_cursor_visibility(handle, 1, error);
+ }
+ break;
+ }
- /* Command byte */
+ } else {
+ /* Sequence is `ESC [ args command`. */
+ int x, y, d;
switch (utf8_codepoint) {
case 'A':
/* cursor up */
FLUSH_TEXT();
- y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);
+ y = -(handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 1);
uv_tty_move_caret(handle, 0, 1, y, 1, error);
break;
case 'B':
/* cursor down */
FLUSH_TEXT();
- y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;
+ y = handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 1;
uv_tty_move_caret(handle, 0, 1, y, 1, error);
break;
case 'C':
/* cursor forward */
FLUSH_TEXT();
- x = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;
+ x = handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 1;
uv_tty_move_caret(handle, x, 1, 0, 1, error);
break;
case 'D':
/* cursor back */
FLUSH_TEXT();
- x = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);
+ x = -(handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 1);
uv_tty_move_caret(handle, x, 1, 0, 1, error);
break;
case 'E':
/* cursor next line */
FLUSH_TEXT();
- y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;
+ y = handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 1;
uv_tty_move_caret(handle, 0, 0, y, 1, error);
break;
case 'F':
/* cursor previous line */
FLUSH_TEXT();
- y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);
+ y = -(handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 1);
uv_tty_move_caret(handle, 0, 0, y, 1, error);
break;
case 'G':
/* cursor horizontal move absolute */
FLUSH_TEXT();
- x = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0])
+ x = (handle->tty.wr.ansi_csi_argc >= 1 &&
+ handle->tty.wr.ansi_csi_argv[0])
? handle->tty.wr.ansi_csi_argv[0] - 1 : 0;
uv_tty_move_caret(handle, x, 0, 0, 1, error);
break;
@@ -1902,9 +2025,11 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
case 'f':
/* cursor move absolute */
FLUSH_TEXT();
- y = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0])
+ y = (handle->tty.wr.ansi_csi_argc >= 1 &&
+ handle->tty.wr.ansi_csi_argv[0])
? handle->tty.wr.ansi_csi_argv[0] - 1 : 0;
- x = (handle->tty.wr.ansi_csi_argc >= 2 && handle->tty.wr.ansi_csi_argv[1])
+ x = (handle->tty.wr.ansi_csi_argc >= 2 &&
+ handle->tty.wr.ansi_csi_argv[1])
? handle->tty.wr.ansi_csi_argv[1] - 1 : 0;
uv_tty_move_caret(handle, x, 0, y, 0, error);
break;
@@ -1912,7 +2037,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
case 'J':
/* Erase screen */
FLUSH_TEXT();
- d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0;
+ d = handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 0;
if (d >= 0 && d <= 2) {
uv_tty_clear(handle, d, 1, error);
}
@@ -1921,7 +2047,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
case 'K':
/* Erase line */
FLUSH_TEXT();
- d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0;
+ d = handle->tty.wr.ansi_csi_argc
+ ? handle->tty.wr.ansi_csi_argv[0] : 0;
if (d >= 0 && d <= 2) {
uv_tty_clear(handle, d, 0, error);
}
@@ -1944,41 +2071,17 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
FLUSH_TEXT();
uv_tty_restore_state(handle, 0, error);
break;
-
- case 'l':
- /* Hide the cursor */
- if (handle->tty.wr.ansi_csi_argc == 1 &&
- handle->tty.wr.ansi_csi_argv[0] == 25) {
- FLUSH_TEXT();
- uv_tty_set_cursor_visibility(handle, 0, error);
- }
- break;
-
- case 'h':
- /* Show the cursor */
- if (handle->tty.wr.ansi_csi_argc == 1 &&
- handle->tty.wr.ansi_csi_argv[0] == 25) {
- FLUSH_TEXT();
- uv_tty_set_cursor_visibility(handle, 1, error);
- }
- break;
}
+ }
- /* Sequence ended - go back to normal state. */
- ansi_parser_state = ANSI_NORMAL;
- continue;
+ /* Sequence ended - go back to normal state. */
+ ansi_parser_state = ANSI_NORMAL;
+ continue;
- } else {
- /* We don't support commands that use private mode characters or
- * intermediaries. Ignore the rest of the sequence. */
- ansi_parser_state |= ANSI_IGNORE;
- continue;
- }
} else {
- /* We're ignoring this command. Stop only on command character. */
- if (utf8_codepoint >= '@' && utf8_codepoint <= '~') {
- ansi_parser_state = ANSI_NORMAL;
- }
+ /* We don't support commands that use private mode characters or
+ * intermediaries. Ignore the rest of the sequence. */
+ ansi_parser_state = ANSI_IGNORE;
continue;
}
diff --git a/deps/uv/test/benchmark-list.h b/deps/uv/test/benchmark-list.h
index 1e843071c0..29e44c30f0 100644
--- a/deps/uv/test/benchmark-list.h
+++ b/deps/uv/test/benchmark-list.h
@@ -23,6 +23,7 @@ BENCHMARK_DECLARE (sizes)
BENCHMARK_DECLARE (loop_count)
BENCHMARK_DECLARE (loop_count_timed)
BENCHMARK_DECLARE (ping_pongs)
+BENCHMARK_DECLARE (ping_udp)
BENCHMARK_DECLARE (tcp_write_batch)
BENCHMARK_DECLARE (tcp4_pound_100)
BENCHMARK_DECLARE (tcp4_pound_1000)
diff --git a/deps/uv/test/benchmark-multi-accept.c b/deps/uv/test/benchmark-multi-accept.c
index 2f32c0caf4..5a186233f5 100644
--- a/deps/uv/test/benchmark-multi-accept.c
+++ b/deps/uv/test/benchmark-multi-accept.c
@@ -218,8 +218,12 @@ static void send_listen_handles(uv_handle_type type,
}
else
ASSERT(0);
-
- ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 1));
+ /* We need to initialize this pipe with ipc=0 - this is not a uv_pipe we'll
+ * be sending handles over, it's just for listening for new connections.
+ * If we accept a connection then the connected pipe must be initialized
+ * with ipc=1.
+ */
+ ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 0));
ASSERT(0 == uv_pipe_bind(&ctx.ipc_pipe, IPC_PIPE_NAME));
ASSERT(0 == uv_listen((uv_stream_t*) &ctx.ipc_pipe, 128, ipc_connection_cb));
diff --git a/deps/uv/test/benchmark-ping-udp.c b/deps/uv/test/benchmark-ping-udp.c
new file mode 100644
index 0000000000..a29502a786
--- /dev/null
+++ b/deps/uv/test/benchmark-ping-udp.c
@@ -0,0 +1,163 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Run the benchmark for this many ms */
+#define TIME 5000
+
+typedef struct {
+ int pongs;
+ int state;
+ uv_udp_t udp;
+ struct sockaddr_in server_addr;
+} pinger_t;
+
+typedef struct buf_s {
+ uv_buf_t uv_buf_t;
+ struct buf_s* next;
+} buf_t;
+
+static char PING[] = "PING\n";
+
+static uv_loop_t* loop;
+
+static int completed_pingers;
+static unsigned long completed_pings;
+static int64_t start_time;
+
+
+static void buf_alloc(uv_handle_t* tcp, size_t size, uv_buf_t* buf) {
+ static char slab[64 * 1024];
+ buf->base = slab;
+ buf->len = sizeof(slab);
+}
+
+
+static void buf_free(const uv_buf_t* buf) {
+}
+
+
+static void pinger_close_cb(uv_handle_t* handle) {
+ pinger_t* pinger;
+
+ pinger = (pinger_t*)handle->data;
+#if DEBUG
+ fprintf(stderr, "ping_pongs: %d roundtrips/s\n",
+ pinger->pongs / (TIME / 1000));
+#endif
+
+ completed_pings += pinger->pongs;
+ completed_pingers++;
+ free(pinger);
+}
+
+static void pinger_write_ping(pinger_t* pinger) {
+ uv_buf_t buf;
+ int r;
+
+ buf = uv_buf_init(PING, sizeof(PING) - 1);
+ r = uv_udp_try_send(&pinger->udp, &buf, 1,
+ (const struct sockaddr*) &pinger->server_addr);
+ if (r < 0)
+ FATAL("uv_udp_send failed");
+}
+
+static void pinger_read_cb(uv_udp_t* udp,
+ ssize_t nread,
+ const uv_buf_t* buf,
+ const struct sockaddr* addr,
+ unsigned flags) {
+ ssize_t i;
+ pinger_t* pinger;
+ pinger = (pinger_t*)udp->data;
+
+ /* Now we count the pings */
+ for (i = 0; i < nread; i++) {
+ ASSERT(buf->base[i] == PING[pinger->state]);
+ pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
+ if (pinger->state == 0) {
+ pinger->pongs++;
+ if (uv_now(loop) - start_time > TIME) {
+ uv_close((uv_handle_t*)udp, pinger_close_cb);
+ break;
+ }
+ pinger_write_ping(pinger);
+ }
+ }
+
+ buf_free(buf);
+}
+
+static void udp_pinger_new(void) {
+ pinger_t* pinger = malloc(sizeof(*pinger));
+ int r;
+
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &pinger->server_addr));
+ pinger->state = 0;
+ pinger->pongs = 0;
+
+ /* Try to do NUM_PINGS ping-pongs (connection-less). */
+ r = uv_udp_init(loop, &pinger->udp);
+ ASSERT(r == 0);
+
+ pinger->udp.data = pinger;
+
+ /* Start pinging */
+ if (0 != uv_udp_recv_start(&pinger->udp, buf_alloc, pinger_read_cb)) {
+ FATAL("uv_udp_read_start failed");
+ }
+ pinger_write_ping(pinger);
+}
+
+static int ping_udp(unsigned pingers) {
+ unsigned i;
+
+ loop = uv_default_loop();
+ start_time = uv_now(loop);
+
+ for (i = 0; i < pingers; ++i) {
+ udp_pinger_new();
+ }
+ uv_run(loop, UV_RUN_DEFAULT);
+ ASSERT(completed_pingers >= 1);
+
+ fprintf(stderr, "ping_pongs: %d pingers, ~ %lu roundtrips/s\n",
+ completed_pingers, completed_pings / (TIME/1000));
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+#define X(PINGERS) \
+BENCHMARK_IMPL(ping_udp##PINGERS) {\
+ return ping_udp(PINGERS); \
+}
+
+X(1)
+X(10)
+X(100)
+
+#undef X
diff --git a/deps/uv/test/echo-server.c b/deps/uv/test/echo-server.c
index a38e975d48..c65142ff90 100644
--- a/deps/uv/test/echo-server.c
+++ b/deps/uv/test/echo-server.c
@@ -37,6 +37,7 @@ static uv_tcp_t tcpServer;
static uv_udp_t udpServer;
static uv_pipe_t pipeServer;
static uv_handle_t* server;
+static uv_udp_send_t* send_freelist;
static void after_write(uv_write_t* req, int status);
static void after_read(uv_stream_t*, ssize_t nread, const uv_buf_t* buf);
@@ -133,6 +134,14 @@ static void echo_alloc(uv_handle_t* handle,
buf->len = suggested_size;
}
+static void slab_alloc(uv_handle_t* handle,
+ size_t suggested_size,
+ uv_buf_t* buf) {
+ /* up to 16 datagrams at once */
+ static char slab[16 * 64 * 1024];
+ buf->base = slab;
+ buf->len = sizeof(slab);
+}
static void on_connection(uv_stream_t* server, int status) {
uv_stream_t* stream;
@@ -178,35 +187,43 @@ static void on_server_close(uv_handle_t* handle) {
ASSERT(handle == server);
}
+static uv_udp_send_t* send_alloc(void) {
+ uv_udp_send_t* req = send_freelist;
+ if (req != NULL)
+ send_freelist = req->data;
+ else
+ req = malloc(sizeof(*req));
+ return req;
+}
-static void on_send(uv_udp_send_t* req, int status);
-
+static void on_send(uv_udp_send_t* req, int status) {
+ ASSERT(req != NULL);
+ ASSERT(status == 0);
+ req->data = send_freelist;
+ send_freelist = req;
+}
static void on_recv(uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* rcvbuf,
const struct sockaddr* addr,
unsigned flags) {
- uv_udp_send_t* req;
uv_buf_t sndbuf;
+ if (nread == 0) {
+ /* Everything OK, but nothing read. */
+ return;
+ }
+
ASSERT(nread > 0);
ASSERT(addr->sa_family == AF_INET);
- req = malloc(sizeof(*req));
+ uv_udp_send_t* req = send_alloc();
ASSERT(req != NULL);
-
- sndbuf = *rcvbuf;
- ASSERT(0 == uv_udp_send(req, handle, &sndbuf, 1, addr, on_send));
-}
-
-
-static void on_send(uv_udp_send_t* req, int status) {
- ASSERT(status == 0);
- free(req);
+ sndbuf = uv_buf_init(rcvbuf->base, nread);
+ ASSERT(0 <= uv_udp_send(req, handle, &sndbuf, 1, addr, on_send));
}
-
static int tcp4_echo_start(int port) {
struct sockaddr_in addr;
int r;
@@ -277,8 +294,10 @@ static int tcp6_echo_start(int port) {
static int udp4_echo_start(int port) {
+ struct sockaddr_in addr;
int r;
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", port, &addr));
server = (uv_handle_t*)&udpServer;
serverType = UDP;
@@ -288,7 +307,13 @@ static int udp4_echo_start(int port) {
return 1;
}
- r = uv_udp_recv_start(&udpServer, echo_alloc, on_recv);
+ r = uv_udp_bind(&udpServer, (const struct sockaddr*) &addr, 0);
+ if (r) {
+ fprintf(stderr, "uv_udp_bind: %s\n", uv_strerror(r));
+ return 1;
+ }
+
+ r = uv_udp_recv_start(&udpServer, slab_alloc, on_recv);
if (r) {
fprintf(stderr, "uv_udp_recv_start: %s\n", uv_strerror(r));
return 1;
diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c
index 2aad6a522f..3a6452ffdf 100644
--- a/deps/uv/test/run-tests.c
+++ b/deps/uv/test/run-tests.c
@@ -45,6 +45,7 @@ int ipc_helper_bind_twice(void);
int ipc_helper_send_zero(void);
int stdio_over_pipes_helper(void);
void spawn_stdin_stdout(void);
+void process_title_big_argv(void);
int spawn_tcp_server_helper(void);
static int maybe_run_test(int argc, char **argv);
@@ -210,7 +211,11 @@ static int maybe_run_test(int argc, char **argv) {
notify_parent_process();
ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd)));
ASSERT(fd > 2);
+# if defined(__PASE__) /* On IBMi PASE, write() returns 1 */
+ ASSERT(1 == write(fd, "x", 1));
+# else
ASSERT(-1 == write(fd, "x", 1));
+# endif /* !__PASE__ */
return 1;
}
@@ -235,5 +240,11 @@ static int maybe_run_test(int argc, char **argv) {
}
#endif /* !_WIN32 */
+ if (strcmp(argv[1], "process_title_big_argv_helper") == 0) {
+ notify_parent_process();
+ process_title_big_argv();
+ return 0;
+ }
+
return run_test(argv[1], 0, 1);
}
diff --git a/deps/uv/test/runner.c b/deps/uv/test/runner.c
index a0f5df8947..bb50b43b30 100644
--- a/deps/uv/test/runner.c
+++ b/deps/uv/test/runner.c
@@ -20,6 +20,7 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "runner.h"
@@ -167,6 +168,7 @@ int run_test(const char* test,
process_info_t processes[1024];
process_info_t *main_proc;
task_entry_t* task;
+ int timeout_multiplier;
int process_count;
int result;
int status;
@@ -249,7 +251,22 @@ int run_test(const char* test,
goto out;
}
- result = process_wait(main_proc, 1, task->timeout);
+ timeout_multiplier = 1;
+#ifndef _WIN32
+ do {
+ const char* var;
+
+ var = getenv("UV_TEST_TIMEOUT_MULTIPLIER");
+ if (var == NULL)
+ break;
+
+ timeout_multiplier = atoi(var);
+ if (timeout_multiplier <= 0)
+ timeout_multiplier = 1;
+ } while (0);
+#endif
+
+ result = process_wait(main_proc, 1, task->timeout * timeout_multiplier);
if (result == -1) {
FATAL("process_wait failed");
} else if (result == -2) {
diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c
index c3e698e585..3335c88106 100644
--- a/deps/uv/test/test-fs-copyfile.c
+++ b/deps/uv/test/test-fs-copyfile.c
@@ -199,8 +199,11 @@ TEST_IMPL(fs_copyfile) {
touch_file(dst, 0);
chmod(dst, S_IRUSR|S_IRGRP|S_IROTH); /* Sets file mode to 444 (read-only). */
r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL);
+ /* On IBMi PASE, qsecofr users can overwrite read-only files */
+# ifndef __PASE__
ASSERT(req.result == UV_EACCES);
ASSERT(r == UV_EACCES);
+# endif
uv_fs_req_cleanup(&req);
#endif
diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c
index e694d258ea..28a6a1ebb3 100644
--- a/deps/uv/test/test-fs-event.c
+++ b/deps/uv/test/test-fs-event.c
@@ -285,6 +285,12 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
if (filename && strcmp(filename, file_prefix_in_subdir) == 0)
return;
#endif
+ /* It may happen that the "subdir" creation event is captured even though
+ * we started watching after its actual creation.
+ */
+ if (strcmp(filename, "subdir") == 0)
+ return;
+
fs_multievent_cb_called++;
ASSERT(handle == &fs_event);
ASSERT(status == 0);
@@ -300,11 +306,13 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
sizeof(file_prefix_in_subdir) - 1) == 0);
#endif
- if (fs_event_created + fs_event_removed == fs_event_file_count) {
+ if (fs_event_created == fs_event_file_count &&
+ fs_multievent_cb_called == fs_event_created) {
/* Once we've processed all create events, delete all files */
ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0));
} else if (fs_multievent_cb_called == 2 * fs_event_file_count) {
/* Once we've processed all create and delete events, stop watching */
+ ASSERT(fs_event_removed == fs_event_file_count);
uv_close((uv_handle_t*) &timer, close_cb);
uv_close((uv_handle_t*) handle, close_cb);
}
diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c
index 75cefe32d8..b6b2b19981 100644
--- a/deps/uv/test/test-fs.c
+++ b/deps/uv/test/test-fs.c
@@ -309,6 +309,12 @@ static void chown_root_cb(uv_fs_t* req) {
# if defined(__CYGWIN__)
/* On Cygwin, uid 0 is invalid (no root). */
ASSERT(req->result == UV_EINVAL);
+# elif defined(__PASE__)
+ /* On IBMi PASE, there is no root user. uid 0 is user qsecofr.
+ * User may grant qsecofr's privileges, including changing
+ * the file's ownership to uid 0.
+ */
+ ASSERT(req->result == 0);
# else
ASSERT(req->result == UV_EPERM);
# endif
@@ -2223,7 +2229,12 @@ int test_symlink_dir_impl(int type) {
#ifdef _WIN32
ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir + 4));
#else
+# ifdef __PASE__
+ /* On IBMi PASE, st_size returns the length of the symlink itself. */
+ ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen("test_dir_symlink"));
+# else
ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir));
+# endif
#endif
uv_fs_req_cleanup(&req);
diff --git a/deps/uv/test/test-get-memory.c b/deps/uv/test/test-get-memory.c
index 6a9a46dc81..4555ba0889 100644
--- a/deps/uv/test/test-get-memory.c
+++ b/deps/uv/test/test-get-memory.c
@@ -32,14 +32,13 @@ TEST_IMPL(get_memory) {
(unsigned long long) total_mem,
(unsigned long long) constrained_mem);
- /* On IBMi PASE, the amount of memory in use includes storage used for
- * memory and disks so it is possible to exceed the amount of main storage.
- */
-#ifndef __PASE__
ASSERT(free_mem > 0);
-#endif
ASSERT(total_mem > 0);
+ /* On IBMi PASE, the amount of memory in use is always zero. */
+#ifdef __PASE__
+ ASSERT(total_mem == free_mem);
+#else
ASSERT(total_mem > free_mem);
-
+#endif
return 0;
}
diff --git a/deps/uv/test/test-get-passwd.c b/deps/uv/test/test-get-passwd.c
index 8e16fb83c8..9b5273b315 100644
--- a/deps/uv/test/test-get-passwd.c
+++ b/deps/uv/test/test-get-passwd.c
@@ -38,7 +38,9 @@ TEST_IMPL(get_passwd) {
ASSERT(pwd.shell == NULL);
#else
len = strlen(pwd.shell);
+# ifndef __PASE__
ASSERT(len > 0);
+# endif
#endif
len = strlen(pwd.homedir);
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index a6cfc6bb92..003b8d2651 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -56,10 +56,27 @@ TEST_DECLARE (tty_raw_cancel)
TEST_DECLARE (tty_duplicate_vt100_fn_key)
TEST_DECLARE (tty_duplicate_alt_modifier_key)
TEST_DECLARE (tty_composing_character)
+TEST_DECLARE (tty_cursor_up)
+TEST_DECLARE (tty_cursor_down)
+TEST_DECLARE (tty_cursor_forward)
+TEST_DECLARE (tty_cursor_back)
+TEST_DECLARE (tty_cursor_next_line)
+TEST_DECLARE (tty_cursor_previous_line)
+TEST_DECLARE (tty_cursor_horizontal_move_absolute)
+TEST_DECLARE (tty_cursor_move_absolute)
+TEST_DECLARE (tty_hide_show_cursor)
+TEST_DECLARE (tty_set_cursor_shape)
+TEST_DECLARE (tty_erase)
+TEST_DECLARE (tty_erase_line)
+TEST_DECLARE (tty_set_style)
+TEST_DECLARE (tty_save_restore_cursor_position)
+TEST_DECLARE (tty_full_reset)
+TEST_DECLARE (tty_escape_sequence_processing)
#endif
TEST_DECLARE (tty_file)
TEST_DECLARE (tty_pty)
TEST_DECLARE (stdio_over_pipes)
+TEST_DECLARE (stdio_emulate_iocp)
TEST_DECLARE (ip6_pton)
TEST_DECLARE (connect_unspecified)
TEST_DECLARE (ipc_heavy_traffic_deadlock_bug)
@@ -242,6 +259,7 @@ TEST_DECLARE (async_null_cb)
TEST_DECLARE (eintr_handling)
TEST_DECLARE (get_currentexe)
TEST_DECLARE (process_title)
+TEST_DECLARE (process_title_big_argv)
TEST_DECLARE (process_title_threadsafe)
TEST_DECLARE (cwd_and_chdir)
TEST_DECLARE (get_memory)
@@ -453,6 +471,7 @@ TEST_DECLARE (we_get_signal_one_shot)
TEST_DECLARE (we_get_signals_mixed)
TEST_DECLARE (signal_multiple_loops)
TEST_DECLARE (signal_pending_on_close)
+TEST_DECLARE (signal_close_loop_alive)
TEST_DECLARE (closed_fd_events)
#endif
#ifdef __APPLE__
@@ -545,10 +564,27 @@ TASK_LIST_START
TEST_ENTRY (tty_duplicate_vt100_fn_key)
TEST_ENTRY (tty_duplicate_alt_modifier_key)
TEST_ENTRY (tty_composing_character)
+ TEST_ENTRY (tty_cursor_up)
+ TEST_ENTRY (tty_cursor_down)
+ TEST_ENTRY (tty_cursor_forward)
+ TEST_ENTRY (tty_cursor_back)
+ TEST_ENTRY (tty_cursor_next_line)
+ TEST_ENTRY (tty_cursor_previous_line)
+ TEST_ENTRY (tty_cursor_horizontal_move_absolute)
+ TEST_ENTRY (tty_cursor_move_absolute)
+ TEST_ENTRY (tty_hide_show_cursor)
+ TEST_ENTRY (tty_set_cursor_shape)
+ TEST_ENTRY (tty_erase)
+ TEST_ENTRY (tty_erase_line)
+ TEST_ENTRY (tty_set_style)
+ TEST_ENTRY (tty_save_restore_cursor_position)
+ TEST_ENTRY (tty_full_reset)
+ TEST_ENTRY (tty_escape_sequence_processing)
#endif
TEST_ENTRY (tty_file)
TEST_ENTRY (tty_pty)
TEST_ENTRY (stdio_over_pipes)
+ TEST_ENTRY (stdio_emulate_iocp)
TEST_ENTRY (ip6_pton)
TEST_ENTRY (connect_unspecified)
TEST_ENTRY (ipc_heavy_traffic_deadlock_bug)
@@ -684,11 +720,9 @@ TASK_LIST_START
TEST_ENTRY (udp_try_send)
TEST_ENTRY (udp_open)
- TEST_HELPER (udp_open, udp4_echo_server)
TEST_ENTRY (udp_open_twice)
TEST_ENTRY (udp_open_bound)
TEST_ENTRY (udp_open_connect)
- TEST_HELPER (udp_open_connect, udp4_echo_server)
#ifndef _WIN32
TEST_ENTRY (udp_send_unix)
#endif
@@ -788,6 +822,7 @@ TASK_LIST_START
TEST_ENTRY (get_currentexe)
TEST_ENTRY (process_title)
+ TEST_ENTRY (process_title_big_argv)
TEST_ENTRY (process_title_threadsafe)
TEST_ENTRY (cwd_and_chdir)
@@ -903,6 +938,7 @@ TASK_LIST_START
TEST_ENTRY (we_get_signals_mixed)
TEST_ENTRY (signal_multiple_loops)
TEST_ENTRY (signal_pending_on_close)
+ TEST_ENTRY (signal_close_loop_alive)
TEST_ENTRY (closed_fd_events)
#endif
diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c
index cc2b5fbe59..b3308446f1 100644
--- a/deps/uv/test/test-poll.c
+++ b/deps/uv/test/test-poll.c
@@ -222,7 +222,10 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
case 1: {
/* Read a couple of bytes. */
static char buffer[74];
- r = recv(context->sock, buffer, sizeof buffer, 0);
+
+ do
+ r = recv(context->sock, buffer, sizeof buffer, 0);
+ while (r == -1 && errno == EINTR);
ASSERT(r >= 0);
if (r > 0) {
@@ -240,12 +243,16 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
case 3: {
/* Read until EAGAIN. */
static char buffer[931];
- r = recv(context->sock, buffer, sizeof buffer, 0);
- ASSERT(r >= 0);
- while (r > 0) {
+ for (;;) {
+ do
+ r = recv(context->sock, buffer, sizeof buffer, 0);
+ while (r == -1 && errno == EINTR);
+
+ if (r <= 0)
+ break;
+
context->read += r;
- r = recv(context->sock, buffer, sizeof buffer, 0);
}
if (r == 0) {
@@ -301,7 +308,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
ASSERT(send_bytes > 0);
- r = send(context->sock, buffer, send_bytes, 0);
+ do
+ r = send(context->sock, buffer, send_bytes, 0);
+ while (r == -1 && errno == EINTR);
if (r < 0) {
ASSERT(got_eagain());
@@ -323,7 +332,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
ASSERT(send_bytes > 0);
- r = send(context->sock, buffer, send_bytes, 0);
+ do
+ r = send(context->sock, buffer, send_bytes, 0);
+ while (r == -1 && errno == EINTR);
if (r < 0) {
ASSERT(got_eagain());
@@ -339,12 +350,18 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
ASSERT(send_bytes > 0);
- r = send(context->sock, buffer, send_bytes, 0);
+ do
+ r = send(context->sock, buffer, send_bytes, 0);
+ while (r == -1 && errno == EINTR);
+ ASSERT(r != 0);
+
+ if (r < 0) {
+ ASSERT(got_eagain());
+ break;
+ }
- if (r <= 0) break;
context->sent += r;
}
- ASSERT(r > 0 || got_eagain());
break;
}
diff --git a/deps/uv/test/test-process-title.c b/deps/uv/test/test-process-title.c
index b49f3bc426..35a14809fb 100644
--- a/deps/uv/test/test-process-title.c
+++ b/deps/uv/test/test-process-title.c
@@ -74,3 +74,62 @@ TEST_IMPL(process_title) {
return 0;
}
+
+
+static void exit_cb(uv_process_t* process, int64_t status, int signo) {
+ ASSERT(status == 0);
+ ASSERT(signo == 0);
+ uv_close((uv_handle_t*) process, NULL);
+}
+
+
+TEST_IMPL(process_title_big_argv) {
+ uv_process_options_t options;
+ uv_process_t process;
+ size_t exepath_size;
+ char exepath[1024];
+ char jumbo[512];
+ char* args[5];
+
+#ifdef _WIN32
+ /* Remove once https://github.com/libuv/libuv/issues/2667 is fixed. */
+ uv_set_process_title("run-tests");
+#endif
+
+ exepath_size = sizeof(exepath) - 1;
+ ASSERT(0 == uv_exepath(exepath, &exepath_size));
+ exepath[exepath_size] = '\0';
+
+ memset(jumbo, 'x', sizeof(jumbo) - 1);
+ jumbo[sizeof(jumbo) - 1] = '\0';
+
+ /* Note: need to pass three arguments, not two, otherwise
+ * run-tests.c thinks it's the name of a test to run.
+ */
+ args[0] = exepath;
+ args[1] = "process_title_big_argv_helper";
+ args[2] = jumbo;
+ args[3] = jumbo;
+ args[4] = NULL;
+
+ memset(&options, 0, sizeof(options));
+ options.file = exepath;
+ options.args = args;
+ options.exit_cb = exit_cb;
+
+ ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+/* Called by process_title_big_argv_helper. */
+void process_title_big_argv(void) {
+ char buf[256] = "fail";
+
+ /* Return value deliberately ignored. */
+ uv_get_process_title(buf, sizeof(buf));
+ ASSERT(0 != strcmp(buf, "fail"));
+}
diff --git a/deps/uv/test/test-signal-pending-on-close.c b/deps/uv/test/test-signal-pending-on-close.c
index bf8d2793d5..23b9ec8d16 100644
--- a/deps/uv/test/test-signal-pending-on-close.c
+++ b/deps/uv/test/test-signal-pending-on-close.c
@@ -34,6 +34,11 @@ static char* buf;
static int close_cb_called;
+static void stop_loop_cb(uv_signal_t* signal, int signum) {
+ ASSERT(signum == SIGPIPE);
+ uv_stop(signal->loop);
+}
+
static void signal_cb(uv_signal_t* signal, int signum) {
ASSERT(0);
}
@@ -91,4 +96,24 @@ TEST_IMPL(signal_pending_on_close) {
return 0;
}
-#endif \ No newline at end of file
+
+TEST_IMPL(signal_close_loop_alive) {
+ ASSERT(0 == uv_loop_init(&loop));
+ ASSERT(0 == uv_signal_init(&loop, &signal_hdl));
+ ASSERT(0 == uv_signal_start(&signal_hdl, stop_loop_cb, SIGPIPE));
+ uv_unref((uv_handle_t*) &signal_hdl);
+
+ ASSERT(0 == uv_kill(uv_os_getpid(), SIGPIPE));
+ ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT));
+ uv_close((uv_handle_t*) &signal_hdl, close_cb);
+ ASSERT(1 == uv_loop_alive(&loop));
+
+ ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT));
+ ASSERT(0 == uv_loop_close(&loop));
+ ASSERT(1 == close_cb_called);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+#endif
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index be9e2539aa..2b7f5d56d2 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/test/test-spawn.c
@@ -1420,6 +1420,8 @@ TEST_IMPL(spawn_setuid_fails) {
int r;
/* if root, become nobody. */
+ /* On IBMi PASE, there is no nobody user. */
+#ifndef __PASE__
uv_uid_t uid = getuid();
if (uid == 0) {
struct passwd* pw;
@@ -1428,11 +1430,19 @@ TEST_IMPL(spawn_setuid_fails) {
ASSERT(0 == setgid(pw->pw_gid));
ASSERT(0 == setuid(pw->pw_uid));
}
+#endif /* !__PASE__ */
init_process_options("spawn_helper1", fail_cb);
options.flags |= UV_PROCESS_SETUID;
+ /* On IBMi PASE, there is no root user. User may grant
+ * root-like privileges, including setting uid to 0.
+ */
+#if defined(__PASE__)
+ options.uid = -1;
+#else
options.uid = 0;
+#endif
/* These flags should be ignored on Unices. */
options.flags |= UV_PROCESS_WINDOWS_HIDE;
@@ -1441,7 +1451,7 @@ TEST_IMPL(spawn_setuid_fails) {
options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
r = uv_spawn(uv_default_loop(), &process, &options);
-#if defined(__CYGWIN__)
+#if defined(__CYGWIN__) || defined(__PASE__)
ASSERT(r == UV_EINVAL);
#else
ASSERT(r == UV_EPERM);
@@ -1461,6 +1471,8 @@ TEST_IMPL(spawn_setgid_fails) {
int r;
/* if root, become nobody. */
+ /* On IBMi PASE, there is no nobody user. */
+#ifndef __PASE__
uv_uid_t uid = getuid();
if (uid == 0) {
struct passwd* pw;
@@ -1469,18 +1481,22 @@ TEST_IMPL(spawn_setgid_fails) {
ASSERT(0 == setgid(pw->pw_gid));
ASSERT(0 == setuid(pw->pw_uid));
}
+#endif /* !__PASE__ */
init_process_options("spawn_helper1", fail_cb);
options.flags |= UV_PROCESS_SETGID;
-#if defined(__MVS__)
+ /* On IBMi PASE, there is no root user. User may grant
+ * root-like privileges, including setting gid to 0.
+ */
+#if defined(__MVS__) || defined(__PASE__)
options.gid = -1;
#else
options.gid = 0;
#endif
r = uv_spawn(uv_default_loop(), &process, &options);
-#if defined(__CYGWIN__) || defined(__MVS__)
+#if defined(__CYGWIN__) || defined(__MVS__) || defined(__PASE__)
ASSERT(r == UV_EINVAL);
#else
ASSERT(r == UV_EPERM);
diff --git a/deps/uv/test/test-stdio-over-pipes.c b/deps/uv/test/test-stdio-over-pipes.c
index a130ff6a9b..1aed471227 100644
--- a/deps/uv/test/test-stdio-over-pipes.c
+++ b/deps/uv/test/test-stdio-over-pipes.c
@@ -94,7 +94,7 @@ static void after_write(uv_write_t* req, int status) {
}
-static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* rdbuf) {
+static void on_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* rdbuf) {
uv_write_t* req;
uv_buf_t wrbuf;
int r;
@@ -103,11 +103,11 @@ static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* rdbuf) {
if (nread > 0) {
output_used += nread;
- if (output_used == 12) {
+ if (output_used % 12 == 0) {
ASSERT(memcmp("hello world\n", output, 12) == 0);
- wrbuf = uv_buf_init(output, output_used);
+ wrbuf = uv_buf_init(output, 12);
req = malloc(sizeof(*req));
- r = uv_write(req, (uv_stream_t*)&in, &wrbuf, 1, after_write);
+ r = uv_write(req, (uv_stream_t*) &in, &wrbuf, 1, after_write);
ASSERT(r == 0);
}
}
@@ -116,10 +116,10 @@ static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* rdbuf) {
}
-TEST_IMPL(stdio_over_pipes) {
+static void test_stdio_over_pipes(int overlapped) {
int r;
uv_process_t process;
- uv_stdio_container_t stdio[2];
+ uv_stdio_container_t stdio[3];
loop = uv_default_loop();
@@ -129,11 +129,15 @@ TEST_IMPL(stdio_over_pipes) {
uv_pipe_init(loop, &in, 0);
options.stdio = stdio;
- options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
- options.stdio[0].data.stream = (uv_stream_t*)&in;
- options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
- options.stdio[1].data.stream = (uv_stream_t*)&out;
- options.stdio_count = 2;
+ options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE |
+ (overlapped ? UV_OVERLAPPED_PIPE : 0);
+ options.stdio[0].data.stream = (uv_stream_t*) &in;
+ options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE |
+ (overlapped ? UV_OVERLAPPED_PIPE : 0);
+ options.stdio[1].data.stream = (uv_stream_t*) &out;
+ options.stdio[2].flags = UV_INHERIT_FD;
+ options.stdio[2].data.fd = 2;
+ options.stdio_count = 3;
r = uv_spawn(loop, &process, &options);
ASSERT(r == 0);
@@ -145,13 +149,22 @@ TEST_IMPL(stdio_over_pipes) {
ASSERT(r == 0);
ASSERT(on_read_cb_called > 1);
- ASSERT(after_write_cb_called == 1);
+ ASSERT(after_write_cb_called == 2);
ASSERT(exit_cb_called == 1);
ASSERT(close_cb_called == 3);
- ASSERT(memcmp("hello world\n", output, 12) == 0);
- ASSERT(output_used == 12);
+ ASSERT(memcmp("hello world\nhello world\n", output, 24) == 0);
+ ASSERT(output_used == 24);
MAKE_VALGRIND_HAPPY();
+}
+
+TEST_IMPL(stdio_over_pipes) {
+ test_stdio_over_pipes(0);
+ return 0;
+}
+
+TEST_IMPL(stdio_emulate_iocp) {
+ test_stdio_over_pipes(1);
return 0;
}
@@ -160,18 +173,19 @@ TEST_IMPL(stdio_over_pipes) {
static int on_pipe_read_called;
static int after_write_called;
-static uv_pipe_t stdin_pipe;
-static uv_pipe_t stdout_pipe;
+static uv_pipe_t stdin_pipe1;
+static uv_pipe_t stdout_pipe1;
+static uv_pipe_t stdin_pipe2;
+static uv_pipe_t stdout_pipe2;
-static void on_pipe_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
+static void on_pipe_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* buf) {
ASSERT(nread > 0);
ASSERT(memcmp("hello world\n", buf->base, nread) == 0);
on_pipe_read_called++;
free(buf->base);
- uv_close((uv_handle_t*)&stdin_pipe, close_cb);
- uv_close((uv_handle_t*)&stdout_pipe, close_cb);
+ uv_read_stop(pipe);
}
@@ -204,52 +218,81 @@ int stdio_over_pipes_helper(void) {
uv_write_t write_req[ARRAY_SIZE(buffers)];
uv_buf_t buf[ARRAY_SIZE(buffers)];
unsigned int i;
+ int j;
int r;
uv_loop_t* loop = uv_default_loop();
ASSERT(UV_NAMED_PIPE == uv_guess_handle(0));
ASSERT(UV_NAMED_PIPE == uv_guess_handle(1));
- r = uv_pipe_init(loop, &stdin_pipe, 0);
+ r = uv_pipe_init(loop, &stdin_pipe1, 0);
+ ASSERT(r == 0);
+ r = uv_pipe_init(loop, &stdout_pipe1, 0);
+ ASSERT(r == 0);
+ r = uv_pipe_init(loop, &stdin_pipe2, 0);
ASSERT(r == 0);
- r = uv_pipe_init(loop, &stdout_pipe, 0);
+ r = uv_pipe_init(loop, &stdout_pipe2, 0);
ASSERT(r == 0);
- uv_pipe_open(&stdin_pipe, 0);
- uv_pipe_open(&stdout_pipe, 1);
+ uv_pipe_open(&stdin_pipe1, 0);
+ uv_pipe_open(&stdout_pipe1, 1);
+ uv_pipe_open(&stdin_pipe2, 0);
+ uv_pipe_open(&stdout_pipe2, 1);
- /* Unref both stdio handles to make sure that all writes complete. */
- uv_unref((uv_handle_t*)&stdin_pipe);
- uv_unref((uv_handle_t*)&stdout_pipe);
+ for (j = 0; j < 2; j++) {
+ /* Unref both stdio handles to make sure that all writes complete. */
+ uv_unref((uv_handle_t*) &stdin_pipe1);
+ uv_unref((uv_handle_t*) &stdout_pipe1);
+ uv_unref((uv_handle_t*) &stdin_pipe2);
+ uv_unref((uv_handle_t*) &stdout_pipe2);
- for (i = 0; i < ARRAY_SIZE(buffers); i++) {
- buf[i] = uv_buf_init((char*)buffers[i], strlen(buffers[i]));
- }
+ for (i = 0; i < ARRAY_SIZE(buffers); i++) {
+ buf[i] = uv_buf_init((char*) buffers[i], strlen(buffers[i]));
+ }
- for (i = 0; i < ARRAY_SIZE(buffers); i++) {
- r = uv_write(&write_req[i], (uv_stream_t*)&stdout_pipe, &buf[i], 1,
- after_pipe_write);
- ASSERT(r == 0);
- }
+ for (i = 0; i < ARRAY_SIZE(buffers); i++) {
+ r = uv_write(&write_req[i],
+ (uv_stream_t*) (j == 0 ? &stdout_pipe1 : &stdout_pipe2),
+ &buf[i],
+ 1,
+ after_pipe_write);
+ ASSERT(r == 0);
+ }
- notify_parent_process();
- uv_run(loop, UV_RUN_DEFAULT);
+ notify_parent_process();
+ uv_run(loop, UV_RUN_DEFAULT);
- ASSERT(after_write_called == 7);
- ASSERT(on_pipe_read_called == 0);
- ASSERT(close_cb_called == 0);
+ ASSERT(after_write_called == 7 * (j + 1));
+ ASSERT(on_pipe_read_called == j);
+ ASSERT(close_cb_called == 0);
- uv_ref((uv_handle_t*)&stdout_pipe);
- uv_ref((uv_handle_t*)&stdin_pipe);
+ uv_ref((uv_handle_t*) &stdout_pipe1);
+ uv_ref((uv_handle_t*) &stdin_pipe1);
+ uv_ref((uv_handle_t*) &stdout_pipe2);
+ uv_ref((uv_handle_t*) &stdin_pipe2);
- r = uv_read_start((uv_stream_t*)&stdin_pipe, on_read_alloc, on_pipe_read);
- ASSERT(r == 0);
+ r = uv_read_start((uv_stream_t*) (j == 0 ? &stdin_pipe1 : &stdin_pipe2),
+ on_read_alloc,
+ on_pipe_read);
+ ASSERT(r == 0);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ ASSERT(after_write_called == 7 * (j + 1));
+ ASSERT(on_pipe_read_called == j + 1);
+ ASSERT(close_cb_called == 0);
+ }
+
+ uv_close((uv_handle_t*)&stdin_pipe1, close_cb);
+ uv_close((uv_handle_t*)&stdout_pipe1, close_cb);
+ uv_close((uv_handle_t*)&stdin_pipe2, close_cb);
+ uv_close((uv_handle_t*)&stdout_pipe2, close_cb);
uv_run(loop, UV_RUN_DEFAULT);
- ASSERT(after_write_called == 7);
- ASSERT(on_pipe_read_called == 1);
- ASSERT(close_cb_called == 2);
+ ASSERT(after_write_called == 14);
+ ASSERT(on_pipe_read_called == 2);
+ ASSERT(close_cb_called == 4);
MAKE_VALGRIND_HAPPY();
return 0;
diff --git a/deps/uv/test/test-tty-escape-sequence-processing.c b/deps/uv/test/test-tty-escape-sequence-processing.c
new file mode 100644
index 0000000000..c4461e91e0
--- /dev/null
+++ b/deps/uv/test/test-tty-escape-sequence-processing.c
@@ -0,0 +1,1621 @@
+/* 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.
+ */
+
+#ifdef _WIN32
+
+#include "task.h"
+#include "uv.h"
+
+#include <io.h>
+#include <windows.h>
+
+#include <errno.h>
+#include <string.h>
+
+#define ESC "\033"
+#define CSI ESC "["
+#define ST ESC "\\"
+#define BEL "\x07"
+#define HELLO "Hello"
+
+#define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
+#define FOREGROUND_BLACK 0
+#define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN)
+#define FOREGROUND_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE)
+#define FOREGROUND_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE)
+#define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
+#define BACKGROUND_BLACK 0
+#define BACKGROUND_YELLOW (BACKGROUND_RED | BACKGROUND_GREEN)
+#define BACKGROUND_CYAN (BACKGROUND_GREEN | BACKGROUND_BLUE)
+#define BACKGROUND_MAGENTA (BACKGROUND_RED | BACKGROUND_BLUE)
+
+#define F_INTENSITY 1
+#define FB_INTENSITY 2
+#define B_INTENSITY 5
+#define INVERSE 7
+#define F_INTENSITY_OFF1 21
+#define F_INTENSITY_OFF2 22
+#define B_INTENSITY_OFF 25
+#define INVERSE_OFF 27
+#define F_BLACK 30
+#define F_RED 31
+#define F_GREEN 32
+#define F_YELLOW 33
+#define F_BLUE 34
+#define F_MAGENTA 35
+#define F_CYAN 36
+#define F_WHITE 37
+#define F_DEFAULT 39
+#define B_BLACK 40
+#define B_RED 41
+#define B_GREEN 42
+#define B_YELLOW 43
+#define B_BLUE 44
+#define B_MAGENTA 45
+#define B_CYAN 46
+#define B_WHITE 47
+#define B_DEFAULT 49
+
+#define CURSOR_SIZE_SMALL 25
+#define CURSOR_SIZE_MIDDLE 50
+#define CURSOR_SIZE_LARGE 100
+
+struct screen_info {
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ int top;
+ int width;
+ int height;
+ int length;
+ WORD default_attr;
+};
+
+struct captured_screen {
+ char* text;
+ WORD* attributes;
+ struct screen_info si;
+};
+
+static void get_screen_info(uv_tty_t* tty_out, struct screen_info* si) {
+ ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &(si->csbi)));
+ si->width = si->csbi.dwSize.X;
+ si->height = si->csbi.srWindow.Bottom - si->csbi.srWindow.Top + 1;
+ si->length = si->width * si->height;
+ si->default_attr = si->csbi.wAttributes;
+ si->top = si->csbi.srWindow.Top;
+}
+
+static void set_cursor_position(uv_tty_t* tty_out, COORD pos) {
+ HANDLE handle = tty_out->handle;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ ASSERT(GetConsoleScreenBufferInfo(handle, &info));
+ pos.X -= 1;
+ pos.Y += info.srWindow.Top - 1;
+ ASSERT(SetConsoleCursorPosition(handle, pos));
+}
+
+static void get_cursor_position(uv_tty_t* tty_out, COORD* cursor_position) {
+ HANDLE handle = tty_out->handle;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ ASSERT(GetConsoleScreenBufferInfo(handle, &info));
+ cursor_position->X = info.dwCursorPosition.X + 1;
+ cursor_position->Y = info.dwCursorPosition.Y - info.srWindow.Top + 1;
+}
+
+static void set_cursor_to_home(uv_tty_t* tty_out) {
+ COORD origin = {1, 1};
+ set_cursor_position(tty_out, origin);
+}
+
+static CONSOLE_CURSOR_INFO get_cursor_info(uv_tty_t* tty_out) {
+ HANDLE handle = tty_out->handle;
+ CONSOLE_CURSOR_INFO info;
+ ASSERT(GetConsoleCursorInfo(handle, &info));
+ return info;
+}
+
+static void set_cursor_size(uv_tty_t* tty_out, DWORD size) {
+ CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
+ info.dwSize = size;
+ ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
+}
+
+static DWORD get_cursor_size(uv_tty_t* tty_out) {
+ return get_cursor_info(tty_out).dwSize;
+}
+
+static void set_cursor_visibility(uv_tty_t* tty_out, BOOL visible) {
+ CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
+ info.bVisible = visible;
+ ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
+}
+
+static BOOL get_cursor_visibility(uv_tty_t* tty_out) {
+ return get_cursor_info(tty_out).bVisible;
+}
+
+static BOOL is_scrolling(uv_tty_t* tty_out, struct screen_info si) {
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
+ return info.srWindow.Top != si.top;
+}
+
+static void write_console(uv_tty_t* tty_out, char* src) {
+ int r;
+ uv_buf_t buf;
+
+ buf.base = src;
+ buf.len = strlen(buf.base);
+
+ r = uv_try_write((uv_stream_t*) tty_out, &buf, 1);
+ ASSERT(r >= 0);
+ ASSERT((unsigned int) r == buf.len);
+}
+
+static void setup_screen(uv_tty_t* tty_out) {
+ DWORD length, number_of_written;
+ COORD origin;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
+ length = info.dwSize.X * (info.srWindow.Bottom - info.srWindow.Top + 1);
+ origin.X = 0;
+ origin.Y = info.srWindow.Top;
+ ASSERT(FillConsoleOutputCharacter(
+ tty_out->handle, '.', length, origin, &number_of_written));
+ ASSERT(length == number_of_written);
+}
+
+static void clear_screen(uv_tty_t* tty_out, struct screen_info* si) {
+ DWORD length, number_of_written;
+ COORD origin;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
+ length = (info.srWindow.Bottom - info.srWindow.Top + 1) * info.dwSize.X - 1;
+ origin.X = 0;
+ origin.Y = info.srWindow.Top;
+ FillConsoleOutputCharacterA(
+ tty_out->handle, ' ', length, origin, &number_of_written);
+ ASSERT(length == number_of_written);
+ FillConsoleOutputAttribute(
+ tty_out->handle, si->default_attr, length, origin, &number_of_written);
+ ASSERT(length == number_of_written);
+}
+
+static void free_screen(struct captured_screen* cs) {
+ free(cs->text);
+ cs->text = NULL;
+ free(cs->attributes);
+ cs->attributes = NULL;
+}
+
+static void capture_screen(uv_tty_t* tty_out, struct captured_screen* cs) {
+ DWORD length;
+ COORD origin;
+ get_screen_info(tty_out, &(cs->si));
+ origin.X = 0;
+ origin.Y = cs->si.csbi.srWindow.Top;
+ cs->text = malloc(cs->si.length * sizeof(*cs->text));
+ ASSERT(cs->text != NULL);
+ cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes));
+ ASSERT(cs->attributes != NULL);
+ ASSERT(ReadConsoleOutputCharacter(
+ tty_out->handle, cs->text, cs->si.length, origin, &length));
+ ASSERT((unsigned int) cs->si.length == length);
+ ASSERT(ReadConsoleOutputAttribute(
+ tty_out->handle, cs->attributes, cs->si.length, origin, &length));
+ ASSERT((unsigned int) cs->si.length == length);
+}
+
+static void make_expect_screen_erase(struct captured_screen* cs,
+ COORD cursor_position,
+ int dir,
+ BOOL entire_screen) {
+ /* beginning of line */
+ char* start;
+ char* end;
+ start = cs->text + cs->si.width * (cursor_position.Y - 1);
+ if (dir == 0) {
+ if (entire_screen) {
+ /* erase to end of screen */
+ end = cs->text + cs->si.length;
+ } else {
+ /* erase to end of line */
+ end = start + cs->si.width;
+ }
+ /* erase from postition of cursor */
+ start += cursor_position.X - 1;
+ } else if (dir == 1) {
+ /* erase to position of cursor */
+ end = start + cursor_position.X;
+ if (entire_screen) {
+ /* erase form beginning of screen */
+ start = cs->text;
+ }
+ } else if (dir == 2) {
+ if (entire_screen) {
+ /* erase form beginning of screen */
+ start = cs->text;
+ /* erase to end of screen */
+ end = cs->text + cs->si.length;
+ } else {
+ /* erase to end of line */
+ end = start + cs->si.width;
+ }
+ } else {
+ ASSERT(FALSE);
+ }
+ ASSERT(start < end);
+ ASSERT(end - cs->text <= cs->si.length);
+ for (; start < end; start++) {
+ *start = ' ';
+ }
+}
+
+static void make_expect_screen_write(struct captured_screen* cs,
+ COORD cursor_position,
+ const char* text) {
+ /* postion of cursor */
+ char* start;
+ start = cs->text + cs->si.width * (cursor_position.Y - 1) +
+ cursor_position.X - 1;
+ size_t length = strlen(text);
+ size_t remain_length = cs->si.length - (cs->text - start);
+ length = length > remain_length ? remain_length : length;
+ memcpy(start, text, length);
+}
+
+static void make_expect_screen_set_attr(struct captured_screen* cs,
+ COORD cursor_position,
+ size_t length,
+ WORD attr) {
+ WORD* start;
+ start = cs->attributes + cs->si.width * (cursor_position.Y - 1) +
+ cursor_position.X - 1;
+ size_t remain_length = cs->si.length - (cs->attributes - start);
+ length = length > remain_length ? remain_length : length;
+ while (length) {
+ *start = attr;
+ start++;
+ length--;
+ }
+}
+
+static BOOL compare_screen(uv_tty_t* tty_out,
+ struct captured_screen* actual,
+ struct captured_screen* expect) {
+ int line, col;
+ BOOL result = TRUE;
+ int current = 0;
+ ASSERT(actual->text);
+ ASSERT(actual->attributes);
+ ASSERT(expect->text);
+ ASSERT(expect->attributes);
+ if (actual->si.length != expect->si.length) {
+ return FALSE;
+ }
+ if (actual->si.width != expect->si.width) {
+ return FALSE;
+ }
+ if (actual->si.height != expect->si.height) {
+ return FALSE;
+ }
+ while (current < actual->si.length) {
+ if (*(actual->text + current) != *(expect->text + current)) {
+ line = current / actual->si.width + 1;
+ col = current - actual->si.width * (line - 1) + 1;
+ fprintf(stderr,
+ "line:%d col:%d expected character '%c' but found '%c'\n",
+ line,
+ col,
+ *(expect->text + current),
+ *(actual->text + current));
+ result = FALSE;
+ }
+ if (*(actual->attributes + current) != *(expect->attributes + current)) {
+ line = current / actual->si.width + 1;
+ col = current - actual->si.width * (line - 1) + 1;
+ fprintf(stderr,
+ "line:%d col:%d expected attributes '%u' but found '%u'\n",
+ line,
+ col,
+ *(expect->attributes + current),
+ *(actual->attributes + current));
+ result = FALSE;
+ }
+ current++;
+ }
+ clear_screen(tty_out, &expect->si);
+ free_screen(expect);
+ free_screen(actual);
+ return result;
+}
+
+static void initialize_tty(uv_tty_t* tty_out) {
+ int r;
+ int ttyout_fd;
+ /* Make sure we have an FD that refers to a tty */
+ HANDLE handle;
+
+ uv_tty_set_vterm_state(UV_TTY_UNSUPPORTED);
+
+ handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CONSOLE_TEXTMODE_BUFFER,
+ NULL);
+ ASSERT(handle != INVALID_HANDLE_VALUE);
+
+ ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
+ ASSERT(ttyout_fd >= 0);
+ ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
+ r = uv_tty_init(uv_default_loop(), tty_out, ttyout_fd, 0); /* Writable. */
+ ASSERT(r == 0);
+}
+
+static void terminate_tty(uv_tty_t* tty_out) {
+ set_cursor_to_home(tty_out);
+ uv_close((uv_handle_t*) tty_out, NULL);
+}
+
+TEST_IMPL(tty_cursor_up) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* cursor up one times if omitted arguments */
+ snprintf(buffer, sizeof(buffer), "%sA", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+
+ /* cursor up nth times */
+ cursor_pos_old = cursor_pos;
+ snprintf(buffer, sizeof(buffer), "%s%dA", CSI, si.height / 4);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+
+ /* cursor up from Window top does nothing */
+ cursor_pos_old.X = 1;
+ cursor_pos_old.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer, sizeof(buffer), "%sA", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+ ASSERT(!is_scrolling(&tty_out, si));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_cursor_down) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* cursor down one times if omitted arguments */
+ snprintf(buffer, sizeof(buffer), "%sB", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+
+ /* cursor down nth times */
+ cursor_pos_old = cursor_pos;
+ snprintf(buffer, sizeof(buffer), "%s%dB", CSI, si.height / 4);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+
+ /* cursor down from bottom line does nothing */
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer, sizeof(buffer), "%sB", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+ ASSERT(!is_scrolling(&tty_out, si));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_cursor_forward) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* cursor forward one times if omitted arguments */
+ snprintf(buffer, sizeof(buffer), "%sC", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X + 1 == cursor_pos.X);
+
+ /* cursor forward nth times */
+ cursor_pos_old = cursor_pos;
+ snprintf(buffer, sizeof(buffer), "%s%dC", CSI, si.width / 4);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X + si.width / 4 == cursor_pos.X);
+
+ /* cursor forward from end of line does nothing*/
+ cursor_pos_old.X = si.width;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer, sizeof(buffer), "%sC", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+
+ /* cursor forward from end of screen does nothing */
+ cursor_pos_old.X = si.width;
+ cursor_pos_old.Y = si.height;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer, sizeof(buffer), "%sC", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+ ASSERT(!is_scrolling(&tty_out, si));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_cursor_back) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* cursor back one times if omitted arguments */
+ snprintf(buffer, sizeof(buffer), "%sD", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X - 1 == cursor_pos.X);
+
+ /* cursor back nth times */
+ cursor_pos_old = cursor_pos;
+ snprintf(buffer, sizeof(buffer), "%s%dD", CSI, si.width / 4);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X - si.width / 4 == cursor_pos.X);
+
+ /* cursor back from beginning of line does nothing */
+ cursor_pos_old.X = 1;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer, sizeof(buffer), "%sD", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(cursor_pos_old.X == cursor_pos.X);
+
+ /* cursor back from top of screen does nothing */
+ cursor_pos_old.X = 1;
+ cursor_pos_old.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer, sizeof(buffer), "%sD", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(1 == cursor_pos.Y);
+ ASSERT(1 == cursor_pos.X);
+ ASSERT(!is_scrolling(&tty_out, si));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_cursor_next_line) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* cursor next line one times if omitted arguments */
+ snprintf(buffer, sizeof(buffer), "%sE", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y);
+ ASSERT(1 == cursor_pos.X);
+
+ /* cursor next line nth times */
+ cursor_pos_old = cursor_pos;
+ snprintf(buffer, sizeof(buffer), "%s%dE", CSI, si.height / 4);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
+ ASSERT(1 == cursor_pos.X);
+
+ /* cursor next line from buttom row moves beginning of line */
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer, sizeof(buffer), "%sE", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+ ASSERT(1 == cursor_pos.X);
+ ASSERT(!is_scrolling(&tty_out, si));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_cursor_previous_line) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* cursor previous line one times if omitted arguments */
+ snprintf(buffer, sizeof(buffer), "%sF", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y);
+ ASSERT(1 == cursor_pos.X);
+
+ /* cursor previous line nth times */
+ cursor_pos_old = cursor_pos;
+ snprintf(buffer, sizeof(buffer), "%s%dF", CSI, si.height / 4);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
+ ASSERT(1 == cursor_pos.X);
+
+ /* cursor previous line from top of screen does nothing */
+ cursor_pos_old.X = 1;
+ cursor_pos_old.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer, sizeof(buffer), "%sD", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(1 == cursor_pos.Y);
+ ASSERT(1 == cursor_pos.X);
+ ASSERT(!is_scrolling(&tty_out, si));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_cursor_horizontal_move_absolute) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* Move to beginning of line if omitted argument */
+ snprintf(buffer, sizeof(buffer), "%sG", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(1 == cursor_pos.X);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+
+ /* Move cursor to nth character */
+ snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width / 4);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(si.width / 4 == cursor_pos.X);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+
+ /* Moving out of screen will fit within screen */
+ snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width + 1);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(si.width == cursor_pos.X);
+ ASSERT(cursor_pos_old.Y == cursor_pos.Y);
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_cursor_move_absolute) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos.X = si.width / 2;
+ cursor_pos.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos);
+
+ /* Move the cursor to home if omitted arguments */
+ snprintf(buffer, sizeof(buffer), "%sH", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(1 == cursor_pos.X);
+ ASSERT(1 == cursor_pos.Y);
+
+ /* Move the cursor to the middle of the screen */
+ snprintf(
+ buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width / 2);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(si.width / 2 == cursor_pos.X);
+ ASSERT(si.height / 2 == cursor_pos.Y);
+
+ /* Moving out of screen will fit within screen */
+ snprintf(
+ buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width + 1);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(si.width == cursor_pos.X);
+ ASSERT(si.height / 2 == cursor_pos.Y);
+
+ snprintf(
+ buffer, sizeof(buffer), "%s%d;%df", CSI, si.height + 1, si.width / 2);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(si.width / 2 == cursor_pos.X);
+ ASSERT(si.height == cursor_pos.Y);
+ ASSERT(!is_scrolling(&tty_out, si));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_hide_show_cursor) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ char buffer[1024];
+ BOOL saved_cursor_visibility;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+
+ saved_cursor_visibility = get_cursor_visibility(&tty_out);
+
+ /* Hide the cursor */
+ set_cursor_visibility(&tty_out, TRUE);
+ snprintf(buffer, sizeof(buffer), "%s?25l", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(!get_cursor_visibility(&tty_out));
+
+ /* Show the cursor */
+ set_cursor_visibility(&tty_out, FALSE);
+ snprintf(buffer, sizeof(buffer), "%s?25h", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_visibility(&tty_out));
+
+ set_cursor_visibility(&tty_out, saved_cursor_visibility);
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_erase) {
+ int dir;
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos;
+ char buffer[1024];
+ struct captured_screen actual = {0}, expect = {0};
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+
+ /* Erase to below if omitted argument */
+ dir = 0;
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%sJ", CSI);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Erase to below(dir = 0) */
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Erase to above */
+ dir = 1;
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Erase All */
+ dir = 2;
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_erase_line) {
+ int dir;
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos;
+ char buffer[1024];
+ struct captured_screen actual = {0}, expect = {0};
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+
+ /* Erase to right if omitted arguments */
+ dir = 0;
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%sK", CSI);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Erase to right(dir = 0) */
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Erase to Left */
+ dir = 1;
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Erase All */
+ dir = 2;
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_set_cursor_shape) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ DWORD saved_cursor_size;
+ char buffer[1024];
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+
+ saved_cursor_size = get_cursor_size(&tty_out);
+
+ /* cursor size large if omitted arguments */
+ set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
+ snprintf(buffer, sizeof(buffer), "%s q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
+
+ /* cursor size large */
+ set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
+ snprintf(buffer, sizeof(buffer), "%s1 q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
+ set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
+ snprintf(buffer, sizeof(buffer), "%s2 q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
+
+ /* cursor size small */
+ set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
+ snprintf(buffer, sizeof(buffer), "%s3 q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL);
+ set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
+ snprintf(buffer, sizeof(buffer), "%s6 q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL);
+
+ /* Nothing occurs with arguments outside valid range */
+ set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
+ snprintf(buffer, sizeof(buffer), "%s7 q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
+
+ /* restore cursor size if arguments is zero */
+ snprintf(buffer, sizeof(buffer), "%s0 q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_set_style) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos;
+ char buffer[1024];
+ struct captured_screen actual = {0}, expect = {0};
+ WORD fg, bg;
+ WORD fg_attrs[9][2] = {{F_BLACK, FOREGROUND_BLACK},
+ {F_RED, FOREGROUND_RED},
+ {F_GREEN, FOREGROUND_GREEN},
+ {F_YELLOW, FOREGROUND_YELLOW},
+ {F_BLUE, FOREGROUND_BLUE},
+ {F_MAGENTA, FOREGROUND_MAGENTA},
+ {F_CYAN, FOREGROUND_CYAN},
+ {F_WHITE, FOREGROUND_WHITE},
+ {F_DEFAULT, 0}};
+ WORD bg_attrs[9][2] = {{B_DEFAULT, 0},
+ {B_BLACK, BACKGROUND_BLACK},
+ {B_RED, BACKGROUND_RED},
+ {B_GREEN, BACKGROUND_GREEN},
+ {B_YELLOW, BACKGROUND_YELLOW},
+ {B_BLUE, BACKGROUND_BLUE},
+ {B_MAGENTA, BACKGROUND_MAGENTA},
+ {B_CYAN, BACKGROUND_CYAN},
+ {B_WHITE, BACKGROUND_WHITE}};
+ WORD attr;
+ int i, length;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+
+ capture_screen(&tty_out, &expect);
+ fg_attrs[8][1] = expect.si.default_attr & FOREGROUND_WHITE;
+ bg_attrs[0][1] = expect.si.default_attr & BACKGROUND_WHITE;
+
+ /* Set foreground color */
+ length = ARRAY_SIZE(fg_attrs);
+ for (i = 0; i < length; i++) {
+ capture_screen(&tty_out, &expect);
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ attr = (expect.si.default_attr & ~FOREGROUND_WHITE) | fg_attrs[i][1];
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(
+ buffer, sizeof(buffer), "%s%dm%s%sm", CSI, fg_attrs[i][0], HELLO, CSI);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+ }
+
+ /* Set background color */
+ length = ARRAY_SIZE(bg_attrs);
+ for (i = 0; i < length; i++) {
+ capture_screen(&tty_out, &expect);
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ attr = (expect.si.default_attr & ~BACKGROUND_WHITE) | bg_attrs[i][1];
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(
+ buffer, sizeof(buffer), "%s%dm%s%sm", CSI, bg_attrs[i][0], HELLO, CSI);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+ }
+
+ /* Set foregroud and background color */
+ ASSERT(ARRAY_SIZE(fg_attrs) == ARRAY_SIZE(bg_attrs));
+ length = ARRAY_SIZE(bg_attrs);
+ for (i = 0; i < length; i++) {
+ capture_screen(&tty_out, &expect);
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ attr = expect.si.default_attr & ~FOREGROUND_WHITE & ~BACKGROUND_WHITE;
+ attr |= fg_attrs[i][1] | bg_attrs[i][1];
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
+
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s%d;%dm%s%sm",
+ CSI,
+ bg_attrs[i][0],
+ fg_attrs[i][0],
+ HELLO,
+ CSI);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+ }
+
+ /* Set foreground bright on */
+ capture_screen(&tty_out, &expect);
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos);
+ attr = expect.si.default_attr;
+ attr |= FOREGROUND_INTENSITY;
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s%dm%s%s%dm%s%dm%s%s%dm",
+ CSI,
+ F_INTENSITY,
+ HELLO,
+ CSI,
+ F_INTENSITY_OFF1,
+ CSI,
+ F_INTENSITY,
+ HELLO,
+ CSI,
+ F_INTENSITY_OFF2);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Set background bright on */
+ capture_screen(&tty_out, &expect);
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos);
+ attr = expect.si.default_attr;
+ attr |= BACKGROUND_INTENSITY;
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s%dm%s%s%dm",
+ CSI,
+ B_INTENSITY,
+ HELLO,
+ CSI,
+ B_INTENSITY_OFF);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Inverse */
+ capture_screen(&tty_out, &expect);
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos);
+ attr = expect.si.default_attr;
+ fg = attr & FOREGROUND_WHITE;
+ bg = attr & BACKGROUND_WHITE;
+ attr &= (~FOREGROUND_WHITE & ~BACKGROUND_WHITE);
+ attr |= COMMON_LVB_REVERSE_VIDEO;
+ attr |= fg << 4;
+ attr |= bg >> 4;
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s%dm%s%s%dm%s",
+ CSI,
+ INVERSE,
+ HELLO,
+ CSI,
+ INVERSE_OFF,
+ HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_save_restore_cursor_position) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ char buffer[1024];
+ struct screen_info si;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+ get_screen_info(&tty_out, &si);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* save the cursor position */
+ snprintf(buffer, sizeof(buffer), "%ss", CSI);
+ write_console(&tty_out, buffer);
+
+ cursor_pos.X = si.width / 4;
+ cursor_pos.Y = si.height / 4;
+ set_cursor_position(&tty_out, cursor_pos);
+
+ /* restore the cursor postion */
+ snprintf(buffer, sizeof(buffer), "%su", CSI);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos.X == cursor_pos_old.X);
+ ASSERT(cursor_pos.Y == cursor_pos_old.Y);
+
+ cursor_pos_old.X = si.width / 2;
+ cursor_pos_old.Y = si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+
+ /* save the cursor position */
+ snprintf(buffer, sizeof(buffer), "%s7", ESC);
+ write_console(&tty_out, buffer);
+
+ cursor_pos.X = si.width / 4;
+ cursor_pos.Y = si.height / 4;
+ set_cursor_position(&tty_out, cursor_pos);
+
+ /* restore the cursor postion */
+ snprintf(buffer, sizeof(buffer), "%s8", ESC);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos.X == cursor_pos_old.X);
+ ASSERT(cursor_pos.Y == cursor_pos_old.Y);
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_full_reset) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ char buffer[1024];
+ struct captured_screen actual = {0}, expect = {0};
+ COORD cursor_pos;
+ DWORD saved_cursor_size;
+ BOOL saved_cursor_visibility;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+
+ capture_screen(&tty_out, &expect);
+ setup_screen(&tty_out);
+ cursor_pos.X = expect.si.width;
+ cursor_pos.Y = expect.si.height;
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%s%d;%dm%s", CSI, F_CYAN, B_YELLOW, HELLO);
+ saved_cursor_size = get_cursor_size(&tty_out);
+ set_cursor_size(&tty_out,
+ saved_cursor_size == CURSOR_SIZE_LARGE ? CURSOR_SIZE_SMALL
+ : CURSOR_SIZE_LARGE);
+ saved_cursor_visibility = get_cursor_visibility(&tty_out);
+ set_cursor_visibility(&tty_out, saved_cursor_visibility ? FALSE : TRUE);
+ write_console(&tty_out, buffer);
+ snprintf(buffer, sizeof(buffer), "%sc", ESC);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+ ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
+ ASSERT(get_cursor_visibility(&tty_out) == saved_cursor_visibility);
+ ASSERT(actual.si.csbi.srWindow.Top == 0);
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(tty_escape_sequence_processing) {
+ uv_tty_t tty_out;
+ uv_loop_t* loop;
+ COORD cursor_pos, cursor_pos_old;
+ DWORD saved_cursor_size;
+ char buffer[1024];
+ struct captured_screen actual = {0}, expect = {0};
+ int dir;
+
+ loop = uv_default_loop();
+
+ initialize_tty(&tty_out);
+
+ /* CSI + finaly byte does not output anything */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer, sizeof(buffer), "%s@%s%s~%s", CSI, HELLO, CSI, HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* CSI(C1) + finaly byte does not output anything */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer, sizeof(buffer), "\xC2\x9B@%s\xC2\x9B~%s", HELLO, HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* CSI + intermediate byte + finaly byte does not output anything */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* CSI + parameter byte + finaly byte does not output anything */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s0@%s%s>~%s%s?~%s",
+ CSI,
+ HELLO,
+ CSI,
+ HELLO,
+ CSI,
+ HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* ESC Single-char control does not output anyghing */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Nothing is output from ESC + ^, _, P, ] to BEL or ESC \ */
+ /* Operaging System Command */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer, sizeof(buffer), "%s]0;%s%s%s", ESC, HELLO, BEL, HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+ /* Device Control Sequence */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer, sizeof(buffer), "%sP$m%s%s", ESC, ST, HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+ /* Privacy Message */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s^\"%s\\\"%s\"%s%s",
+ ESC,
+ HELLO,
+ HELLO,
+ ST,
+ HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+ /* Application Program Command */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s_\"%s%s%s\"%s%s",
+ ESC,
+ HELLO,
+ ST,
+ HELLO,
+ BEL,
+ HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Ignore double escape */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ cursor_pos.X += strlen(HELLO);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s%s@%s%s%s~%s",
+ ESC,
+ CSI,
+ HELLO,
+ ESC,
+ CSI,
+ HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Ignored if argument overflow */
+ set_cursor_to_home(&tty_out);
+ snprintf(buffer, sizeof(buffer), "%s1;%dH", CSI, UINT16_MAX + 1);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos.X == 1);
+ ASSERT(cursor_pos.Y == 1);
+
+ /* Too many argument are ignored */
+ cursor_pos.X = 1;
+ cursor_pos.Y = 1;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s%d;%d;%d;%d;%dm%s%sm",
+ CSI,
+ F_RED,
+ F_INTENSITY,
+ INVERSE,
+ B_CYAN,
+ B_INTENSITY_OFF,
+ HELLO,
+ CSI);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* In the case of DECSCUSR, the others are ignored */
+ set_cursor_to_home(&tty_out);
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s%d;%d H",
+ CSI,
+ expect.si.height / 2,
+ expect.si.width / 2);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos.X == 1);
+ ASSERT(cursor_pos.Y == 1);
+
+ /* Invalid sequence are ignored */
+ saved_cursor_size = get_cursor_size(&tty_out);
+ set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
+ snprintf(buffer, sizeof(buffer), "%s 1q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
+ snprintf(buffer, sizeof(buffer), "%s 1 q", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
+ set_cursor_size(&tty_out, saved_cursor_size);
+
+ /* #1874 2. */
+ snprintf(buffer, sizeof(buffer), "%s??25l", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_visibility(&tty_out));
+ snprintf(buffer, sizeof(buffer), "%s25?l", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_visibility(&tty_out));
+ cursor_pos_old.X = expect.si.width / 2;
+ cursor_pos_old.Y = expect.si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos_old);
+ snprintf(buffer,
+ sizeof(buffer),
+ "%s??%d;%df",
+ CSI,
+ expect.si.height / 4,
+ expect.si.width / 4);
+ write_console(&tty_out, buffer);
+ get_cursor_position(&tty_out, &cursor_pos);
+ ASSERT(cursor_pos.X = cursor_pos_old.X);
+ ASSERT(cursor_pos.Y = cursor_pos_old.Y);
+ set_cursor_to_home(&tty_out);
+
+ /* CSI 25 l does nothing (#1874 4.) */
+ snprintf(buffer, sizeof(buffer), "%s25l", CSI);
+ write_console(&tty_out, buffer);
+ ASSERT(get_cursor_visibility(&tty_out));
+
+ /* Unsupported sequences are ignored(#1874 5.) */
+ dir = 2;
+ setup_screen(&tty_out);
+ capture_screen(&tty_out, &expect);
+ set_cursor_position(&tty_out, cursor_pos);
+ snprintf(buffer, sizeof(buffer), "%s?%dJ", CSI, dir);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ /* Finaly byte immedately after CSI [ are also output(#1874 1.) */
+ cursor_pos.X = expect.si.width / 2;
+ cursor_pos.Y = expect.si.height / 2;
+ set_cursor_position(&tty_out, cursor_pos);
+ capture_screen(&tty_out, &expect);
+ make_expect_screen_write(&expect, cursor_pos, HELLO);
+ snprintf(buffer, sizeof(buffer), "%s[%s", CSI, HELLO);
+ write_console(&tty_out, buffer);
+ capture_screen(&tty_out, &actual);
+ ASSERT(compare_screen(&tty_out, &actual, &expect));
+
+ terminate_tty(&tty_out);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+#else
+
+typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
+
+#endif /* ifdef _WIN32 */
diff --git a/deps/uv/test/test-udp-connect.c b/deps/uv/test/test-udp-connect.c
index f44634248f..58cf9475a4 100644
--- a/deps/uv/test/test-udp-connect.c
+++ b/deps/uv/test/test-udp-connect.c
@@ -98,6 +98,10 @@ static void sv_recv_cb(uv_udp_t* handle,
TEST_IMPL(udp_connect) {
+#if defined(__PASE__)
+ RETURN_SKIP(
+ "IBMi PASE's UDP connection can not be disconnected with AF_UNSPEC.");
+#endif
uv_udp_send_t req;
struct sockaddr_in ext_addr;
struct sockaddr_in tmp_addr;
diff --git a/deps/uv/test/test-udp-ipv6.c b/deps/uv/test/test-udp-ipv6.c
index 9d4db2bc4f..7099953097 100644
--- a/deps/uv/test/test-udp-ipv6.c
+++ b/deps/uv/test/test-udp-ipv6.c
@@ -41,11 +41,13 @@
static uv_udp_t client;
static uv_udp_t server;
static uv_udp_send_t req_;
+static char data[10];
static uv_timer_t timeout;
static int send_cb_called;
static int recv_cb_called;
static int close_cb_called;
+static uint16_t client_port;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
static int can_ipv6_ipv4_dual(void) {
@@ -83,12 +85,35 @@ static void send_cb(uv_udp_send_t* req, int status) {
send_cb_called++;
}
+static int is_from_client(const struct sockaddr* addr) {
+ const struct sockaddr_in6* addr6;
+ char dst[256];
+ int r;
+
+ /* Debugging output, and filter out unwanted network traffic */
+ if (addr != NULL) {
+ ASSERT(addr->sa_family == AF_INET6);
+ addr6 = (struct sockaddr_in6*) addr;
+ r = uv_inet_ntop(addr->sa_family, &addr6->sin6_addr, dst, sizeof(dst));
+ if (r == 0)
+ printf("from [%.*s]:%d\n", (int) sizeof(dst), dst, addr6->sin6_port);
+ if (addr6->sin6_port != client_port)
+ return 0;
+ if (r != 0 || strcmp(dst, "::ffff:127.0.0.1"))
+ return 0;
+ }
+ return 1;
+}
+
static void ipv6_recv_fail(uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* buf,
const struct sockaddr* addr,
unsigned flags) {
+ printf("got %d %.*s\n", (int) nread, nread > 0 ? (int) nread : 0, buf->base);
+ if (!is_from_client(addr) || (nread == 0 && addr == NULL))
+ return;
ASSERT(0 && "this function should not have been called");
}
@@ -99,10 +124,14 @@ static void ipv6_recv_ok(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned flags) {
CHECK_HANDLE(handle);
- ASSERT(nread >= 0);
- if (nread)
- recv_cb_called++;
+ printf("got %d %.*s\n", (int) nread, nread > 0 ? (int) nread : 0, buf->base);
+ if (!is_from_client(addr) || (nread == 0 && addr == NULL))
+ return;
+
+ ASSERT(nread == 9);
+ ASSERT(!memcmp(buf->base, data, 9));
+ recv_cb_called++;
}
@@ -116,7 +145,10 @@ static void timeout_cb(uv_timer_t* timer) {
static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) {
struct sockaddr_in6 addr6;
struct sockaddr_in addr;
+ int addr6_len;
+ int addr_len;
uv_buf_t buf;
+ char dst[256];
int r;
ASSERT(0 == uv_ip6_addr("::0", TEST_PORT, &addr6));
@@ -127,14 +159,25 @@ static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) {
r = uv_udp_bind(&server, (const struct sockaddr*) &addr6, bind_flags);
ASSERT(r == 0);
+ addr6_len = sizeof(addr6);
+ ASSERT(uv_udp_getsockname(&server, (struct sockaddr*) &addr6, &addr6_len) == 0);
+ ASSERT(uv_inet_ntop(addr6.sin6_family, &addr6.sin6_addr, dst, sizeof(dst)) == 0);
+ printf("on [%.*s]:%d\n", (int) sizeof(dst), dst, addr6.sin6_port);
+
r = uv_udp_recv_start(&server, alloc_cb, recv_cb);
ASSERT(r == 0);
r = uv_udp_init(uv_default_loop(), &client);
ASSERT(r == 0);
- buf = uv_buf_init("PING", 4);
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
+ ASSERT(uv_inet_ntop(addr.sin_family, &addr.sin_addr, dst, sizeof(dst)) == 0);
+ printf("to [%.*s]:%d\n", (int) sizeof(dst), dst, addr.sin_port);
+
+ /* Create some unique data to send */
+ ASSERT(9 == snprintf(data, sizeof(data), "PING%5u", uv_os_getpid() & 0xFFFF));
+ buf = uv_buf_init(data, 9);
+ printf("sending %s\n", data);
r = uv_udp_send(&req_,
&client,
@@ -144,6 +187,12 @@ static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) {
send_cb);
ASSERT(r == 0);
+ addr_len = sizeof(addr);
+ ASSERT(uv_udp_getsockname(&client, (struct sockaddr*) &addr, &addr_len) == 0);
+ ASSERT(uv_inet_ntop(addr.sin_family, &addr.sin_addr, dst, sizeof(dst)) == 0);
+ printf("from [%.*s]:%d\n", (int) sizeof(dst), dst, addr.sin_port);
+ client_port = addr.sin_port;
+
r = uv_timer_init(uv_default_loop(), &timeout);
ASSERT(r == 0);
@@ -180,6 +229,8 @@ TEST_IMPL(udp_dual_stack) {
do_test(ipv6_recv_ok, 0);
+ printf("recv_cb_called %d\n", recv_cb_called);
+ printf("send_cb_called %d\n", send_cb_called);
ASSERT(recv_cb_called == 1);
ASSERT(send_cb_called == 1);
diff --git a/deps/uv/test/test-watcher-cross-stop.c b/deps/uv/test/test-watcher-cross-stop.c
index 29a82a5c37..b26deb8d88 100644
--- a/deps/uv/test/test-watcher-cross-stop.c
+++ b/deps/uv/test/test-watcher-cross-stop.c
@@ -26,8 +26,9 @@
#include <errno.h>
/* NOTE: Number should be big enough to trigger this problem */
-#if defined(__CYGWIN__) || defined(__MSYS__)
+#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__)
/* Cygwin crashes or hangs in socket() with too many AF_INET sockets. */
+/* IBMi PASE timeout with too many AF_INET sockets. */
static uv_udp_t sockets[1250];
#else
static uv_udp_t sockets[2500];
diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp
index 73ff42c56e..48fc5eaf8e 100644
--- a/deps/uv/test/test.gyp
+++ b/deps/uv/test/test.gyp
@@ -143,6 +143,7 @@
'test-timer-from-check.c',
'test-timer.c',
'test-tty-duplicate-key.c',
+ 'test-tty-escape-sequence-processing.c',
'test-tty.c',
'test-udp-alloc-cb-fail.c',
'test-udp-bind.c',
@@ -240,6 +241,7 @@
'benchmark-million-timers.c',
'benchmark-multi-accept.c',
'benchmark-ping-pongs.c',
+ 'benchmark-ping-udp.c',
'benchmark-pound.c',
'benchmark-pump.c',
'benchmark-sizes.c',
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index fa0a001527..116b753719 100644
--- a/deps/uv/uv.gyp
+++ b/deps/uv/uv.gyp
@@ -261,7 +261,6 @@
'src/unix/android-ifaddrs.c',
'src/unix/procfs-exepath.c',
'src/unix/random-getrandom.c',
- 'src/unix/random-getentropy.c',
'src/unix/random-sysctl-linux.c',
'src/unix/sysinfo-loadavg.c',
],