From da51e8777459d7c86c76454d4f40d26cd63fa501 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Tue, 27 Jul 2021 22:08:18 +0000 Subject: [PATCH] libuv 1.42.0. git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3650 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- Makefile | 1 + deps/libuv/.github/ISSUE_TEMPLATE.md | 2 +- deps/libuv/.github/workflows/sanitizer.yml | 17 + deps/libuv/.mailmap | 6 + deps/libuv/.readthedocs.yaml | 11 + deps/libuv/AUTHORS | 37 +- deps/libuv/CMakeLists.txt | 75 ++- deps/libuv/CONTRIBUTING.md | 10 +- deps/libuv/ChangeLog | 236 ++++++++- deps/libuv/LINKS.md | 101 ++++ deps/libuv/MAINTAINERS.md | 1 + deps/libuv/Makefile.am | 17 +- deps/libuv/README.md | 22 +- deps/libuv/SUPPORTED_PLATFORMS.md | 4 +- deps/libuv/configure.ac | 10 +- deps/libuv/docs/code/dns/main.c | 4 +- deps/libuv/docs/requirements.txt | 42 ++ deps/libuv/docs/src/errors.rst | 8 + deps/libuv/docs/src/guide/basics.rst | 2 + deps/libuv/docs/src/guide/eventloops.rst | 2 + deps/libuv/docs/src/guide/filesystem.rst | 9 + deps/libuv/docs/src/guide/introduction.rst | 2 +- deps/libuv/docs/src/guide/networking.rst | 9 +- deps/libuv/docs/src/guide/processes.rst | 15 + deps/libuv/docs/src/guide/threads.rst | 12 + deps/libuv/docs/src/guide/utilities.rst | 13 + deps/libuv/docs/src/index.rst | 2 +- deps/libuv/docs/src/misc.rst | 2 +- deps/libuv/docs/src/pipe.rst | 18 + deps/libuv/docs/src/poll.rst | 61 ++- deps/libuv/docs/src/process.rst | 12 +- deps/libuv/docs/src/stream.rst | 25 +- deps/libuv/docs/src/tcp.rst | 24 +- deps/libuv/docs/src/udp.rst | 28 +- deps/libuv/include/uv.h | 30 +- deps/libuv/include/uv/errno.h | 12 + deps/libuv/include/uv/tree.h | 2 +- deps/libuv/include/uv/version.h | 2 +- deps/libuv/src/idna.c | 49 +- deps/libuv/src/inet.c | 3 +- deps/libuv/src/threadpool.c | 2 - deps/libuv/src/timer.c | 1 + deps/libuv/src/unix/async.c | 2 +- deps/libuv/src/unix/atomic-ops.h | 6 +- deps/libuv/src/unix/bsd-ifaddrs.c | 6 +- deps/libuv/src/unix/core.c | 28 +- deps/libuv/src/unix/darwin.c | 12 +- deps/libuv/src/unix/epoll.c | 422 ++++++++++++++++ deps/libuv/src/unix/freebsd.c | 15 +- deps/libuv/src/unix/fs.c | 106 +++- deps/libuv/src/unix/fsevents.c | 23 +- deps/libuv/src/unix/getaddrinfo.c | 3 - deps/libuv/src/unix/ibmi.c | 48 +- deps/libuv/src/unix/internal.h | 30 +- deps/libuv/src/unix/linux-core.c | 470 ++---------------- deps/libuv/src/unix/linux-inotify.c | 2 +- deps/libuv/src/unix/linux-syscalls.c | 37 +- deps/libuv/src/unix/linux-syscalls.h | 7 +- deps/libuv/src/unix/os390-proctitle.c | 136 +++++ deps/libuv/src/unix/os390-syscalls.c | 57 +-- deps/libuv/src/unix/os390-syscalls.h | 2 +- deps/libuv/src/unix/os390.c | 136 +---- deps/libuv/src/unix/pipe.c | 54 ++ deps/libuv/src/unix/poll.c | 14 +- deps/libuv/src/unix/process.c | 127 ++--- deps/libuv/src/unix/proctitle.c | 4 +- deps/libuv/src/unix/signal.c | 2 +- deps/libuv/src/unix/stream.c | 227 ++++----- deps/libuv/src/unix/sunos.c | 11 + deps/libuv/src/unix/tcp.c | 53 +- deps/libuv/src/unix/thread.c | 12 +- deps/libuv/src/unix/tty.c | 18 + deps/libuv/src/unix/udp.c | 32 +- deps/libuv/src/uv-common.c | 25 +- deps/libuv/src/uv-common.h | 9 +- deps/libuv/src/win/atomicops-inl.h | 8 +- deps/libuv/src/win/error.c | 2 +- deps/libuv/src/win/fs.c | 51 +- deps/libuv/src/win/internal.h | 4 +- deps/libuv/src/win/pipe.c | 236 ++++++++- deps/libuv/src/win/poll.c | 3 +- deps/libuv/src/win/process-stdio.c | 96 ---- deps/libuv/src/win/process.c | 2 +- deps/libuv/src/win/stream.c | 23 +- deps/libuv/src/win/tcp.c | 260 +++++++--- deps/libuv/src/win/udp.c | 4 +- deps/libuv/src/win/util.c | 17 +- deps/libuv/test/benchmark-async-pummel.c | 2 +- deps/libuv/test/benchmark-async.c | 2 +- deps/libuv/test/benchmark-million-async.c | 2 +- deps/libuv/test/benchmark-million-timers.c | 2 +- deps/libuv/test/benchmark-multi-accept.c | 8 +- deps/libuv/test/benchmark-pound.c | 8 +- deps/libuv/test/benchmark-pump.c | 2 + deps/libuv/test/benchmark-tcp-write-batch.c | 4 +- deps/libuv/test/benchmark-udp-pummel.c | 14 +- deps/libuv/test/blackhole-server.c | 3 +- deps/libuv/test/dns-server.c | 2 +- deps/libuv/test/echo-server.c | 64 ++- deps/libuv/test/run-benchmarks.c | 12 +- deps/libuv/test/run-tests.c | 50 +- deps/libuv/test/runner-unix.c | 4 +- deps/libuv/test/runner.c | 42 +- deps/libuv/test/task.h | 37 +- deps/libuv/test/test-active.c | 2 +- deps/libuv/test/test-async.c | 2 +- deps/libuv/test/test-callback-stack.c | 2 +- deps/libuv/test/test-close-fd.c | 30 +- deps/libuv/test/test-close-order.c | 2 +- deps/libuv/test/test-default-loop-close.c | 4 +- deps/libuv/test/test-delayed-accept.c | 18 +- deps/libuv/test/test-dlerror.c | 16 +- deps/libuv/test/test-error.c | 11 +- deps/libuv/test/test-fs-copyfile.c | 3 + deps/libuv/test/test-fs-event.c | 11 +- deps/libuv/test/test-fs-poll.c | 4 +- deps/libuv/test/test-fs-readdir.c | 19 +- deps/libuv/test/test-fs.c | 205 +++++--- deps/libuv/test/test-get-currentexe.c | 2 +- deps/libuv/test/test-get-passwd.c | 14 +- deps/libuv/test/test-getaddrinfo.c | 8 +- deps/libuv/test/test-getnameinfo.c | 6 +- deps/libuv/test/test-getsockname.c | 2 +- deps/libuv/test/test-getters-setters.c | 14 +- deps/libuv/test/test-idna.c | 19 + .../test-ipc-heavy-traffic-deadlock-bug.c | 2 +- deps/libuv/test/test-ipc.c | 9 +- deps/libuv/test/test-list.h | 47 +- deps/libuv/test/test-loop-handles.c | 4 +- deps/libuv/test/test-multiple-listen.c | 6 +- ...-not-readable-nor-writable-on-read-error.c | 104 ++++ deps/libuv/test/test-not-readable-on-eof.c | 103 ++++ .../test/test-not-writable-after-shutdown.c | 69 +++ deps/libuv/test/test-ping-pong.c | 221 ++++++-- deps/libuv/test/test-pipe-bind-error.c | 2 +- deps/libuv/test/test-pipe-connect-error.c | 5 +- deps/libuv/test/test-pipe-connect-prepare.c | 2 +- deps/libuv/test/test-pipe-getsockname.c | 10 +- deps/libuv/test/test-pipe-server-close.c | 2 +- deps/libuv/test/test-pipe-set-non-blocking.c | 53 +- deps/libuv/test/test-platform-output.c | 1 + deps/libuv/test/test-poll-multiple-handles.c | 99 ++++ deps/libuv/test/test-poll.c | 4 +- deps/libuv/test/test-ref.c | 2 +- deps/libuv/test/test-shutdown-eof.c | 8 +- deps/libuv/test/test-shutdown-simultaneous.c | 135 +++++ deps/libuv/test/test-signal-multiple-loops.c | 2 +- .../libuv/test/test-signal-pending-on-close.c | 4 +- deps/libuv/test/test-spawn.c | 136 ++--- deps/libuv/test/test-tcp-alloc-cb-fail.c | 2 +- deps/libuv/test/test-tcp-bind-error.c | 51 +- deps/libuv/test/test-tcp-bind6-error.c | 2 +- deps/libuv/test/test-tcp-close.c | 2 +- deps/libuv/test/test-tcp-connect-error.c | 4 +- deps/libuv/test/test-tcp-connect-timeout.c | 2 +- deps/libuv/test/test-tcp-connect6-error.c | 4 +- .../libuv/test/test-tcp-create-socket-early.c | 2 +- deps/libuv/test/test-tcp-open.c | 17 +- deps/libuv/test/test-tcp-write-fail.c | 4 +- .../test-tcp-write-to-half-open-connection.c | 2 +- deps/libuv/test/test-tcp-writealot.c | 8 +- deps/libuv/test/test-thread.c | 6 +- deps/libuv/test/test-threadpool-cancel.c | 6 +- deps/libuv/test/test-timer-again.c | 2 +- deps/libuv/test/test-timer.c | 8 +- deps/libuv/test/test-tty-duplicate-key.c | 2 +- .../test-tty-escape-sequence-processing.c | 4 +- deps/libuv/test/test-tty.c | 3 + deps/libuv/test/test-udp-alloc-cb-fail.c | 10 +- deps/libuv/test/test-udp-connect.c | 6 +- deps/libuv/test/test-udp-mmsg.c | 6 +- .../libuv/test/test-udp-multicast-interface.c | 2 +- .../test/test-udp-multicast-interface6.c | 2 +- deps/libuv/test/test-udp-multicast-join.c | 6 +- deps/libuv/test/test-udp-multicast-join6.c | 6 +- deps/libuv/test/test-udp-multicast-ttl.c | 2 +- deps/libuv/test/test-udp-open.c | 16 +- deps/libuv/test/test-udp-send-and-recv.c | 14 +- deps/libuv/test/test-udp-send-hang-loop.c | 4 +- deps/libuv/test/test-udp-send-immediate.c | 6 +- deps/libuv/test/test-udp-send-unreachable.c | 93 +++- deps/libuv/test/test-udp-try-send.c | 4 +- deps/libuv/tools/make_dist_html.py | 8 +- 183 files changed, 4013 insertions(+), 1768 deletions(-) create mode 100644 deps/libuv/.github/workflows/sanitizer.yml create mode 100644 deps/libuv/.readthedocs.yaml create mode 100644 deps/libuv/LINKS.md create mode 100644 deps/libuv/docs/requirements.txt create mode 100644 deps/libuv/src/unix/epoll.c create mode 100644 deps/libuv/src/unix/os390-proctitle.c create mode 100644 deps/libuv/test/test-not-readable-nor-writable-on-read-error.c create mode 100644 deps/libuv/test/test-not-readable-on-eof.c create mode 100644 deps/libuv/test/test-not-writable-after-shutdown.c create mode 100644 deps/libuv/test/test-poll-multiple-handles.c create mode 100644 deps/libuv/test/test-shutdown-simultaneous.c diff --git a/Makefile b/Makefile index f8b62464..88bb3f3c 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ UV_SOURCES = \ deps/libuv/src/unix/async.c \ deps/libuv/src/unix/core.c \ deps/libuv/src/unix/dl.c \ + deps/libuv/src/unix/epoll.c \ deps/libuv/src/unix/fs.c \ deps/libuv/src/unix/getaddrinfo.c \ deps/libuv/src/unix/getnameinfo.c \ diff --git a/deps/libuv/.github/ISSUE_TEMPLATE.md b/deps/libuv/.github/ISSUE_TEMPLATE.md index 42538796..43934de7 100644 --- a/deps/libuv/.github/ISSUE_TEMPLATE.md +++ b/deps/libuv/.github/ISSUE_TEMPLATE.md @@ -2,7 +2,7 @@ If you want to report a bug, you are in the right place! If you need help or have a question, go here: -https://github.com/libuv/help/issues/new +https://github.com/libuv/libuv/discussions If you are reporting a libuv test failure, please ensure that you are not running the test as root. diff --git a/deps/libuv/.github/workflows/sanitizer.yml b/deps/libuv/.github/workflows/sanitizer.yml new file mode 100644 index 00000000..51e14794 --- /dev/null +++ b/deps/libuv/.github/workflows/sanitizer.yml @@ -0,0 +1,17 @@ +name: Sanitizer checks + +on: [push, pull_request] + +jobs: + asan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Envinfo + run: npx envinfo + - name: ASAN + run: | + mkdir build + cd build && cmake .. -DBUILD_TESTING=ON -DASAN=ON -DCMAKE_BUILD_TYPE=Debug + cmake --build . && ./uv_run_tests_a + diff --git a/deps/libuv/.mailmap b/deps/libuv/.mailmap index 56a80f58..7be85aba 100644 --- a/deps/libuv/.mailmap +++ b/deps/libuv/.mailmap @@ -2,6 +2,7 @@ A. Hauptmann Aaron Bieber Alan Gutierrez Andrius Bentkus +Andy Fiddaman Bert Belder Bert Belder Bert Belder @@ -10,6 +11,8 @@ Brian White Brian White Caleb James DeLisle Christoph Iserlohn +Darshan Sen +David Carlier Devchandra Meetei Leishangthem Fedor Indutny Frank Denis @@ -32,6 +35,7 @@ Nicholas Vavilov Nick Logan Rasmus Christian Pedersen Rasmus Christian Pedersen +Richard Lau Robert Mustacchi Ryan Dahl Ryan Emery @@ -47,8 +51,10 @@ Timothy J. Fontaine Yasuhiro Matsumoto Yazhong Liu Yuki Okumura +cjihrig gengjiawen jBarz jBarz ptlomholt +tjarlama <59913901+tjarlama@users.noreply.github.com> zlargon diff --git a/deps/libuv/.readthedocs.yaml b/deps/libuv/.readthedocs.yaml new file mode 100644 index 00000000..e53b9f3e --- /dev/null +++ b/deps/libuv/.readthedocs.yaml @@ -0,0 +1,11 @@ +version: 2 + +sphinx: + builder: html + configuration: null + fail_on_warning: false + +python: + version: 3.8 + install: + - requirements: docs/requirements.txt diff --git a/deps/libuv/AUTHORS b/deps/libuv/AUTHORS index e7c789cf..741bcc70 100644 --- a/deps/libuv/AUTHORS +++ b/deps/libuv/AUTHORS @@ -114,7 +114,6 @@ Dylan Cali Austin Foxley Benjamin Saunders Geoffry Song -Rasmus Christian Pedersen William Light Oleg Efimov Lars Gierth @@ -123,7 +122,6 @@ Justin Venus Kristian Evensen Linus Mårtensson Navaneeth Kedaram Nambiathan -Yorkie StarWing thierry-FreeBSD Isaiah Norton @@ -212,7 +210,7 @@ guworks RossBencina Roger A. Light chenttuuvv -Richard Lau +Richard Lau ronkorving Corbin Simpson Zachary Hamm @@ -448,3 +446,36 @@ Aleksej Lebedev Nikolay Mitev Ulrik Strid Elad Lahav +Elad Nachmias +Darshan Sen +Simon Kadisch +Momtchil Momtchev +Ethel Weston <66453757+ethelweston@users.noreply.github.com> +Drew DeVault +Mark Klein +schamberg97 <50446906+schamberg97@users.noreply.github.com> +Bob Weinand +Issam E. Maghni +Juan Pablo Canepa +Shuowang (Wayne) Zhang +Ondřej Surý +Juan José Arboleda +Zhao Zhili +Brandon Cheng +Matvii Hodovaniuk +Hayden +yiyuaner +bbara +SeverinLeonhardt +Andy Fiddaman +Romain Roffé +Eagle Liang +Ricky Zhou +Simon Kissane +James M Snell +Ali Mohammad Pur +Erkhes N <71805796+rexes-ND@users.noreply.github.com> +Joshua M. Clulow +Guilherme Íscaro +Martin Storsjö +Claes Nästén diff --git a/deps/libuv/CMakeLists.txt b/deps/libuv/CMakeLists.txt index e648b00b..148d0e68 100644 --- a/deps/libuv/CMakeLists.txt +++ b/deps/libuv/CMakeLists.txt @@ -30,6 +30,14 @@ if(QEMU) add_definitions(-D__QEMU__=1) endif() +option(ASAN "Enable AddressSanitizer (ASan)" OFF) +if(ASAN AND CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang") + add_definitions(-D__ASAN__=1) + set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") + set (CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address") +endif() + # Compiler check string(CONCAT is-msvc $, @@ -95,6 +103,9 @@ list(APPEND uv_cflags ${lint-no-conditional-assignment-msvc}) list(APPEND uv_cflags ${lint-no-unsafe-msvc}) list(APPEND uv_cflags ${lint-utf8-msvc} ) +check_c_compiler_flag(-fno-strict-aliasing UV_F_STRICT_ALIASING) +list(APPEND uv_cflags $<$:-fno-strict-aliasing>) + set(uv_sources src/fs-poll.c src/idna.c @@ -108,7 +119,7 @@ set(uv_sources src/version.c) if(WIN32) - list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0600) + list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602) list(APPEND uv_libraries psapi user32 @@ -199,10 +210,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android") src/unix/pthread-fixes.c src/unix/random-getentropy.c src/unix/random-getrandom.c - src/unix/random-sysctl-linux.c) + src/unix/random-sysctl-linux.c + src/unix/epoll.c) endif() -if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS390") +if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux") list(APPEND uv_sources src/unix/proctitle.c) endif() @@ -243,7 +255,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") src/unix/linux-syscalls.c src/unix/procfs-exepath.c src/unix/random-getrandom.c - src/unix/random-sysctl-linux.c) + src/unix/random-sysctl-linux.c + src/unix/epoll.c) endif() if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") @@ -256,9 +269,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") endif() if(CMAKE_SYSTEM_NAME STREQUAL "OS390") - list(APPEND uv_defines PATH_MAX=255) + enable_language(CXX) + list(APPEND uv_defines PATH_MAX=1024) list(APPEND uv_defines _AE_BIMODAL) list(APPEND uv_defines _ALL_SOURCE) + list(APPEND uv_defines _ENHANCED_ASCII_EXT=0xFFFFFFFF) list(APPEND uv_defines _ISOC99_SOURCE) list(APPEND uv_defines _LARGE_TIME_API) list(APPEND uv_defines _OPEN_MSGQ_EXT) @@ -269,14 +284,31 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS390") list(APPEND uv_defines _UNIX03_SOURCE) list(APPEND uv_defines _UNIX03_THREADS) list(APPEND uv_defines _UNIX03_WITHDRAWN) + list(APPEND uv_defines _XOPEN_SOURCE=600) list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED) list(APPEND uv_sources src/unix/pthread-fixes.c src/unix/os390.c - src/unix/os390-syscalls.c) - list(APPEND uv_cflags -Wc,DLL -Wc,exportall -Wc,xplink) - list(APPEND uv_libraries -Wl,xplink) - list(APPEND uv_test_libraries -Wl,xplink) + src/unix/os390-syscalls.c + src/unix/os390-proctitle.c) + list(APPEND uv_cflags + -q64 + -qascii + -qexportall + -qgonumber + -qlongname + -qlibansi + -qfloat=IEEE + -qtune=10 + -qarch=10 + -qasm + -qasmlib=sys1.maclib:sys1.modgen) + find_library(ZOSLIB + NAMES zoslib + PATHS ${ZOSLIB_DIR} + PATH_SUFFIXES lib + ) + list(APPEND uv_libraries ${ZOSLIB}) endif() if(CMAKE_SYSTEM_NAME STREQUAL "OS400") @@ -293,9 +325,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS400") endif() if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") - list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500) + list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500 _REENTRANT) list(APPEND uv_libraries kstat nsl sendfile socket) - list(APPEND uv_sources src/unix/no-proctitle.c src/unix/sunos.c) + list(APPEND uv_sources + src/unix/no-proctitle.c + src/unix/sunos.c) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Haiku") @@ -318,7 +352,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "QNX") src/unix/bsd-ifaddrs.c src/unix/no-proctitle.c src/unix/no-fsevents.c) - list(APPEND uv_cflags -fno-strict-aliasing) list(APPEND uv_libraries socket) endif() @@ -340,6 +373,10 @@ target_include_directories(uv $ PRIVATE $) +if(CMAKE_SYSTEM_NAME STREQUAL "OS390") + target_include_directories(uv PUBLIC $) + set_target_properties(uv PROPERTIES LINKER_LANGUAGE CXX) +endif() target_link_libraries(uv ${uv_libraries}) add_library(uv_a STATIC ${uv_sources}) @@ -351,6 +388,10 @@ target_include_directories(uv_a $ PRIVATE $) +if(CMAKE_SYSTEM_NAME STREQUAL "OS390") + target_include_directories(uv_a PUBLIC $) + set_target_properties(uv_a PROPERTIES LINKER_LANGUAGE CXX) +endif() target_link_libraries(uv_a ${uv_libraries}) if(LIBUV_BUILD_TESTS) @@ -448,6 +489,9 @@ if(LIBUV_BUILD_TESTS) test/test-metrics.c test/test-multiple-listen.c test/test-mutexes.c + test/test-not-readable-nor-writable-on-read-error.c + test/test-not-readable-on-eof.c + test/test-not-writable-after-shutdown.c test/test-osx-select.c test/test-pass-always.c test/test-ping-pong.c @@ -466,6 +510,7 @@ if(LIBUV_BUILD_TESTS) test/test-poll-close-doesnt-corrupt-stack.c test/test-poll-close.c test/test-poll-closesocket.c + test/test-poll-multiple-handles.c test/test-poll-oob.c test/test-poll.c test/test-process-priority.c @@ -479,6 +524,7 @@ if(LIBUV_BUILD_TESTS) test/test-semaphore.c test/test-shutdown-close.c test/test-shutdown-eof.c + test/test-shutdown-simultaneous.c test/test-shutdown-twice.c test/test-signal-multiple-loops.c test/test-signal-pending-on-close.c @@ -572,6 +618,11 @@ if(LIBUV_BUILD_TESTS) add_test(NAME uv_test_a COMMAND uv_run_tests_a WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + if(CMAKE_SYSTEM_NAME STREQUAL "OS390") + set_target_properties(uv_run_benchmarks_a PROPERTIES LINKER_LANGUAGE CXX) + set_target_properties(uv_run_tests PROPERTIES LINKER_LANGUAGE CXX) + set_target_properties(uv_run_tests_a PROPERTIES LINKER_LANGUAGE CXX) + endif() endif() if(UNIX OR MINGW) diff --git a/deps/libuv/CONTRIBUTING.md b/deps/libuv/CONTRIBUTING.md index b0abe3b4..d37c51d6 100644 --- a/deps/libuv/CONTRIBUTING.md +++ b/deps/libuv/CONTRIBUTING.md @@ -23,11 +23,11 @@ The stable branch is effectively frozen; patches that change the libuv API/ABI or affect the run-time behavior of applications get rejected. In case of doubt, open an issue in the [issue tracker][], post your question -to the [libuv mailing list], or contact one of [project maintainers][] on [IRC][]. +to the [libuv discussions forum], or message the [libuv mailing list]. -Especially do so if you plan to work on something big. Nothing is more -frustrating than seeing your hard work go to waste because your vision -does not align with that of a project maintainers. +Especially do so if you plan to work on something big. Nothing is more +frustrating than seeing your hard work go to waste because your vision does not +align with that of the [project maintainers]. ### BRANCH @@ -166,6 +166,6 @@ not send out notifications when you add commits. [issue tracker]: https://github.com/libuv/libuv/issues [libuv mailing list]: http://groups.google.com/group/libuv -[IRC]: http://webchat.freenode.net/?channels=libuv +[libuv discussions forum]: https://github.com/libuv/libuv/discussions [Google C/C++ style guide]: https://google.github.io/styleguide/cppguide.html [project maintainers]: https://github.com/libuv/libuv/blob/master/MAINTAINERS.md diff --git a/deps/libuv/ChangeLog b/deps/libuv/ChangeLog index 8788d946..4f2a4bc9 100644 --- a/deps/libuv/ChangeLog +++ b/deps/libuv/ChangeLog @@ -1,4 +1,238 @@ -2020.09.26, Version 1.40.0 (Stable) +2021.07.21, Version 1.42.0 (Stable) + +Changes since version 1.41.0: + +* doc: fix code highlighting (Darshan Sen) + +* test: move to ASSERT_NULL and ASSERT_NOT_NULL test macros (tjarlama) + +* zos: build in ascii code page (Shuowang (Wayne) Zhang) + +* zos: don't use nanosecond timestamp fields (Shuowang (Wayne) Zhang) + +* zos: introduce zoslib (Shuowang (Wayne) Zhang) + +* zos: use strnlen() from zoslib (Shuowang (Wayne) Zhang) + +* zos: use nanosleep() from zoslib (Shuowang (Wayne) Zhang) + +* zos: use __getargv() from zoslib to get exe path (Shuowang (Wayne) Zhang) + +* zos: treat __rfim_utok as binary (Shuowang (Wayne) Zhang) + +* zos: use execvpe() to set environ explictly (Shuowang (Wayne) Zhang) + +* zos: use custom proctitle implementation (Shuowang (Wayne) Zhang) + +* doc: add instructions for building on z/OS (Shuowang (Wayne) Zhang) + +* linux,udp: enable full ICMP error reporting (Ondřej Surý) + +* test: fix test-udp-send-unreachable (Ondřej Surý) + +* include: fix typo in documentation (Tobias Nießen) + +* chore: use for(;;) instead of while (Yash Ladha) + +* test: remove string + int warning on udp-pummel (Juan José Arboleda) + +* cmake: fix linker flags (Zhao Zhili) + +* test: fix stack-use-after-scope (Zhao Zhili) + +* unix: expose thread_stack_size() internally (Brandon Cheng) + +* darwin: use RLIMIT_STACK for fsevents pthread (Brandon Cheng) + +* darwin: abort on pthread_attr_init fail (Brandon Cheng) + +* benchmark: remove unreachable code (Matvii Hodovaniuk) + +* macos: fix memleaks in uv__get_cpu_speed (George Zhao) + +* Make Thread Sanitizer aware of file descriptor close in uv__close() (Ondřej + Surý) + +* darwin: fix iOS compilation and functionality (Hayden) + +* linux: work around copy_file_range() cephfs bug (Ben Noordhuis) + +* zos: implement uv_get_constrained_memory() (Shuowang (Wayne) Zhang) + +* zos: fix uv_get_free_memory() (Shuowang (Wayne) Zhang) + +* zos: use CVTRLSTG to get total memory accurately (Shuowang (Wayne) Zhang) + +* ibmi: Handle interface names longer than 10 chars (Kevin Adler) + +* docs: update read-the-docs version of sphinx (Jameson Nash) + +* unix: refactor uv_try_write (twosee) + +* linux-core: add proper divide by zero assert (yiyuaner) + +* misc: remove unnecessary _GNU_SOURCE macros (Darshan Sen) + +* test: log to stdout to conform TAP spec (bbara) + +* win,fs: fix C4090 warning with MSVC (SeverinLeonhardt) + +* build: some systems provide dlopen() in libc (Andy Fiddaman) + +* include: add EOVERFLOW status code mapping (Darshan Sen) + +* unix,fs: use uv__load_relaxed and uv__store_relaxed (Darshan Sen) + +* win: fix string encoding issue of uv_os_gethostname (Eagle Liang) + +* unix,process: add uv__write_errno helper function (Ricky Zhou) + +* Re-merge "unix,stream: clear read/write states on close/eof" (Jameson Nash) + +* unix,core: fix errno handling in uv__getpwuid_r (Darshan Sen) + +* errors: map ESOCKTNOSUPPORT errno (Ryan Liptak) + +* doc: uv_read_stop always succeeds (Simon Kissane) + +* inet: fix inconsistent return value of inet_ntop6 (twosee) + +* darwin: fix -Wsometimes-uninitialized warning (twosee) + +* stream: introduce uv_try_write2 function (twosee) + +* poll,win: UV_PRIORITIZED option should not assert (twosee) + +* src: DragonFlyBSD has mmsghdr struct too (David Carlier) + +* cleanup,win: Remove _WIN32 guards on threadpool (James M Snell) + +* freebsd: fix an incompatible pointer type warning (Darshan Sen) + +* core: Correct the conditionals for {cloexec,nonblock}_ioctl (Ali Mohammad + Pur) + +* win,tcp: make uv_close work more like unix (Jameson Nash) + +* doc: more accurate list of valid send_handle's (twosee) + +* win,tcp: translate system errors correctly (twosee) + +* unix: implement cpu_relax() on ppc64 (Ben Noordhuis) + +* docs: move list of project links under PR control (Jameson Nash) + +* test: wrong pointer arithmetic multiplier (Erkhes N) + +* doc: switch discussion forum to github (Jameson Nash) + +* idna: fix OOB read in punycode decoder (Ben Noordhuis) + +* build: make sure -fvisibility=hidden is set (Santiago Gimeno) + +* illumos: event ports to epoll (tjarlama) + +* illumos,tty: UV_TTY_MODE_IO waits for 4 bytes (Joshua M. Clulow) + +* doc: add vtjnash GPG ID (Jameson Nash) + +* linux: read CPU model information on ppc (Richard Lau) + +* darwin: fix uv_barrier race condition (Guilherme Íscaro) + +* unix,stream: fix loop hang after uv_shutdown (Jameson Nash) + +* doc,udp: note that suggested_size is 1 max-sized dgram (Ryan Liptak) + +* mingw: fix building for ARM/AArch64 (Martin Storsjö) + +* unix: strnlen is not available on Solaris 10 (Claes Nästén) + +* sunos: restore use of event ports (Andy Fiddaman) + +* sunos,cmake: use thread-safe errno (Andy Fiddaman) + + +2021.02.14, Version 1.41.0 (Stable), 1dff88e5161cba5c59276d2070d2e304e4dcb242 + +Changes since version 1.40.0: + +* mailmap: update contact information for richardlau (Richard Lau) + +* build: add asan checks (gengjiawen) + +* unix: report bind error in uv_tcp_connect() (Ben Noordhuis) + +* doc: uv_tcp_bind() never returns UV_EADDRINUSE (Ben Noordhuis) + +* test: fix pump and tcp_write_batch benchmarks (Santiago Gimeno) + +* doc: mark IBM i as Tier 2 support (Jesse Gorzinski) + +* doc,poll: add notes (repeated cb & cancel pending cb) (Elad Nachmias) + +* linux: fix -Wincompatible-pointer-types warning (Ben Noordhuis) + +* linux: fix -Wsign-compare warning (Ben Noordhuis) + +* android: add system call api guards (Ben Noordhuis) + +* unix,win: harmonize uv_read_start() error handling (Ben Noordhuis) + +* unix,win: more uv_read_start() argument validation (Ben Noordhuis) + +* build: turn on -fno-strict-aliasing (Ben Noordhuis) + +* stream: add uv_pipe and uv_socketpair to the API (Jameson Nash) + +* unix,win: initialize timer `timeout` field (Ben Noordhuis) + +* bsd-ifaddrs: improve comments (Darshan Sen) + +* test: remove unnecessary uv_fs_stat() calls (Ben Noordhuis) + +* fs: fix utime/futime timestamp rounding errors (Ben Noordhuis) + +* test: ensure reliable floating point comparison (Jameson Nash) + +* unix,fs: fix uv_fs_sendfile() (Santiago Gimeno) + +* unix: fix uv_fs_stat when using statx (Simon Kadisch) + +* linux,macos: fix uv_set_process_title regression (Momtchil Momtchev) + +* doc: clarify UDP errors and recvmmsg (Ethel Weston) + +* test-getaddrinfo: use example.invalid (Drew DeVault) + +* Revert "build: fix android autotools build" (Bernardo Ramos) + +* unix,fs: on DVS fs, statx returns EOPNOTSUPP (Mark Klein) + +* win, fs: mkdir really return UV_EINVAL for invalid names (Nicholas Vavilov) + +* tools: migrate tools/make_dist_html.py to python3 (Dominique Dumont) + +* unix: fix uv_uptime() on linux (schamberg97) + +* unix: check for partial copy_file_range support (Momtchil Momtchev) + +* win: bump minimum supported version to windows 8 (Ben Noordhuis) + +* poll,unix: ensure safety of rapid fd reuse (Bob Weinand) + +* test: fix some warnings (Issam E. Maghni) + +* unix: fix uv_uptime() regression (Santiago Gimeno) + +* doc: fix versionadded metadata (cjihrig) + +* test: fix 'incompatible pointer types' warnings (cjihrig) + +* unix: check for EXDEV in uv__fs_sendfile() (Darshan Sen) + + +2020.09.26, Version 1.40.0 (Stable), 4e69e333252693bd82d6338d6124f0416538dbfc Changes since version 1.39.0: diff --git a/deps/libuv/LINKS.md b/deps/libuv/LINKS.md new file mode 100644 index 00000000..b8204e56 --- /dev/null +++ b/deps/libuv/LINKS.md @@ -0,0 +1,101 @@ +### Apps / VM +* [BIND 9](https://bind.isc.org/): DNS software system including an authoritative server, a recursive resolver and related utilities. +* [cjdns](https://github.com/cjdelisle/cjdns): Encrypted self-configuring network/VPN routing engine +* [clearskies_core](https://github.com/larroy/clearskies_core): Clearskies file synchronization program. (C++11) +* [CMake](https://cmake.org) open-source, cross-platform family of tools designed to build, test and package software +* [Coherence](https://github.com/liesware/coherence/): Cryptographic server for modern web apps. +* [DPS-For-IoT](https://github.com/intel/dps-for-iot/wiki): Fully distributed publish/subscribe protocol. +* [HashLink](https://github.com/HaxeFoundation/hashlink): Haxe run-time with libuv support included. +* [Haywire](https://github.com/kellabyte/Haywire): Asynchronous HTTP server. +* [H2O](https://github.com/h2o/h2o): An optimized HTTP server with support for HTTP/1.x and HTTP/2. +* [Igropyr](https://github.com/guenchi/Igropyr): a async Scheme http server base on libuv. +* [Julia](http://julialang.org/): Scientific computing programming language +* [Kestrel](https://github.com/aspnet/AspNetCore/tree/master/src/Servers/Kestrel): web server (C# + libuv + [ASP.NET Core](http://github.com/aspnet)) +* [Knot DNS Resolver](https://www.knot-resolver.cz/): A minimalistic DNS caching resolver +* [Lever](http://leverlanguage.com): runtime, libuv at the 0.9.0 release +* [libnode](https://github.com/plenluno/libnode): C++ implementation of Node.js +* [libstorj](https://github.com/Storj/libstorj): Library for interacting with Storj network +* [libuv_message_framing](https://github.com/litesync/libuv_message_framing) Message-based communication for libuv +* [luaw](https://github.com/raksoras/luaw): Lua web server backed by libuv +* [Luvit](http://luvit.io): Node.JS for the Lua Inventor +* [mo](https://github.com/wehu/mo): Scheme (guile) + libuv runtime +* [MoarVM](https://github.com/MoarVM/MoarVM): a VM for [Rakudo](http://rakudo.org/) [Raku](http://raku.org) +* [Mysocks](https://github.com/zhou0/mysocks): a cross-platform [Shadowsocks](https://shadowsocks.org) client +* [mediasoup](http://mediasoup.org): Powerful WebRTC SFU for Node.js +* [Neovim](https://neovim.io/): A major refactor of Vim. +* [node9](https://github.com/jvburnes/node9): A portable, hybrid, distributed OS based on Inferno, LuaJIT and Libuv +* [node.js](http://www.nodejs.org/): Javascript (using Google's V8) + libuv +* [node.native](https://github.com/d5/node.native): node.js-like API for C++11 +* [nodeuv](https://github.com/nodeuv): An organization with several c++ wrappers for libs which are used in node.js. +* [phastlight](https://github.com/phastlight/phastlight): Command line tool and web server written in PHP 5.3+ inspired by Node.js +* [pilight](https://www.pilight.org/): home automation ("domotica") +* [pixie](https://github.com/pixie-lang/pixie): clojure-inspired lisp with a tracing JIT +* [potion](https://github.com/perl11/potion)/[p2](https://github.com/perl11/p2): runtime +* [racer](https://libraries.io/rubygems/racer): Ruby web server written as an C extension +* [spider-gazelle](https://github.com/cotag/spider-gazelle): Ruby web server using libuv bindings +* [Suave](http://suave.io/): A simple web development F# library providing a lightweight web server and a set of combinators to manipulate route flow and task composition +* [Swish](https://github.com/becls/swish/): Concurrency engine with Erlang-like concepts. Includes a web server. +* [Trevi](https://github.com/Yoseob/Trevi): A powerful Swift Web Application Server Framework Project +* [Urbit](http://urbit.org): runtime +* [uv_callback](https://github.com/litesync/uv_callback) libuv thread communication +* [uvloop](https://github.com/MagicStack/uvloop): Ultra fast implementation of python's asyncio event loop on top of libuv +* [Wren CLI](https://github.com/wren-lang/wren-cli): For io, process, scheduler and timer modules + +### Other +* [libtuv](https://github.com/Samsung/libtuv): libuv fork for IoT and embedded systems + +### Bindings +* [Ring](http://ring-lang.net) + * [RingLibuv](http://ring-lang.sourceforge.net/doc1.7/libuv.html) +* Ruby + * [libuv](https://github.com/cotag/libuv) + * [uvrb](https://github.com/avalanche123/uvrb) + * [ruv](https://github.com/aq1018/ruv) + * [rbuv](https://github.com/rbuv/rbuv) + * [mruby-uv](https://github.com/mattn/mruby-uv): mruby binding +* Lua + * [luv](https://github.com/creationix/luv) + * [lev](https://github.com/connectFree/lev) + * [lluv](https://github.com/moteus/lua-lluv) +* C++11 + * [uvpp](https://github.com/larroy/uvpp) - Not complete, exposes very few aspects of `libuv` +* C++17 + * [uvw](https://github.com/skypjack/uvw) - Header-only, event based, tiny and easy to use *libuv* wrapper in modern C++. +* Python + * [Pyuv](https://github.com/saghul/pyuv) + * [uvloop](https://github.com/MagicStack/uvloop) - Ultra fast asyncio event loop. + * [gevent](http://www.gevent.org) - Coroutine-based concurrency library for Python +* C# + * [NetUV](http://github.com/StormHub/NetUV) + * [LibuvSharp](http://github.com/txdv/LibuvSharp) +* Perl 5 + * [UV](https://metacpan.org/pod/UV) +* [Raku](https://raku.org/) + * [MoarVM](https://github.com/MoarVM/MoarVM) [uses](http://6guts.wordpress.com/2013/05/31/moarvm-a-virtual-machine-for-nqp-and-rakudo/) libuv +* PHP + * [php-uv](https://github.com/bwoebi/php-uv) +* Go + * [go-uv](https://github.com/mattn/go-uv) +* OCaml + * [luv](https://github.com/aantron/luv) + * [uwt](https://github.com/fdopen/uwt) +* ooc + * [ooc-uv](https://github.com/nddrylliog/ooc-uv) +* dylan + * [uv-dylan](https://github.com/waywardmonkeys/uv-dylan) +* R + * [httpuv](https://github.com/rstudio/httpuv): HTTP and WebSocket server library for R + * [fs](https://fs.r-lib.org/): Cross-platform file system operations +* Java + * [libuv-java](https://java.net/projects/avatar-js/sources/libuv-java/show): Java bindings +* Nim + * [nimuv](https://github.com/2vg/nimuv): Nim bindings +* Lisp + * [cl-libuv](https://github.com/orthecreedence/cl-libuv) Common Lisp bindings + * [cl-async](https://github.com/orthecreedence/cl-async) Common Lisp async abstraction on top of cl-libuv +* [Céu](http://www.ceu-lang.org) + * [Céu-libuv](https://github.com/fsantanna/ceu-libuv) +* Delphi + * [node.pas](https://github.com/vovach777/node.pas) NodeJS-like ecosystem +* Haskell + * [Z.Haskell](https://z.haskell.world) diff --git a/deps/libuv/MAINTAINERS.md b/deps/libuv/MAINTAINERS.md index 268251e6..fb7e5ef3 100644 --- a/deps/libuv/MAINTAINERS.md +++ b/deps/libuv/MAINTAINERS.md @@ -16,6 +16,7 @@ libuv is currently managed by the following individuals: * **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq)) - GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere) * **Jameson Nash** ([@vtjnash](https://github.com/vtjnash)) + - GPG key: AEAD 0A4B 6867 6775 1A0E 4AEF 34A2 5FB1 2824 6514 (pubkey-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) diff --git a/deps/libuv/Makefile.am b/deps/libuv/Makefile.am index 46308eaa..5830003c 100644 --- a/deps/libuv/Makefile.am +++ b/deps/libuv/Makefile.am @@ -56,7 +56,7 @@ if WINNT uvinclude_HEADERS += include/uv/win.h include/uv/tree.h AM_CPPFLAGS += -I$(top_srcdir)/src/win \ -DWIN32_LEAN_AND_MEAN \ - -D_WIN32_WINNT=0x0600 + -D_WIN32_WINNT=0x0602 libuv_la_SOURCES += src/win/async.c \ src/win/atomicops-inl.h \ src/win/core.c \ @@ -206,6 +206,9 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-metrics.c \ test/test-multiple-listen.c \ test/test-mutexes.c \ + test/test-not-readable-nor-writable-on-read-error.c \ + test/test-not-readable-on-eof.c \ + test/test-not-writable-after-shutdown.c \ test/test-osx-select.c \ test/test-pass-always.c \ test/test-ping-pong.c \ @@ -225,6 +228,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-poll-close.c \ test/test-poll-close-doesnt-corrupt-stack.c \ test/test-poll-closesocket.c \ + test/test-poll-multiple-handles.c \ test/test-poll-oob.c \ test/test-process-priority.c \ test/test-process-title.c \ @@ -237,6 +241,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-semaphore.c \ test/test-shutdown-close.c \ test/test-shutdown-eof.c \ + test/test-shutdown-simultaneous.c \ test/test-shutdown-twice.c \ test/test-signal-multiple-loops.c \ test/test-signal-pending-on-close.c \ @@ -385,13 +390,10 @@ if ANDROID uvinclude_HEADERS += include/uv/android-ifaddrs.h libuv_la_CFLAGS += -D_GNU_SOURCE libuv_la_SOURCES += src/unix/android-ifaddrs.c \ - src/unix/linux-core.c \ - src/unix/linux-inotify.c \ - src/unix/linux-syscalls.c \ - src/unix/procfs-exepath.c \ src/unix/pthread-fixes.c \ src/unix/random-getrandom.c \ - src/unix/random-sysctl-linux.c + src/unix/random-sysctl-linux.c \ + src/unix/epoll.c endif if CYGWIN @@ -472,7 +474,8 @@ libuv_la_SOURCES += src/unix/linux-core.c \ src/unix/procfs-exepath.c \ src/unix/proctitle.c \ src/unix/random-getrandom.c \ - src/unix/random-sysctl-linux.c + src/unix/random-sysctl-linux.c \ + src/unix/epoll.c test_run_tests_LDFLAGS += -lutil endif diff --git a/deps/libuv/README.md b/deps/libuv/README.md index 98007c5e..a9a8a9d1 100644 --- a/deps/libuv/README.md +++ b/deps/libuv/README.md @@ -5,7 +5,7 @@ libuv is a multi-platform support library with a focus on asynchronous I/O. It was primarily developed for use by [Node.js][], but it's also used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/), -[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/wiki/Projects-that-use-libuv). +[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/blob/v1.x/LINKS.md). ## Feature highlights @@ -48,9 +48,8 @@ The documentation is licensed under the CC BY 4.0 license. Check the [LICENSE-do ## Community - * [Support](https://github.com/libuv/help) + * [Support](https://github.com/libuv/libuv/discussions) * [Mailing list](http://groups.google.com/group/libuv) - * [IRC chatroom (#libuv@irc.freenode.org)](http://webchat.freenode.net?channels=libuv&uio=d4) ## Documentation @@ -286,6 +285,16 @@ listed in `test/benchmark-list.h`. Check the [SUPPORTED_PLATFORMS file](SUPPORTED_PLATFORMS.md). +### `-fno-strict-aliasing` + +It is recommended to turn on the `-fno-strict-aliasing` compiler flag in +projects that use libuv. The use of ad hoc "inheritance" in the libuv API +may not be safe in the presence of compiler optimizations that depend on +strict aliasing. + +MSVC does not have an equivalent flag but it also does not appear to need it +at the time of writing (December 2019.) + ### AIX Notes AIX compilation using IBM XL C/C++ requires version 12.1 or greater. @@ -298,6 +307,13 @@ describes the package in more detail. ### z/OS Notes +z/OS compilation requires [ZOSLIB](https://github.com/ibmruntimes/zoslib) to be installed. When building with [CMake][], use the flag `-DZOSLIB_DIR` to specify the path to [ZOSLIB](https://github.com/ibmruntimes/zoslib): + +```bash +$ (cd build && cmake .. -DBUILD_TESTING=ON -DZOSLIB_DIR=/path/to/zoslib) +$ cmake --build build +``` + z/OS creates System V semaphores and message queues. These persist on the system after the process terminates unless the event loop is closed. diff --git a/deps/libuv/SUPPORTED_PLATFORMS.md b/deps/libuv/SUPPORTED_PLATFORMS.md index 72e054eb..30e0ea61 100644 --- a/deps/libuv/SUPPORTED_PLATFORMS.md +++ b/deps/libuv/SUPPORTED_PLATFORMS.md @@ -4,14 +4,14 @@ |---|---|---|---| | GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | | | macOS | Tier 1 | macOS >= 10.7 | | -| Windows | Tier 1 | >= Windows 7 | MSVC 2008 and later are supported | +| Windows | Tier 1 | >= Windows 8 | VS 2015 and later are supported | | FreeBSD | Tier 1 | >= 10 | | | AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix | +| IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi | | z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos | | Linux with musl | Tier 2 | musl >= 1.0 | | | SmartOS | Tier 2 | >= 14.4 | Maintainers: @libuv/smartos | | Android | Tier 3 | NDK >= r15b | | -| IBM i | Tier 3 | >= IBM i 7.2 | Maintainers: @libuv/ibmi | | MinGW | Tier 3 | MinGW32 and MinGW-w64 | | | SunOS | Tier 3 | Solaris 121 and later | | | Other | Tier 3 | N/A | | diff --git a/deps/libuv/configure.ac b/deps/libuv/configure.ac index 1a66b74d..1fbb5c8c 100644 --- a/deps/libuv/configure.ac +++ b/deps/libuv/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.40.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.42.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]) @@ -24,7 +24,11 @@ AC_ENABLE_SHARED AC_ENABLE_STATIC AC_PROG_CC AM_PROG_CC_C_O -CC_FLAG_VISIBILITY #[-fvisibility=hidden] + +CC_ATTRIBUTE_VISIBILITY([default], [ + CC_FLAG_VISIBILITY([CFLAGS="${CFLAGS} -fvisibility=hidden"]) +]) +CC_CHECK_CFLAGS_APPEND([-fno-strict-aliasing]) CC_CHECK_CFLAGS_APPEND([-g]) CC_CHECK_CFLAGS_APPEND([-std=gnu89]) CC_CHECK_CFLAGS_APPEND([-Wall]) @@ -42,7 +46,7 @@ AX_PTHREAD([ LIBS="$LIBS $PTHREAD_LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ]) -AC_CHECK_LIB([dl], [dlopen]) +AC_SEARCH_LIBS([dlopen], [dl]) AC_SEARCH_LIBS([kstat_lookup], [kstat]) AC_SEARCH_LIBS([gethostbyname], [nsl]) AC_SEARCH_LIBS([perfstat_cpu], [perfstat]) diff --git a/deps/libuv/docs/code/dns/main.c b/deps/libuv/docs/code/dns/main.c index 77a7005f..2d63f1aa 100644 --- a/deps/libuv/docs/code/dns/main.c +++ b/deps/libuv/docs/code/dns/main.c @@ -69,8 +69,8 @@ int main() { hints.ai_flags = 0; uv_getaddrinfo_t resolver; - fprintf(stderr, "irc.freenode.net is... "); - int r = uv_getaddrinfo(loop, &resolver, on_resolved, "irc.freenode.net", "6667", &hints); + fprintf(stderr, "irc.libera.chat is... "); + int r = uv_getaddrinfo(loop, &resolver, on_resolved, "irc.libera.chat", "6667", &hints); if (r) { fprintf(stderr, "getaddrinfo call error %s\n", uv_err_name(r)); diff --git a/deps/libuv/docs/requirements.txt b/deps/libuv/docs/requirements.txt new file mode 100644 index 00000000..8386e017 --- /dev/null +++ b/deps/libuv/docs/requirements.txt @@ -0,0 +1,42 @@ +# primary +Sphinx==3.5.4 + +# dependencies +alabaster==0.7.12 +appdirs==1.4.3 +Babel==2.9.0 +CacheControl==0.12.6 +certifi==2019.11.28 +chardet==3.0.4 +colorama==0.4.3 +contextlib2==0.6.0 +distlib==0.3.0 +distro==1.4.0 +docutils==0.16 +html5lib==1.0.1 +idna==2.8 +imagesize==1.2.0 +ipaddr==2.2.0 +Jinja2==2.11.3 +lockfile==0.12.2 +MarkupSafe==1.1.1 +msgpack==0.6.2 +packaging==20.3 +pep517==0.8.2 +progress==1.5 +Pygments==2.8.1 +pyparsing==2.4.6 +pytoml==0.1.21 +pytz==2021.1 +requests==2.22.0 +retrying==1.3.3 +six==1.14.0 +snowballstemmer==2.1.0 +sphinxcontrib-applehelp==1.0.2 +sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-htmlhelp==1.0.3 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-serializinghtml==1.1.4 +urllib3==1.25.8 +webencodings==0.5.1 diff --git a/deps/libuv/docs/src/errors.rst b/deps/libuv/docs/src/errors.rst index c2daa858..c7240f35 100644 --- a/deps/libuv/docs/src/errors.rst +++ b/deps/libuv/docs/src/errors.rst @@ -251,6 +251,10 @@ Error constants operation not supported on socket +.. c:macro:: UV_EOVERFLOW + + value too large for defined data type + .. c:macro:: UV_EPERM operation not permitted @@ -331,6 +335,10 @@ Error constants illegal byte sequence +.. c:macro:: UV_ESOCKTNOSUPPORT + + socket type not supported + API --- diff --git a/deps/libuv/docs/src/guide/basics.rst b/deps/libuv/docs/src/guide/basics.rst index 1da8d5ef..e55a20cf 100644 --- a/deps/libuv/docs/src/guide/basics.rst +++ b/deps/libuv/docs/src/guide/basics.rst @@ -87,6 +87,7 @@ nothing, except start a loop which will exit immediately. .. rubric:: helloworld/main.c .. literalinclude:: ../../code/helloworld/main.c + :language: c :linenos: This program quits immediately because it has no events to process. A libuv @@ -202,6 +203,7 @@ event watchers are active. .. rubric:: idle-basic/main.c .. literalinclude:: ../../code/idle-basic/main.c + :language: c :emphasize-lines: 6,10,14-17 Storing context diff --git a/deps/libuv/docs/src/guide/eventloops.rst b/deps/libuv/docs/src/guide/eventloops.rst index fd9df5fb..12244ff6 100644 --- a/deps/libuv/docs/src/guide/eventloops.rst +++ b/deps/libuv/docs/src/guide/eventloops.rst @@ -20,6 +20,7 @@ these things can be a bit difficult to understand, so let's look at .. rubric:: src/unix/core.c - uv_run .. literalinclude:: ../../../src/unix/core.c + :language: c :linenos: :lines: 304-324 :emphasize-lines: 10,19,21 @@ -43,6 +44,7 @@ iteration of the loop still takes places. .. rubric:: uvstop/main.c .. literalinclude:: ../../code/uvstop/main.c + :language: c :linenos: :emphasize-lines: 11 diff --git a/deps/libuv/docs/src/guide/filesystem.rst b/deps/libuv/docs/src/guide/filesystem.rst index e89d4cd5..2d5f6cb9 100644 --- a/deps/libuv/docs/src/guide/filesystem.rst +++ b/deps/libuv/docs/src/guide/filesystem.rst @@ -54,6 +54,7 @@ a callback for when the file is opened: .. rubric:: uvcat/main.c - opening a file .. literalinclude:: ../../code/uvcat/main.c + :language: c :linenos: :lines: 41-53 :emphasize-lines: 4, 6-7 @@ -63,6 +64,7 @@ The ``result`` field of a ``uv_fs_t`` is the file descriptor in case of the .. rubric:: uvcat/main.c - read callback .. literalinclude:: ../../code/uvcat/main.c + :language: c :linenos: :lines: 26-40 :emphasize-lines: 2,8,12 @@ -87,6 +89,7 @@ callbacks. .. rubric:: uvcat/main.c - write callback .. literalinclude:: ../../code/uvcat/main.c + :language: c :linenos: :lines: 16-24 :emphasize-lines: 6 @@ -100,6 +103,7 @@ We set the dominos rolling in ``main()``: .. rubric:: uvcat/main.c .. literalinclude:: ../../code/uvcat/main.c + :language: c :linenos: :lines: 55- :emphasize-lines: 2 @@ -203,6 +207,7 @@ opened as bidirectional by default. .. rubric:: uvtee/main.c - read on pipes .. literalinclude:: ../../code/uvtee/main.c + :language: c :linenos: :lines: 61-80 :emphasize-lines: 4,5,15 @@ -218,6 +223,7 @@ these buffers. .. rubric:: uvtee/main.c - reading buffers .. literalinclude:: ../../code/uvtee/main.c + :language: c :linenos: :lines: 19-22,44-60 @@ -242,6 +248,7 @@ point there is nothing to be read. Most applications will just ignore this. .. rubric:: uvtee/main.c - Write to pipe .. literalinclude:: ../../code/uvtee/main.c + :language: c :linenos: :lines: 9-13,23-42 @@ -282,6 +289,7 @@ The file change notification is started using ``uv_fs_event_init()``: .. rubric:: onchange/main.c - The setup .. literalinclude:: ../../code/onchange/main.c + :language: c :linenos: :lines: 26- :emphasize-lines: 15 @@ -320,6 +328,7 @@ In our example we simply print the arguments and run the command using .. rubric:: onchange/main.c - file change notification callback .. literalinclude:: ../../code/onchange/main.c + :language: c :linenos: :lines: 9-24 diff --git a/deps/libuv/docs/src/guide/introduction.rst b/deps/libuv/docs/src/guide/introduction.rst index 0a3af434..0656e4d8 100644 --- a/deps/libuv/docs/src/guide/introduction.rst +++ b/deps/libuv/docs/src/guide/introduction.rst @@ -72,4 +72,4 @@ There is no need to ``make install``. To build the examples run ``make`` in the .. _node.js: https://www.nodejs.org .. _libev was removed: https://github.com/joyent/libuv/issues/485 .. _Rust: https://www.rust-lang.org -.. _variety: https://github.com/libuv/libuv/wiki/Projects-that-use-libuv +.. _variety: https://github.com/libuv/libuv/blob/v1.x/LINKS.md diff --git a/deps/libuv/docs/src/guide/networking.rst b/deps/libuv/docs/src/guide/networking.rst index b2f3fc77..dcb56431 100644 --- a/deps/libuv/docs/src/guide/networking.rst +++ b/deps/libuv/docs/src/guide/networking.rst @@ -38,6 +38,7 @@ Here is a simple echo server .. rubric:: tcp-echo-server/main.c - The listen socket .. literalinclude:: ../../code/tcp-echo-server/main.c + :language: c :linenos: :lines: 68- :emphasize-lines: 4-5,7-10 @@ -60,6 +61,7 @@ In this case we also establish interest in reading from this stream. .. rubric:: tcp-echo-server/main.c - Accepting the client .. literalinclude:: ../../code/tcp-echo-server/main.c + :language: c :linenos: :lines: 51-66 :emphasize-lines: 9-10 @@ -108,6 +110,7 @@ address from a `DHCP`_ server -- DHCP Discover. .. rubric:: udp-dhcp/main.c - Setup and send UDP packets .. literalinclude:: ../../code/udp-dhcp/main.c + :language: c :linenos: :lines: 7-11,104- :emphasize-lines: 8,10-11,17-18,21 @@ -143,6 +146,7 @@ the OS will discard the data that could not fit* (That's UDP for you!). .. rubric:: udp-dhcp/main.c - Reading packets .. literalinclude:: ../../code/udp-dhcp/main.c + :language: c :linenos: :lines: 17-40 :emphasize-lines: 1,23 @@ -189,10 +193,11 @@ Querying DNS libuv provides asynchronous DNS resolution. For this it provides its own ``getaddrinfo`` replacement [#]_. In the callback you can perform normal socket operations on the retrieved addresses. Let's connect to -Freenode to see an example of DNS resolution. +Libera.chat to see an example of DNS resolution. .. rubric:: dns/main.c .. literalinclude:: ../../code/dns/main.c + :language: c :linenos: :lines: 61- :emphasize-lines: 12 @@ -209,6 +214,7 @@ call ``uv_freeaddrinfo`` in the callback. .. rubric:: dns/main.c .. literalinclude:: ../../code/dns/main.c + :language: c :linenos: :lines: 42-60 :emphasize-lines: 8,16 @@ -227,6 +233,7 @@ useful to allow your service to bind to IP addresses when it starts. .. rubric:: interfaces/main.c .. literalinclude:: ../../code/interfaces/main.c + :language: c :linenos: :emphasize-lines: 9,17 diff --git a/deps/libuv/docs/src/guide/processes.rst b/deps/libuv/docs/src/guide/processes.rst index cbd8bce7..c1278f17 100644 --- a/deps/libuv/docs/src/guide/processes.rst +++ b/deps/libuv/docs/src/guide/processes.rst @@ -27,6 +27,7 @@ exits. This is achieved using ``uv_spawn``. .. rubric:: spawn/main.c .. literalinclude:: ../../code/spawn/main.c + :language: c :linenos: :lines: 6-8,15- :emphasize-lines: 11,13-17 @@ -54,6 +55,7 @@ which caused the exit. .. rubric:: spawn/main.c .. literalinclude:: ../../code/spawn/main.c + :language: c :linenos: :lines: 9-12 :emphasize-lines: 3 @@ -104,6 +106,7 @@ does not affect it. .. rubric:: detach/main.c .. literalinclude:: ../../code/detach/main.c + :language: c :linenos: :lines: 9-30 :emphasize-lines: 12,19 @@ -140,6 +143,7 @@ stop watching. Here is a small example demonstrating the various possibilities: .. rubric:: signal/main.c .. literalinclude:: ../../code/signal/main.c + :language: c :linenos: :emphasize-lines: 17-18,27-28 @@ -172,6 +176,7 @@ which is: .. rubric:: proc-streams/test.c .. literalinclude:: ../../code/proc-streams/test.c + :language: c The actual program ``proc-streams`` runs this while sharing only ``stderr``. The file descriptors of the child process are set using the ``stdio`` field in @@ -199,6 +204,7 @@ Then we set the ``fd`` to ``stderr``. .. rubric:: proc-streams/main.c .. literalinclude:: ../../code/proc-streams/main.c + :language: c :linenos: :lines: 15-17,27- :emphasize-lines: 6,10,11,12 @@ -217,12 +223,14 @@ A sample CGI script/executable is: .. rubric:: cgi/tick.c .. literalinclude:: ../../code/cgi/tick.c + :language: c The CGI server combines the concepts from this chapter and :doc:`networking` so that every client is sent ten ticks after which that connection is closed. .. rubric:: cgi/main.c .. literalinclude:: ../../code/cgi/main.c + :language: c :linenos: :lines: 49-63 :emphasize-lines: 10 @@ -232,6 +240,7 @@ Here we simply accept the TCP connection and pass on the socket (*stream*) to .. rubric:: cgi/main.c .. literalinclude:: ../../code/cgi/main.c + :language: c :linenos: :lines: 16, 25-45 :emphasize-lines: 8-9,18,20 @@ -291,6 +300,7 @@ messaging is no different from TCP, so we'll re-use the echo server example. .. rubric:: pipe-echo-server/main.c .. literalinclude:: ../../code/pipe-echo-server/main.c + :language: c :linenos: :lines: 70- :emphasize-lines: 5,10,14 @@ -330,6 +340,7 @@ it by the master. .. rubric:: multi-echo-server/worker.c .. literalinclude:: ../../code/multi-echo-server/worker.c + :language: c :linenos: :lines: 7-9,81- :emphasize-lines: 6-8 @@ -343,6 +354,7 @@ standard input of the worker, we connect the pipe to ``stdin`` using .. rubric:: multi-echo-server/worker.c .. literalinclude:: ../../code/multi-echo-server/worker.c + :language: c :linenos: :lines: 51-79 :emphasize-lines: 10,15,20 @@ -361,6 +373,7 @@ allow load balancing. .. rubric:: multi-echo-server/main.c .. literalinclude:: ../../code/multi-echo-server/main.c + :language: c :linenos: :lines: 9-13 @@ -369,6 +382,7 @@ master and the individual process. .. rubric:: multi-echo-server/main.c .. literalinclude:: ../../code/multi-echo-server/main.c + :language: c :linenos: :lines: 51,61-95 :emphasize-lines: 17,20-21 @@ -387,6 +401,7 @@ worker in the round-robin. .. rubric:: multi-echo-server/main.c .. literalinclude:: ../../code/multi-echo-server/main.c + :language: c :linenos: :lines: 31-49 :emphasize-lines: 9,12-13 diff --git a/deps/libuv/docs/src/guide/threads.rst b/deps/libuv/docs/src/guide/threads.rst index c610d47c..3990e442 100644 --- a/deps/libuv/docs/src/guide/threads.rst +++ b/deps/libuv/docs/src/guide/threads.rst @@ -39,6 +39,7 @@ wait for it to close using ``uv_thread_join()``. .. rubric:: thread-create/main.c .. literalinclude:: ../../code/thread-create/main.c + :language: c :linenos: :lines: 26-36 :emphasize-lines: 3-7 @@ -55,6 +56,7 @@ thread, scheduled pre-emptively by the operating system: .. rubric:: thread-create/main.c .. literalinclude:: ../../code/thread-create/main.c + :language: c :linenos: :lines: 6-14 :emphasize-lines: 2 @@ -124,6 +126,7 @@ example. .. rubric:: locks/main.c - simple rwlocks .. literalinclude:: ../../code/locks/main.c + :language: c :linenos: :emphasize-lines: 13,16,27,31,42,55 @@ -208,6 +211,7 @@ event loop from performing other activities. .. rubric:: queue-work/main.c - lazy fibonacci .. literalinclude:: ../../code/queue-work/main.c + :language: c :linenos: :lines: 17-29 @@ -221,6 +225,7 @@ The trigger is ``uv_queue_work``: .. rubric:: queue-work/main.c .. literalinclude:: ../../code/queue-work/main.c + :language: c :linenos: :lines: 31-44 :emphasize-lines: 10 @@ -248,6 +253,7 @@ up a signal handler for termination. .. rubric:: queue-cancel/main.c .. literalinclude:: ../../code/queue-cancel/main.c + :language: c :linenos: :lines: 43- @@ -256,6 +262,7 @@ When the user triggers the signal by pressing ``Ctrl+C`` we send .. rubric:: queue-cancel/main.c .. literalinclude:: ../../code/queue-cancel/main.c + :language: c :linenos: :lines: 33-41 :emphasize-lines: 6 @@ -265,6 +272,7 @@ with ``status`` set to ``UV_ECANCELED``. .. rubric:: queue-cancel/main.c .. literalinclude:: ../../code/queue-cancel/main.c + :language: c :linenos: :lines: 28-31 :emphasize-lines: 2 @@ -292,6 +300,7 @@ informing the user of the status of running downloads. .. rubric:: progress/main.c .. literalinclude:: ../../code/progress/main.c + :language: c :linenos: :lines: 7-8,35- :emphasize-lines: 2,11 @@ -317,6 +326,7 @@ with the async watcher whenever it receives a message. .. rubric:: progress/main.c .. literalinclude:: ../../code/progress/main.c + :language: c :linenos: :lines: 10-24 :emphasize-lines: 7-8 @@ -327,6 +337,7 @@ non-blocking and will return immediately. .. rubric:: progress/main.c .. literalinclude:: ../../code/progress/main.c + :language: c :linenos: :lines: 31-34 @@ -336,6 +347,7 @@ Finally it is important to remember to clean up the watcher. .. rubric:: progress/main.c .. literalinclude:: ../../code/progress/main.c + :language: c :linenos: :lines: 26-29 :emphasize-lines: 3 diff --git a/deps/libuv/docs/src/guide/utilities.rst b/deps/libuv/docs/src/guide/utilities.rst index a863c5ea..4657b1b0 100644 --- a/deps/libuv/docs/src/guide/utilities.rst +++ b/deps/libuv/docs/src/guide/utilities.rst @@ -87,6 +87,7 @@ JS object and can be ref/unrefed. .. rubric:: ref-timer/main.c .. literalinclude:: ../../code/ref-timer/main.c + :language: c :linenos: :lines: 5-8, 17- :emphasize-lines: 9 @@ -111,6 +112,7 @@ idle watcher to keep the UI operational. .. rubric:: idle-compute/main.c .. literalinclude:: ../../code/idle-compute/main.c + :language: c :linenos: :lines: 5-9, 34- :emphasize-lines: 13 @@ -123,6 +125,7 @@ keep calling the idle callback again. .. rubric:: idle-compute/main.c .. literalinclude:: ../../code/idle-compute/main.c + :language: c :linenos: :lines: 10-19 @@ -215,6 +218,7 @@ progress with the download whenever libuv notifies of I/O readiness. .. rubric:: uvwget/main.c - The setup .. literalinclude:: ../../code/uvwget/main.c + :language: c :linenos: :lines: 1-9,140- :emphasize-lines: 7,21,24-25 @@ -235,6 +239,7 @@ So we add each argument as an URL .. rubric:: uvwget/main.c - Adding urls .. literalinclude:: ../../code/uvwget/main.c + :language: c :linenos: :lines: 39-56 :emphasize-lines: 13-14 @@ -251,6 +256,7 @@ on sockets whenever ``handle_socket`` is called. .. rubric:: uvwget/main.c - Setting up polling .. literalinclude:: ../../code/uvwget/main.c + :language: c :linenos: :lines: 102-140 :emphasize-lines: 9,11,15,21,24 @@ -271,6 +277,7 @@ mask with the new value. ``curl_perform`` is the crux of this program. .. rubric:: uvwget/main.c - Driving libcurl. .. literalinclude:: ../../code/uvwget/main.c + :language: c :linenos: :lines: 81-95 :emphasize-lines: 2,6-7,12 @@ -288,6 +295,7 @@ transfers are done. .. rubric:: uvwget/main.c - Reading transfer status. .. literalinclude:: ../../code/uvwget/main.c + :language: c :linenos: :lines: 58-79 :emphasize-lines: 6,9-10,13-14 @@ -312,6 +320,7 @@ Let us first look at the interface provided to plugin authors. .. rubric:: plugin/plugin.h .. literalinclude:: ../../code/plugin/plugin.h + :language: c :linenos: You can similarly add more functions that plugin authors can use to do useful @@ -319,6 +328,7 @@ things in your application [#]_. A sample plugin using this API is: .. rubric:: plugin/hello.c .. literalinclude:: ../../code/plugin/hello.c + :language: c :linenos: Our interface defines that all plugins should have an ``initialize`` function @@ -340,6 +350,7 @@ This is done by using ``uv_dlopen`` to first load the shared library .. rubric:: plugin/main.c .. literalinclude:: ../../code/plugin/main.c + :language: c :linenos: :lines: 7- :emphasize-lines: 15, 18, 24 @@ -393,6 +404,7 @@ Here is a simple example which prints white text on a red background: .. rubric:: tty/main.c .. literalinclude:: ../../code/tty/main.c + :language: c :linenos: :emphasize-lines: 11-12,14,17,27 @@ -403,6 +415,7 @@ escape codes. .. rubric:: tty-gravity/main.c .. literalinclude:: ../../code/tty-gravity/main.c + :language: c :linenos: :emphasize-lines: 19,25,38 diff --git a/deps/libuv/docs/src/index.rst b/deps/libuv/docs/src/index.rst index f696dc16..4b5d4d2c 100644 --- a/deps/libuv/docs/src/index.rst +++ b/deps/libuv/docs/src/index.rst @@ -17,7 +17,7 @@ was primarily developed for use by `Node.js`_, but it's also used by `Luvit`_, .. _Luvit: https://luvit.io .. _Julia: https://julialang.org .. _pyuv: https://github.com/saghul/pyuv -.. _others: https://github.com/libuv/libuv/wiki/Projects-that-use-libuv +.. _others: https://github.com/libuv/libuv/blob/v1.x/LINKS.md Features diff --git a/deps/libuv/docs/src/misc.rst b/deps/libuv/docs/src/misc.rst index b2725c39..9a8595e5 100644 --- a/deps/libuv/docs/src/misc.rst +++ b/deps/libuv/docs/src/misc.rst @@ -533,7 +533,7 @@ API .. note:: This function currently only returns a non-zero value on Linux, based - on cgroups if it is present. + on cgroups if it is present, and on z/OS based on RLIMIT_MEMLIMIT. .. versionadded:: 1.29.0 diff --git a/deps/libuv/docs/src/pipe.rst b/deps/libuv/docs/src/pipe.rst index 6437a9d9..5fa83b80 100644 --- a/deps/libuv/docs/src/pipe.rst +++ b/deps/libuv/docs/src/pipe.rst @@ -118,3 +118,21 @@ API function is blocking. .. versionadded:: 1.16.0 + +.. c:function:: int uv_pipe(uv_file fds[2], int read_flags, int write_flags) + + Create a pair of connected pipe handles. + Data may be written to `fds[1]` and read from `fds[0]`. + The resulting handles can be passed to `uv_pipe_open`, used with `uv_spawn`, + or for any other purpose. + + Valid values for `flags` are: + + - UV_NONBLOCK_PIPE: Opens the specified socket handle for `OVERLAPPED` + or `FIONBIO`/`O_NONBLOCK` I/O usage. + This is recommended for handles that will be used by libuv, + and not usually recommended otherwise. + + Equivalent to :man:`pipe(2)` with the `O_CLOEXEC` flag set. + + .. versionadded:: 1.41.0 diff --git a/deps/libuv/docs/src/poll.rst b/deps/libuv/docs/src/poll.rst index aba89158..93a101ec 100644 --- a/deps/libuv/docs/src/poll.rst +++ b/deps/libuv/docs/src/poll.rst @@ -86,36 +86,63 @@ API .. c:function:: int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) Starts polling the file descriptor. `events` is a bitmask made up of - UV_READABLE, UV_WRITABLE, UV_PRIORITIZED and UV_DISCONNECT. As soon as an - event is detected the callback will be called with `status` set to 0, and the - detected events set on the `events` field. + `UV_READABLE`, `UV_WRITABLE`, `UV_PRIORITIZED` and `UV_DISCONNECT`. As soon + as an event is detected the callback will be called with `status` set to 0, + and the detected events set on the `events` field. - The UV_PRIORITIZED event is used to watch for sysfs interrupts or TCP out-of-band - messages. + The `UV_PRIORITIZED` event is used to watch for sysfs interrupts or TCP + out-of-band messages. - The UV_DISCONNECT event is optional in the sense that it may not be - reported and the user is free to ignore it, but it can help optimize the shutdown - path because an extra read or write call might be avoided. + The `UV_DISCONNECT` event is optional in the sense that it may not be + reported and the user is free to ignore it, but it can help optimize the + shutdown path because an extra read or write call might be avoided. If an error happens while polling, `status` will be < 0 and corresponds - with one of the UV_E* error codes (see :ref:`errors`). The user should + with one of the `UV_E*` error codes (see :ref:`errors`). The user should not close the socket while the handle is active. If the user does that - anyway, the callback *may* be called reporting an error status, but this - is **not** guaranteed. + anyway, the callback *may* be called reporting an error status, but this is + **not** guaranteed. .. note:: - Calling :c:func:`uv_poll_start` on a handle that is already active is fine. Doing so - will update the events mask that is being watched for. + Calling :c:func:`uv_poll_start` on a handle that is already active is + fine. Doing so will update the events mask that is being watched for. .. note:: - Though UV_DISCONNECT can be set, it is unsupported on AIX and as such will not be set - on the `events` field in the callback. + Though `UV_DISCONNECT` can be set, it is unsupported on AIX and as such + will not be set on the `events` field in the callback. - .. versionchanged:: 1.9.0 Added the UV_DISCONNECT event. - .. versionchanged:: 1.14.0 Added the UV_PRIORITIZED event. + .. note:: + If one of the events `UV_READABLE` or `UV_WRITABLE` are set, the + callback will be called again, as long as the given fd/socket remains + readable or writable accordingly. Particularly in each of the following + scenarios: + + * The callback has been called because the socket became + readable/writable and the callback did not conduct a read/write on + this socket at all. + * The callback committed a read on the socket, and has not read all the + available data (when `UV_READABLE` is set). + * The callback committed a write on the socket, but it remained + writable afterwards (when `UV_WRITABLE` is set). + * The socket has already became readable/writable before calling + :c:func:`uv_poll_start` on a poll handle associated with this socket, + and since then the state of the socket did not changed. + + In all of the above listed scenarios, the socket remains readable or + writable and hence the callback will be called again (depending on the + events set in the bitmask). This behaviour is known as level + triggering. + + .. versionchanged:: 1.9.0 Added the `UV_DISCONNECT` event. + .. versionchanged:: 1.14.0 Added the `UV_PRIORITIZED` event. .. c:function:: int uv_poll_stop(uv_poll_t* poll) Stop polling the file descriptor, the callback will no longer be called. + .. note:: + Calling :c:func:`uv_poll_stop` is effective immediately: any pending + callback is also canceled, even if the socket state change notification + was already pending. + .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/libuv/docs/src/process.rst b/deps/libuv/docs/src/process.rst index 8ff19add..ea6c4b9a 100644 --- a/deps/libuv/docs/src/process.rst +++ b/deps/libuv/docs/src/process.rst @@ -119,12 +119,14 @@ Data types * flags may be specified to create a duplex data stream. */ UV_READABLE_PIPE = 0x10, - UV_WRITABLE_PIPE = 0x20 + UV_WRITABLE_PIPE = 0x20, /* - * Open the child pipe handle in overlapped mode on Windows. - * On Unix it is silently ignored. - */ - UV_OVERLAPPED_PIPE = 0x40 + * When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the + * handle in non-blocking mode in the child. This may cause loss of data, + * if the child is not designed to handle to encounter this mode, + * but can also be significantly more efficient. + */ + UV_NONBLOCK_PIPE = 0x40 } uv_stdio_flags; diff --git a/deps/libuv/docs/src/stream.rst b/deps/libuv/docs/src/stream.rst index 2ccb59b5..0b42c4b3 100644 --- a/deps/libuv/docs/src/stream.rst +++ b/deps/libuv/docs/src/stream.rst @@ -139,6 +139,11 @@ API be made several times until there is no more data to read or :c:func:`uv_read_stop` is called. + .. versionchanged:: 1.38.0 :c:func:`uv_read_start()` now consistently + returns `UV_EALREADY` when called twice, and `UV_EINVAL` when the + stream is closing. With older libuv versions, it returns `UV_EALREADY` + on Windows but not UNIX, and `UV_EINVAL` on UNIX but not Windows. + .. c:function:: int uv_read_stop(uv_stream_t*) Stop reading data from the stream. The :c:type:`uv_read_cb` callback will @@ -146,6 +151,11 @@ API This function is idempotent and may be safely called on a stopped stream. + This function will always succeed; hence, checking its return value is + unnecessary. A non-zero return indicates that finishing releasing resources + may be pending on the next input event on that TTY on Windows, and does not + indicate failure. + .. c:function:: int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb) Write data to stream. Buffers are written in order. Example: @@ -183,8 +193,9 @@ API initialized with `ipc` == 1. .. note:: - `send_handle` must be a TCP socket or pipe, which is a server or a connection (listening - or connected state). Bound sockets or pipes will be assumed to be servers. + `send_handle` must be a TCP, pipe and UDP handle on Unix, or a TCP + handle on Windows, which is a server or a connection (listening or + connected state). Bound sockets or pipes will be assumed to be servers. .. c:function:: int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs) @@ -197,6 +208,16 @@ API * < 0: negative error code (``UV_EAGAIN`` is returned if no data can be sent immediately). +.. c:function:: int uv_try_write2(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle) + + Same as :c:func:`uv_try_write` and extended write function for sending + handles over a pipe like c:func:`uv_write2`. + + Try to send a handle is not supported on Windows, + where it returns ``UV_EAGAIN``. + + .. versionadded:: 1.42.0 + .. c:function:: int uv_is_readable(const uv_stream_t* handle) Returns 1 if the stream is readable, 0 otherwise. diff --git a/deps/libuv/docs/src/tcp.rst b/deps/libuv/docs/src/tcp.rst index 3cc8efaa..cccc86bb 100644 --- a/deps/libuv/docs/src/tcp.rst +++ b/deps/libuv/docs/src/tcp.rst @@ -81,10 +81,9 @@ API initialized ``struct sockaddr_in`` or ``struct sockaddr_in6``. When the port is already taken, you can expect to see an ``UV_EADDRINUSE`` - error from either :c:func:`uv_tcp_bind`, :c:func:`uv_listen` or - :c:func:`uv_tcp_connect`. That is, a successful call to this function does - not guarantee that the call to :c:func:`uv_listen` or :c:func:`uv_tcp_connect` - will succeed as well. + error from :c:func:`uv_listen` or :c:func:`uv_tcp_connect`. That is, + a successful call to this function does not guarantee that the call + to :c:func:`uv_listen` or :c:func:`uv_tcp_connect` will succeed as well. `flags` can contain ``UV_TCP_IPV6ONLY``, in which case dual-stack support is disabled and only IPv6 is used. @@ -128,3 +127,20 @@ API :c:func:`uv_tcp_close_reset` calls is not allowed. .. versionadded:: 1.32.0 + +.. c:function:: int uv_socketpair(int type, int protocol, uv_os_sock_t socket_vector[2], int flags0, int flags1) + + Create a pair of connected sockets with the specified properties. + The resulting handles can be passed to `uv_tcp_open`, used with `uv_spawn`, + or for any other purpose. + + Valid values for `flags0` and `flags1` are: + + - UV_NONBLOCK_PIPE: Opens the specified socket handle for `OVERLAPPED` + or `FIONBIO`/`O_NONBLOCK` I/O usage. + This is recommended for handles that will be used by libuv, + and not usually recommended otherwise. + + Equivalent to :man:`socketpair(2)` with a domain of AF_UNIX. + + .. versionadded:: 1.41.0 diff --git a/deps/libuv/docs/src/udp.rst b/deps/libuv/docs/src/udp.rst index 30aa4593..009767d5 100644 --- a/deps/libuv/docs/src/udp.rst +++ b/deps/libuv/docs/src/udp.rst @@ -53,6 +53,14 @@ Data types * in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL. */ UV_UDP_MMSG_FREE = 16, + /* + * Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle. + * This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on + * Linux. This stops the Linux kernel from supressing some ICMP error messages + * and enables full ICMP error reporting for faster failover. + * This flag is no-op on platforms other than Linux. + */ + UV_UDP_LINUX_RECVERR = 32, /* * Indicates that recvmmsg should be used, if available. */ @@ -73,7 +81,8 @@ Data types * `nread`: Number of bytes that have been received. 0 if there is no more data to read. Note that 0 may also mean that an empty datagram was received (in this case `addr` is not NULL). < 0 if - a transmission error was detected. + a transmission error was detected; if using :man:`recvmmsg(2)` no more + chunks will be received and the buffer can be freed safely. * `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. @@ -84,10 +93,11 @@ Data types on error. When using :man:`recvmmsg(2)`, chunks will have the `UV_UDP_MMSG_CHUNK` flag set, - those must not be freed. There will be a final callback with `nread` set to 0, - `addr` set to NULL and the buffer pointing at the initially allocated data with - the `UV_UDP_MMSG_CHUNK` flag cleared and the `UV_UDP_MMSG_FREE` flag set. - The callee can now safely free the provided buffer. + those must not be freed. If no errors occur, there will be a final callback with + `nread` set to 0, `addr` set to NULL and the buffer pointing at the initially + allocated data with the `UV_UDP_MMSG_CHUNK` flag cleared and the `UV_UDP_MMSG_FREE` + flag set. If a UDP socket error occurs, `nread` will be < 0. In either scenario, + the callee can now safely free the provided buffer. .. versionchanged:: 1.40.0 added the `UV_UDP_MMSG_FREE` flag. @@ -176,7 +186,8 @@ API with the address and port to bind to. :param flags: Indicate how the socket will be bound, - ``UV_UDP_IPV6ONLY`` and ``UV_UDP_REUSEADDR`` are supported. + ``UV_UDP_IPV6ONLY``, ``UV_UDP_REUSEADDR``, and ``UV_UDP_RECVERR`` + are supported. :returns: 0 on success, or an error code < 0 on failure. @@ -393,6 +404,11 @@ API :returns: 0 on success, or an error code < 0 on failure. + .. note:: + When using :man:`recvmmsg(2)`, the number of messages received at a time is limited + by the number of max size dgrams that will fit into the buffer allocated in `alloc_cb`, and + `suggested_size` in `alloc_cb` for udp_recv is always set to the size of 1 max size dgram. + .. versionchanged:: 1.35.0 added support for :man:`recvmmsg(2)` on supported platforms). The use of this feature requires a buffer larger than 2 * 64KB to be passed to `alloc_cb`. diff --git a/deps/libuv/include/uv.h b/deps/libuv/include/uv.h index 2557961e..77503bde 100644 --- a/deps/libuv/include/uv.h +++ b/deps/libuv/include/uv.h @@ -126,6 +126,7 @@ extern "C" { XX(ENOTEMPTY, "directory not empty") \ XX(ENOTSOCK, "socket operation on non-socket") \ XX(ENOTSUP, "operation not supported on socket") \ + XX(EOVERFLOW, "value too large for defined data type") \ XX(EPERM, "operation not permitted") \ XX(EPIPE, "broken pipe") \ XX(EPROTO, "protocol error") \ @@ -148,6 +149,7 @@ extern "C" { XX(ENOTTY, "inappropriate ioctl for device") \ XX(EFTYPE, "inappropriate file type or format") \ XX(EILSEQ, "illegal byte sequence") \ + XX(ESOCKTNOSUPPORT, "socket type not supported") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ @@ -475,6 +477,12 @@ UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd); UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len); +UV_EXTERN int uv_pipe(uv_file fds[2], int read_flags, int write_flags); +UV_EXTERN int uv_socketpair(int type, + int protocol, + uv_os_sock_t socket_vector[2], + int flags0, + int flags1); #define UV_STREAM_FIELDS \ /* number of bytes queued for writing */ \ @@ -520,6 +528,10 @@ UV_EXTERN int uv_write2(uv_write_t* req, UV_EXTERN int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs); +UV_EXTERN int uv_try_write2(uv_stream_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_stream_t* send_handle); /* uv_write_t is a subclass of uv_req_t. */ struct uv_write_s { @@ -620,7 +632,14 @@ enum uv_udp_flags { * in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL. */ UV_UDP_MMSG_FREE = 16, - + /* + * Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle. + * This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on + * Linux. This stops the Linux kernel from suppressing some ICMP error + * messages and enables full ICMP error reporting for faster failover. + * This flag is no-op on platforms other than Linux. + */ + UV_UDP_LINUX_RECVERR = 32, /* * Indicates that recvmmsg should be used, if available. */ @@ -933,10 +952,13 @@ typedef enum { UV_WRITABLE_PIPE = 0x20, /* - * Open the child pipe handle in overlapped mode on Windows. - * On Unix it is silently ignored. + * When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the + * handle in non-blocking mode in the child. This may cause loss of data, + * if the child is not designed to handle to encounter this mode, + * but can also be significantly more efficient. */ - UV_OVERLAPPED_PIPE = 0x40 + UV_NONBLOCK_PIPE = 0x40, + UV_OVERLAPPED_PIPE = 0x40 /* old name, for compatibility */ } uv_stdio_flags; typedef struct uv_stdio_container_s { diff --git a/deps/libuv/include/uv/errno.h b/deps/libuv/include/uv/errno.h index aadce9c1..71906b3f 100644 --- a/deps/libuv/include/uv/errno.h +++ b/deps/libuv/include/uv/errno.h @@ -445,4 +445,16 @@ # define UV__EILSEQ (-4027) #endif +#if defined(EOVERFLOW) && !defined(_WIN32) +# define UV__EOVERFLOW UV__ERR(EOVERFLOW) +#else +# define UV__EOVERFLOW (-4026) +#endif + +#if defined(ESOCKTNOSUPPORT) && !defined(_WIN32) +# define UV__ESOCKTNOSUPPORT UV__ERR(ESOCKTNOSUPPORT) +#else +# define UV__ESOCKTNOSUPPORT (-4025) +#endif + #endif /* UV_ERRNO_H_ */ diff --git a/deps/libuv/include/uv/tree.h b/deps/libuv/include/uv/tree.h index f936416e..2b28835f 100644 --- a/deps/libuv/include/uv/tree.h +++ b/deps/libuv/include/uv/tree.h @@ -251,7 +251,7 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \ __left = __right = &__node; \ \ - while (1) { \ + for (;;) { \ if (__comp < 0) { \ __tmp = SPLAY_LEFT((head)->sph_root, field); \ if (__tmp == NULL) \ diff --git a/deps/libuv/include/uv/version.h b/deps/libuv/include/uv/version.h index 5272008a..d5ba36c3 100644 --- a/deps/libuv/include/uv/version.h +++ b/deps/libuv/include/uv/version.h @@ -31,7 +31,7 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 40 +#define UV_VERSION_MINOR 42 #define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/libuv/src/idna.c b/deps/libuv/src/idna.c index 13ffac6b..b44cb16a 100644 --- a/deps/libuv/src/idna.c +++ b/deps/libuv/src/idna.c @@ -19,6 +19,7 @@ #include "uv.h" #include "idna.h" +#include #include static unsigned uv__utf8_decode1_slow(const char** p, @@ -32,7 +33,7 @@ static unsigned uv__utf8_decode1_slow(const char** p, if (a > 0xF7) return -1; - switch (*p - pe) { + switch (pe - *p) { default: if (a > 0xEF) { min = 0x10000; @@ -62,6 +63,8 @@ static unsigned uv__utf8_decode1_slow(const char** p, a = 0; break; } + /* Fall through. */ + case 0: return -1; /* Invalid continuation byte. */ } @@ -88,6 +91,8 @@ static unsigned uv__utf8_decode1_slow(const char** p, unsigned uv__utf8_decode1(const char** p, const char* pe) { unsigned a; + assert(*p < pe); + a = (unsigned char) *(*p)++; if (a < 128) @@ -96,9 +101,6 @@ unsigned uv__utf8_decode1(const char** p, const char* pe) { return uv__utf8_decode1_slow(p, pe, a); } -#define foreach_codepoint(c, p, pe) \ - for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;) - static int uv__idna_toascii_label(const char* s, const char* se, char** d, char* de) { static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789"; @@ -121,15 +123,22 @@ static int uv__idna_toascii_label(const char* s, const char* se, ss = s; todo = 0; - foreach_codepoint(c, &s, se) { + /* Note: after this loop we've visited all UTF-8 characters and know + * they're legal so we no longer need to check for decode errors. + */ + while (s < se) { + c = uv__utf8_decode1(&s, se); + + if (c == -1u) + return UV_EINVAL; + if (c < 128) h++; - else if (c == (unsigned) -1) - return UV_EINVAL; else todo++; } + /* Only write "xn--" when there are non-ASCII characters. */ if (todo > 0) { if (*d < de) *(*d)++ = 'x'; if (*d < de) *(*d)++ = 'n'; @@ -137,9 +146,13 @@ static int uv__idna_toascii_label(const char* s, const char* se, if (*d < de) *(*d)++ = '-'; } + /* Write ASCII characters. */ x = 0; s = ss; - foreach_codepoint(c, &s, se) { + while (s < se) { + c = uv__utf8_decode1(&s, se); + assert(c != -1u); + if (c > 127) continue; @@ -166,10 +179,15 @@ static int uv__idna_toascii_label(const char* s, const char* se, while (todo > 0) { m = -1; s = ss; - foreach_codepoint(c, &s, se) + + while (s < se) { + c = uv__utf8_decode1(&s, se); + assert(c != -1u); + if (c >= n) if (c < m) m = c; + } x = m - n; y = h + 1; @@ -181,7 +199,10 @@ static int uv__idna_toascii_label(const char* s, const char* se, n = m; s = ss; - foreach_codepoint(c, &s, se) { + while (s < se) { + c = uv__utf8_decode1(&s, se); + assert(c != -1u); + if (c < n) if (++delta == 0) return UV_E2BIG; /* Overflow. */ @@ -245,8 +266,6 @@ static int uv__idna_toascii_label(const char* s, const char* se, return 0; } -#undef foreach_codepoint - long uv__idna_toascii(const char* s, const char* se, char* d, char* de) { const char* si; const char* st; @@ -256,10 +275,14 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) { ds = d; - for (si = s; si < se; /* empty */) { + si = s; + while (si < se) { st = si; c = uv__utf8_decode1(&si, se); + if (c == -1u) + return UV_EINVAL; + if (c != '.') if (c != 0x3002) /* 。 */ if (c != 0xFF0E) /* . */ diff --git a/deps/libuv/src/inet.c b/deps/libuv/src/inet.c index 698ab232..ddabf22f 100644 --- a/deps/libuv/src/inet.c +++ b/deps/libuv/src/inet.c @@ -141,8 +141,9 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) { if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words)) *tp++ = ':'; *tp++ = '\0'; - if (UV_E2BIG == uv__strscpy(dst, tmp, size)) + if ((size_t) (tp - tmp) > size) return UV_ENOSPC; + uv__strscpy(dst, tmp, size); return 0; } diff --git a/deps/libuv/src/threadpool.c b/deps/libuv/src/threadpool.c index 0998938f..869ae95f 100644 --- a/deps/libuv/src/threadpool.c +++ b/deps/libuv/src/threadpool.c @@ -161,7 +161,6 @@ static void post(QUEUE* q, enum uv__work_kind kind) { void uv__threadpool_cleanup(void) { -#ifndef _WIN32 unsigned int i; if (nthreads == 0) @@ -181,7 +180,6 @@ void uv__threadpool_cleanup(void) { threads = NULL; nthreads = 0; -#endif } diff --git a/deps/libuv/src/timer.c b/deps/libuv/src/timer.c index 1bea2a8b..bc680e71 100644 --- a/deps/libuv/src/timer.c +++ b/deps/libuv/src/timer.c @@ -58,6 +58,7 @@ static int timer_less_than(const struct heap_node* ha, int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER); handle->timer_cb = NULL; + handle->timeout = 0; handle->repeat = 0; return 0; } diff --git a/deps/libuv/src/unix/async.c b/deps/libuv/src/unix/async.c index 5f58fb88..e1805c32 100644 --- a/deps/libuv/src/unix/async.c +++ b/deps/libuv/src/unix/async.c @@ -214,7 +214,7 @@ static int uv__async_start(uv_loop_t* loop) { pipefd[0] = err; pipefd[1] = -1; #else - err = uv__make_pipe(pipefd, UV__F_NONBLOCK); + err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE); if (err < 0) return err; #endif diff --git a/deps/libuv/src/unix/atomic-ops.h b/deps/libuv/src/unix/atomic-ops.h index 347d1936..c48d0584 100644 --- a/deps/libuv/src/unix/atomic-ops.h +++ b/deps/libuv/src/unix/atomic-ops.h @@ -52,9 +52,11 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { UV_UNUSED(static void cpu_relax(void)) { #if defined(__i386__) || defined(__x86_64__) - __asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */ + __asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */ #elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__) - __asm__ volatile("yield"); + __asm__ __volatile__ ("yield" ::: "memory"); +#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) + __asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory"); #endif } diff --git a/deps/libuv/src/unix/bsd-ifaddrs.c b/deps/libuv/src/unix/bsd-ifaddrs.c index 5223ab48..e48934bc 100644 --- a/deps/libuv/src/unix/bsd-ifaddrs.c +++ b/deps/libuv/src/unix/bsd-ifaddrs.c @@ -42,8 +42,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { return 1; #if !defined(__CYGWIN__) && !defined(__MSYS__) /* - * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, just see whether `sa_family` - * equals to `AF_LINK` or not. Otherwise, the result depends on the operation + * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family` + * equals `AF_LINK`. Otherwise, the result depends on the operating * system with `AF_LINK` or `PF_INET`. */ if (exclude_type == UV__EXCLUDE_IFPHYS) @@ -53,7 +53,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { defined(__HAIKU__) /* * On BSD getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information. + * devices. We're not interested in this information. */ if (ent->ifa_addr->sa_family == AF_LINK) return 1; diff --git a/deps/libuv/src/unix/core.c b/deps/libuv/src/unix/core.c index 1597828c..71e9c525 100644 --- a/deps/libuv/src/unix/core.c +++ b/deps/libuv/src/unix/core.c @@ -88,6 +88,10 @@ extern char** environ; # define uv__accept4 accept4 #endif +#if defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__) +# include +#endif + static int uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */ @@ -539,7 +543,13 @@ int uv__close_nocancel(int fd) { return close$NOCANCEL$UNIX2003(fd); #endif #pragma GCC diagnostic pop -#elif defined(__linux__) +#elif defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__) + long rc; + __sanitizer_syscall_pre_close(fd); + rc = syscall(SYS_close, fd); + __sanitizer_syscall_post_close(rc, fd); + return rc; +#elif defined(__linux__) && !defined(__SANITIZE_THREAD__) return syscall(SYS_close, fd); #else return close(fd); @@ -574,7 +584,7 @@ int uv__close(int fd) { return uv__close_nocheckstdio(fd); } - +#if UV__NONBLOCK_IS_IOCTL int uv__nonblock_ioctl(int fd, int set) { int r; @@ -589,7 +599,6 @@ int uv__nonblock_ioctl(int fd, int set) { } -#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__) int uv__cloexec_ioctl(int fd, int set) { int r; @@ -925,13 +934,12 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { if (w->pevents == 0) { QUEUE_REMOVE(&w->watcher_queue); QUEUE_INIT(&w->watcher_queue); + w->events = 0; - if (loop->watchers[w->fd] != NULL) { - assert(loop->watchers[w->fd] == w); + if (w == loop->watchers[w->fd]) { assert(loop->nfds > 0); loop->watchers[w->fd] = NULL; loop->nfds--; - w->events = 0; } } else if (QUEUE_EMPTY(&w->watcher_queue)) @@ -1175,7 +1183,9 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { if (buf == NULL) return UV_ENOMEM; - r = getpwuid_r(uid, &pw, buf, bufsize, &result); + do + r = getpwuid_r(uid, &pw, buf, bufsize, &result); + while (r == EINTR); if (r != ERANGE) break; @@ -1185,7 +1195,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { if (r != 0) { uv__free(buf); - return -r; + return UV__ERR(r); } if (result == NULL) { @@ -1571,7 +1581,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) { buf[*buflen] = '\0'; return 0; - } + } /* Case iii). Search PATH environment variable */ cloned_path = NULL; diff --git a/deps/libuv/src/unix/darwin.c b/deps/libuv/src/unix/darwin.c index d0ecd452..a7be0dd2 100644 --- a/deps/libuv/src/unix/darwin.c +++ b/deps/libuv/src/unix/darwin.c @@ -33,9 +33,7 @@ #include #include /* sysconf */ -#if !TARGET_OS_IPHONE #include "darwin-stub.h" -#endif static uv_once_t once = UV_ONCE_INIT; static uint64_t (*time_func)(void); @@ -223,10 +221,10 @@ static int uv__get_cpu_speed(uint64_t* speed) { err = UV_ENOENT; core_foundation_handle = dlopen("/System/Library/Frameworks/" "CoreFoundation.framework/" - "Versions/A/CoreFoundation", + "CoreFoundation", RTLD_LAZY | RTLD_LOCAL); iokit_handle = dlopen("/System/Library/Frameworks/IOKit.framework/" - "Versions/A/IOKit", + "IOKit", RTLD_LAZY | RTLD_LOCAL); if (core_foundation_handle == NULL || iokit_handle == NULL) @@ -304,6 +302,12 @@ static int uv__get_cpu_speed(uint64_t* speed) { pIOObjectRelease(it); err = 0; + + if (device_type_str != NULL) + pCFRelease(device_type_str); + if (clock_frequency_str != NULL) + pCFRelease(clock_frequency_str); + out: if (core_foundation_handle != NULL) dlclose(core_foundation_handle); diff --git a/deps/libuv/src/unix/epoll.c b/deps/libuv/src/unix/epoll.c new file mode 100644 index 00000000..97348e25 --- /dev/null +++ b/deps/libuv/src/unix/epoll.c @@ -0,0 +1,422 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" +#include +#include + +int uv__epoll_init(uv_loop_t* loop) { + int fd; + fd = epoll_create1(O_CLOEXEC); + + /* epoll_create1() can fail either because it's not implemented (old kernel) + * or because it doesn't understand the O_CLOEXEC flag. + */ + if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) { + fd = epoll_create(256); + + if (fd != -1) + uv__cloexec(fd, 1); + } + + loop->backend_fd = fd; + if (fd == -1) + return UV__ERR(errno); + + return 0; +} + + +void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { + struct epoll_event* events; + struct epoll_event dummy; + uintptr_t i; + uintptr_t nfds; + + assert(loop->watchers != NULL); + assert(fd >= 0); + + events = (struct epoll_event*) loop->watchers[loop->nwatchers]; + nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; + if (events != NULL) + /* Invalidate events with same file descriptor */ + for (i = 0; i < nfds; i++) + if (events[i].data.fd == fd) + events[i].data.fd = -1; + + /* Remove the file descriptor from the epoll. + * This avoids a problem where the same file description remains open + * in another process, causing repeated junk epoll events. + * + * We pass in a dummy epoll_event, to work around a bug in old kernels. + */ + if (loop->backend_fd >= 0) { + /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that + * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings. + */ + memset(&dummy, 0, sizeof(dummy)); + epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy); + } +} + + +int uv__io_check_fd(uv_loop_t* loop, int fd) { + struct epoll_event e; + int rc; + + memset(&e, 0, sizeof(e)); + e.events = POLLIN; + e.data.fd = -1; + + rc = 0; + if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e)) + if (errno != EEXIST) + rc = UV__ERR(errno); + + if (rc == 0) + if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e)) + abort(); + + return rc; +} + + +void uv__io_poll(uv_loop_t* loop, int timeout) { + /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes + * effectively infinite on 32 bits architectures. To avoid blocking + * indefinitely, we cap the timeout and poll again if necessary. + * + * Note that "30 minutes" is a simplification because it depends on + * the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200, + * that being the largest value I have seen in the wild (and only once.) + */ + static const int max_safe_timeout = 1789569; + static int no_epoll_pwait_cached; + static int no_epoll_wait_cached; + int no_epoll_pwait; + int no_epoll_wait; + struct epoll_event events[1024]; + struct epoll_event* pe; + struct epoll_event e; + int real_timeout; + QUEUE* q; + uv__io_t* w; + sigset_t sigset; + uint64_t sigmask; + uint64_t base; + int have_signals; + int nevents; + int count; + int nfds; + int fd; + int op; + int i; + int user_timeout; + int reset_timeout; + + if (loop->nfds == 0) { + assert(QUEUE_EMPTY(&loop->watcher_queue)); + return; + } + + memset(&e, 0, sizeof(e)); + + while (!QUEUE_EMPTY(&loop->watcher_queue)) { + q = QUEUE_HEAD(&loop->watcher_queue); + QUEUE_REMOVE(q); + QUEUE_INIT(q); + + w = QUEUE_DATA(q, uv__io_t, watcher_queue); + assert(w->pevents != 0); + assert(w->fd >= 0); + assert(w->fd < (int) loop->nwatchers); + + e.events = w->pevents; + e.data.fd = w->fd; + + if (w->events == 0) + op = EPOLL_CTL_ADD; + else + op = EPOLL_CTL_MOD; + + /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching + * events, skip the syscall and squelch the events after epoll_wait(). + */ + if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) { + if (errno != EEXIST) + abort(); + + assert(op == EPOLL_CTL_ADD); + + /* We've reactivated a file descriptor that's been watched before. */ + if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e)) + abort(); + } + + w->events = w->pevents; + } + + sigmask = 0; + if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { + sigemptyset(&sigset); + sigaddset(&sigset, SIGPROF); + sigmask |= 1 << (SIGPROF - 1); + } + + assert(timeout >= -1); + base = loop->time; + count = 48; /* Benchmarks suggest this gives the best throughput. */ + real_timeout = timeout; + + if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { + reset_timeout = 1; + user_timeout = timeout; + timeout = 0; + } else { + reset_timeout = 0; + user_timeout = 0; + } + + /* You could argue there is a dependency between these two but + * ultimately we don't care about their ordering with respect + * to one another. Worst case, we make a few system calls that + * could have been avoided because another thread already knows + * they fail with ENOSYS. Hardly the end of the world. + */ + no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached); + no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached); + + for (;;) { + /* Only need to set the provider_entry_time if timeout != 0. The function + * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. + */ + if (timeout != 0) + uv__metrics_set_provider_entry_time(loop); + + /* See the comment for max_safe_timeout for an explanation of why + * this is necessary. Executive summary: kernel bug workaround. + */ + if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) + timeout = max_safe_timeout; + + if (sigmask != 0 && no_epoll_pwait != 0) + if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) + abort(); + + if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) { + nfds = epoll_pwait(loop->backend_fd, + events, + ARRAY_SIZE(events), + timeout, + &sigset); + if (nfds == -1 && errno == ENOSYS) { + uv__store_relaxed(&no_epoll_pwait_cached, 1); + no_epoll_pwait = 1; + } + } else { + nfds = epoll_wait(loop->backend_fd, + events, + ARRAY_SIZE(events), + timeout); + if (nfds == -1 && errno == ENOSYS) { + uv__store_relaxed(&no_epoll_wait_cached, 1); + no_epoll_wait = 1; + } + } + + if (sigmask != 0 && no_epoll_pwait != 0) + if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) + abort(); + + /* Update loop->time unconditionally. It's tempting to skip the update when + * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the + * operating system didn't reschedule our process while in the syscall. + */ + SAVE_ERRNO(uv__update_time(loop)); + + if (nfds == 0) { + assert(timeout != -1); + + if (reset_timeout != 0) { + timeout = user_timeout; + reset_timeout = 0; + } + + if (timeout == -1) + continue; + + if (timeout == 0) + return; + + /* We may have been inside the system call for longer than |timeout| + * milliseconds so we need to update the timestamp to avoid drift. + */ + goto update_timeout; + } + + if (nfds == -1) { + if (errno == ENOSYS) { + /* epoll_wait() or epoll_pwait() failed, try the other system call. */ + assert(no_epoll_wait == 0 || no_epoll_pwait == 0); + continue; + } + + if (errno != EINTR) + abort(); + + if (reset_timeout != 0) { + timeout = user_timeout; + reset_timeout = 0; + } + + if (timeout == -1) + continue; + + if (timeout == 0) + return; + + /* Interrupted by a signal. Update timeout and poll again. */ + goto update_timeout; + } + + have_signals = 0; + nevents = 0; + + { + /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */ + union { + struct epoll_event* events; + uv__io_t* watchers; + } x; + + x.events = events; + assert(loop->watchers != NULL); + loop->watchers[loop->nwatchers] = x.watchers; + loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; + } + + for (i = 0; i < nfds; i++) { + pe = events + i; + fd = pe->data.fd; + + /* Skip invalidated events, see uv__platform_invalidate_fd */ + if (fd == -1) + continue; + + assert(fd >= 0); + assert((unsigned) fd < loop->nwatchers); + + w = loop->watchers[fd]; + + if (w == NULL) { + /* File descriptor that we've stopped watching, disarm it. + * + * Ignore all errors because we may be racing with another thread + * when the file descriptor is closed. + */ + epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe); + continue; + } + + /* Give users only events they're interested in. Prevents spurious + * callbacks when previous callback invocation in this loop has stopped + * the current watcher. Also, filters out events that users has not + * requested us to watch. + */ + pe->events &= w->pevents | POLLERR | POLLHUP; + + /* Work around an epoll quirk where it sometimes reports just the + * EPOLLERR or EPOLLHUP event. In order to force the event loop to + * move forward, we merge in the read/write events that the watcher + * is interested in; uv__read() and uv__write() will then deal with + * the error or hangup in the usual fashion. + * + * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user + * reads the available data, calls uv_read_stop(), then sometime later + * calls uv_read_start() again. By then, libuv has forgotten about the + * hangup and the kernel won't report EPOLLIN again because there's + * nothing left to read. If anything, libuv is to blame here. The + * current hack is just a quick bandaid; to properly fix it, libuv + * needs to remember the error/hangup event. We should get that for + * free when we switch over to edge-triggered I/O. + */ + if (pe->events == POLLERR || pe->events == POLLHUP) + pe->events |= + w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); + + if (pe->events != 0) { + /* Run signal watchers last. This also affects child process watchers + * because those are implemented in terms of signal watchers. + */ + if (w == &loop->signal_io_watcher) { + have_signals = 1; + } else { + uv__metrics_update_idle_time(loop); + w->cb(loop, w, pe->events); + } + + nevents++; + } + } + + if (reset_timeout != 0) { + timeout = user_timeout; + reset_timeout = 0; + } + + if (have_signals != 0) { + uv__metrics_update_idle_time(loop); + loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); + } + + loop->watchers[loop->nwatchers] = NULL; + loop->watchers[loop->nwatchers + 1] = NULL; + + if (have_signals != 0) + return; /* Event loop should cycle now so don't poll again. */ + + if (nevents != 0) { + if (nfds == ARRAY_SIZE(events) && --count != 0) { + /* Poll for more events but don't block this time. */ + timeout = 0; + continue; + } + return; + } + + if (timeout == 0) + return; + + if (timeout == -1) + continue; + +update_timeout: + assert(timeout > 0); + + real_timeout -= (loop->time - base); + if (real_timeout <= 0) + return; + + timeout = real_timeout; + } +} + diff --git a/deps/libuv/src/unix/freebsd.c b/deps/libuv/src/unix/freebsd.c index fe795a0e..170b897e 100644 --- a/deps/libuv/src/unix/freebsd.c +++ b/deps/libuv/src/unix/freebsd.c @@ -265,8 +265,11 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { -#if __FreeBSD__ >= 11 - return sendmmsg(fd, mmsg, vlen, /* flags */ 0); +#if __FreeBSD__ >= 11 && !defined(__DragonFly__) + return sendmmsg(fd, + (struct mmsghdr*) mmsg, + vlen, + 0 /* flags */); #else return errno = ENOSYS, -1; #endif @@ -274,8 +277,12 @@ int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { -#if __FreeBSD__ >= 11 - return recvmmsg(fd, mmsg, vlen, 0 /* flags */, NULL /* timeout */); +#if __FreeBSD__ >= 11 && !defined(__DragonFly__) + return recvmmsg(fd, + (struct mmsghdr*) mmsg, + vlen, + 0 /* flags */, + NULL /* timeout */); #else return errno = ENOSYS, -1; #endif diff --git a/deps/libuv/src/unix/fs.c b/deps/libuv/src/unix/fs.c index 556fd103..eb17fb4a 100644 --- a/deps/libuv/src/unix/fs.c +++ b/deps/libuv/src/unix/fs.c @@ -56,8 +56,13 @@ # define HAVE_PREADV 0 #endif +#if defined(__linux__) +# include "sys/utsname.h" +#endif + #if defined(__linux__) || defined(__sun) # include +# include #endif #if defined(__APPLE__) @@ -212,14 +217,30 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) { struct timespec ts; ts.tv_sec = time; - ts.tv_nsec = (uint64_t)(time * 1000000) % 1000000 * 1000; + ts.tv_nsec = (time - ts.tv_sec) * 1e9; + + /* TODO(bnoordhuis) Remove this. utimesat() has nanosecond resolution but we + * stick to microsecond resolution for the sake of consistency with other + * platforms. I'm the original author of this compatibility hack but I'm + * less convinced it's useful nowadays. + */ + ts.tv_nsec -= ts.tv_nsec % 1000; + + if (ts.tv_nsec < 0) { + ts.tv_nsec += 1e9; + ts.tv_sec -= 1; + } return ts; } UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) { struct timeval tv; tv.tv_sec = time; - tv.tv_usec = (uint64_t)(time * 1000000) % 1000000; + tv.tv_usec = (time - tv.tv_sec) * 1e6; + if (tv.tv_usec < 0) { + tv.tv_usec += 1e6; + tv.tv_sec -= 1; + } return tv; } @@ -227,9 +248,6 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { #if defined(__linux__) \ || defined(_AIX71) \ || defined(__HAIKU__) - /* utimesat() has nanosecond resolution but we stick to microseconds - * for the sake of consistency with other platforms. - */ struct timespec ts[2]; ts[0] = uv__fs_to_timespec(req->atime); ts[1] = uv__fs_to_timespec(req->mtime); @@ -887,6 +905,50 @@ out: } +#ifdef __linux__ +static unsigned uv__kernel_version(void) { + static unsigned cached_version; + struct utsname u; + unsigned version; + unsigned major; + unsigned minor; + unsigned patch; + + version = uv__load_relaxed(&cached_version); + if (version != 0) + return version; + + if (-1 == uname(&u)) + return 0; + + if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch)) + return 0; + + version = major * 65536 + minor * 256 + patch; + uv__store_relaxed(&cached_version, version); + + return version; +} + + +/* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command + * in copy_file_range() when it shouldn't. There is no workaround except to + * fall back to a regular copy. + */ +static int uv__is_buggy_cephfs(int fd) { + struct statfs s; + + if (-1 == fstatfs(fd, &s)) + return 0; + + if (s.f_type != /* CephFS */ 0xC36400) + return 0; + + return uv__kernel_version() < /* 4.20.0 */ 0x041400; +} +#endif /* __linux__ */ + + static ssize_t uv__fs_sendfile(uv_fs_t* req) { int in_fd; int out_fd; @@ -903,14 +965,25 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { #ifdef __linux__ { - static int copy_file_range_support = 1; + static int no_copy_file_range_support; - if (copy_file_range_support) { - r = uv__fs_copy_file_range(in_fd, NULL, out_fd, &off, req->bufsml[0].len, 0); + if (uv__load_relaxed(&no_copy_file_range_support) == 0) { + r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0); if (r == -1 && errno == ENOSYS) { + /* ENOSYS - it will never work */ + errno = 0; + uv__store_relaxed(&no_copy_file_range_support, 1); + } else if (r == -1 && errno == EACCES && uv__is_buggy_cephfs(in_fd)) { + /* EACCES - pre-4.20 kernels have a bug where CephFS uses the RADOS + copy-from command when it shouldn't */ + errno = 0; + uv__store_relaxed(&no_copy_file_range_support, 1); + } else if (r == -1 && (errno == ENOTSUP || errno == EXDEV)) { + /* ENOTSUP - it could work on another file system type */ + /* EXDEV - it will not work when in_fd and out_fd are not on the same + mounted filesystem (pre Linux 5.3) */ errno = 0; - copy_file_range_support = 0; } else { goto ok; } @@ -1010,9 +1083,6 @@ static ssize_t uv__fs_utime(uv_fs_t* req) { || defined(_AIX71) \ || defined(__sun) \ || defined(__HAIKU__) - /* utimesat() has nanosecond resolution but we stick to microseconds - * for the sake of consistency with other platforms. - */ struct timespec ts[2]; ts[0] = uv__fs_to_timespec(req->atime); ts[1] = uv__fs_to_timespec(req->mtime); @@ -1220,7 +1290,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { if (fstatfs(dstfd, &s) == -1) goto out; - if (s.f_type != /* CIFS */ 0xFF534D42u) + if ((unsigned) s.f_type != /* CIFS */ 0xFF534D42u) goto out; } @@ -1340,7 +1410,8 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { dst->st_birthtim.tv_nsec = src->st_ctimensec; dst->st_flags = 0; dst->st_gen = 0; -#elif !defined(_AIX) && ( \ +#elif !defined(_AIX) && \ + !defined(__MVS__) && ( \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ defined(__OpenBSD__) || \ @@ -1420,8 +1491,9 @@ static int uv__fs_statx(int fd, case -1: /* EPERM happens when a seccomp filter rejects the system call. * Has been observed with libseccomp < 2.3.3 and docker < 18.04. + * EOPNOTSUPP is used on DVS exported filesystems */ - if (errno != EINVAL && errno != EPERM && errno != ENOSYS) + if (errno != EINVAL && errno != EPERM && errno != ENOSYS && errno != EOPNOTSUPP) return -1; /* Fall through. */ default: @@ -1434,12 +1506,12 @@ static int uv__fs_statx(int fd, return UV_ENOSYS; } - buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor; + buf->st_dev = makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor); buf->st_mode = statxbuf.stx_mode; buf->st_nlink = statxbuf.stx_nlink; buf->st_uid = statxbuf.stx_uid; buf->st_gid = statxbuf.stx_gid; - buf->st_rdev = statxbuf.stx_rdev_major; + buf->st_rdev = makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor); buf->st_ino = statxbuf.stx_ino; buf->st_size = statxbuf.stx_size; buf->st_blksize = statxbuf.stx_blksize; diff --git a/deps/libuv/src/unix/fsevents.c b/deps/libuv/src/unix/fsevents.c index a51f29b3..bf4f1f6a 100644 --- a/deps/libuv/src/unix/fsevents.c +++ b/deps/libuv/src/unix/fsevents.c @@ -595,8 +595,7 @@ out: static int uv__fsevents_loop_init(uv_loop_t* loop) { CFRunLoopSourceContext ctx; uv__cf_loop_state_t* state; - pthread_attr_t attr_storage; - pthread_attr_t* attr; + pthread_attr_t attr; int err; if (loop->cf_state != NULL) @@ -641,25 +640,19 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { goto fail_signal_source_create; } - /* In the unlikely event that pthread_attr_init() fails, create the thread - * with the default stack size. We'll use a little more address space but - * that in itself is not a fatal error. - */ - attr = &attr_storage; - if (pthread_attr_init(attr)) - attr = NULL; + if (pthread_attr_init(&attr)) + abort(); - if (attr != NULL) - if (pthread_attr_setstacksize(attr, 4 * PTHREAD_STACK_MIN)) - abort(); + if (pthread_attr_setstacksize(&attr, uv__thread_stack_size())) + abort(); loop->cf_state = state; /* uv_thread_t is an alias for pthread_t. */ - err = UV__ERR(pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop)); + err = UV__ERR(pthread_create(&loop->cf_thread, &attr, uv__cf_loop_runner, loop)); - if (attr != NULL) - pthread_attr_destroy(attr); + if (pthread_attr_destroy(&attr)) + abort(); if (err) goto fail_thread_create; diff --git a/deps/libuv/src/unix/getaddrinfo.c b/deps/libuv/src/unix/getaddrinfo.c index d7ca7d1a..77337ace 100644 --- a/deps/libuv/src/unix/getaddrinfo.c +++ b/deps/libuv/src/unix/getaddrinfo.c @@ -21,9 +21,6 @@ /* Expose glibc-specific EAI_* error codes. Needs to be defined before we * include any headers. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif #include "uv.h" #include "internal.h" diff --git a/deps/libuv/src/unix/ibmi.c b/deps/libuv/src/unix/ibmi.c index 96efc02b..8c6ae636 100644 --- a/deps/libuv/src/unix/ibmi.c +++ b/deps/libuv/src/unix/ibmi.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -166,7 +165,7 @@ static void iconv_a2e(const char* src, unsigned char dst[], size_t length) { srclen = strlen(src); if (srclen > length) - abort(); + srclen = length; for (i = 0; i < srclen; i++) dst[i] = a2e[src[i]]; /* padding the remaining part with spaces */ @@ -360,6 +359,10 @@ static int get_ibmi_physical_address(const char* line, char (*phys_addr)[6]) { if (rc != 0) return rc; + if (err.bytes_available > 0) { + return -1; + } + /* convert ebcdic loca_adapter_address to ascii first */ iconv_e2a(rcvr.loca_adapter_address, mac_addr, sizeof(rcvr.loca_adapter_address)); @@ -443,9 +446,42 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { } address->is_internal = cur->ifa_flags & IFF_LOOPBACK ? 1 : 0; if (!address->is_internal) { - int rc = get_ibmi_physical_address(address->name, &address->phys_addr); - if (rc != 0) - r = rc; + int rc = -1; + size_t name_len = strlen(address->name); + /* To get the associated MAC address, we must convert the address to a + * line description. Normally, the name field contains the line + * description name, but for VLANs it has the VLAN appended with a + * period. Since object names can also contain periods and numbers, there + * is no way to know if a returned name is for a VLAN or not. eg. + * *LIND ETH1.1 and *LIND ETH1, VLAN 1 both have the same name: ETH1.1 + * + * Instead, we apply the same heuristic used by some of the XPF ioctls: + * - names > 10 *must* contain a VLAN + * - assume names <= 10 do not contain a VLAN and try directly + * - if >10 or QDCRLIND returned an error, try to strip off a VLAN + * and try again + * - if we still get an error or couldn't find a period, leave the MAC as + * 00:00:00:00:00:00 + */ + if (name_len <= 10) { + /* Assume name does not contain a VLAN ID */ + rc = get_ibmi_physical_address(address->name, &address->phys_addr); + } + + if (name_len > 10 || rc != 0) { + /* The interface name must contain a VLAN ID suffix. Attempt to strip + * it off so we can get the line description to pass to QDCRLIND. + */ + char* temp_name = uv__strdup(address->name); + char* dot = strrchr(temp_name, '.'); + if (dot != NULL) { + *dot = '\0'; + if (strlen(temp_name) <= 10) { + rc = get_ibmi_physical_address(temp_name, &address->phys_addr); + } + } + uv__free(temp_name); + } } address++; @@ -498,4 +534,4 @@ int uv_get_process_title(char* buffer, size_t size) { } void uv__process_title_cleanup(void) { -} \ No newline at end of file +} diff --git a/deps/libuv/src/unix/internal.h b/deps/libuv/src/unix/internal.h index 570274ed..12d4da93 100644 --- a/deps/libuv/src/unix/internal.h +++ b/deps/libuv/src/unix/internal.h @@ -62,6 +62,17 @@ # include #endif +/* + * Define common detection for active Thread Sanitizer + * - clang uses __has_feature(thread_sanitizer) + * - gcc-7+ uses __SANITIZE_THREAD__ + */ +#if defined(__has_feature) +# if __has_feature(thread_sanitizer) +# define __SANITIZE_THREAD__ 1 +# endif +#endif + #if defined(PATH_MAX) # define UV__PATH_MAX PATH_MAX #else @@ -165,9 +176,11 @@ struct uv__stream_queued_fds_s { defined(__NetBSD__) #define uv__cloexec uv__cloexec_ioctl #define uv__nonblock uv__nonblock_ioctl +#define UV__NONBLOCK_IS_IOCTL 1 #else #define uv__cloexec uv__cloexec_fcntl #define uv__nonblock uv__nonblock_fcntl +#define UV__NONBLOCK_IS_IOCTL 0 #endif /* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute @@ -246,6 +259,7 @@ int uv__signal_loop_fork(uv_loop_t* loop); /* platform specific */ uint64_t uv__hrtime(uv_clocktype_t type); int uv__kqueue_init(uv_loop_t* loop); +int uv__epoll_init(uv_loop_t* loop); int uv__platform_loop_init(uv_loop_t* loop); void uv__platform_loop_delete(uv_loop_t* loop); void uv__platform_invalidate_fd(uv_loop_t* loop, int fd); @@ -261,6 +275,7 @@ void uv__prepare_close(uv_prepare_t* handle); void uv__process_close(uv_process_t* handle); void uv__stream_close(uv_stream_t* handle); void uv__tcp_close(uv_tcp_t* handle); +size_t uv__thread_stack_size(void); void uv__udp_close(uv_udp_t* handle); void uv__udp_finish_close(uv_udp_t* handle); uv_handle_type uv__handle_type(int fd); @@ -282,12 +297,6 @@ int uv___stream_fd(const uv_stream_t* handle); #define uv__stream_fd(handle) ((handle)->io_watcher.fd) #endif /* defined(__APPLE__) */ -#ifdef O_NONBLOCK -# define UV__F_NONBLOCK O_NONBLOCK -#else -# define UV__F_NONBLOCK 1 -#endif - int uv__make_pipe(int fds[2], int flags); #if defined(__APPLE__) @@ -327,7 +336,8 @@ int uv__getsockpeername(const uv_handle_t* handle, #if defined(__linux__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) + defined(__FreeBSD_kernel__) || \ + defined(__DragonFly__) #define HAVE_MMSG 1 struct uv__mmsghdr { struct msghdr msg_hdr; @@ -340,5 +350,11 @@ int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen); #define HAVE_MMSG 0 #endif +#if defined(__sun) +#if !defined(_POSIX_VERSION) || _POSIX_VERSION < 200809L +size_t strnlen(const char* s, size_t maxlen); +#endif +#endif + #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/deps/libuv/src/unix/linux-core.c b/deps/libuv/src/unix/linux-core.c index 4db2f050..2716e2be 100644 --- a/deps/libuv/src/unix/linux-core.c +++ b/deps/libuv/src/unix/linux-core.c @@ -82,29 +82,12 @@ static int read_times(FILE* statfile_fp, static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); static uint64_t read_cpufreq(unsigned int cpunum); - int uv__platform_loop_init(uv_loop_t* loop) { - int fd; - fd = epoll_create1(O_CLOEXEC); - - /* epoll_create1() can fail either because it's not implemented (old kernel) - * or because it doesn't understand the O_CLOEXEC flag. - */ - if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) { - fd = epoll_create(256); - - if (fd != -1) - uv__cloexec(fd, 1); - } - - loop->backend_fd = fd; + loop->inotify_fd = -1; loop->inotify_watchers = NULL; - if (fd == -1) - return UV__ERR(errno); - - return 0; + return uv__epoll_init(loop); } @@ -134,380 +117,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct epoll_event* events; - struct epoll_event dummy; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - assert(fd >= 0); - - events = (struct epoll_event*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events != NULL) - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if (events[i].data.fd == fd) - events[i].data.fd = -1; - - /* Remove the file descriptor from the epoll. - * This avoids a problem where the same file description remains open - * in another process, causing repeated junk epoll events. - * - * We pass in a dummy epoll_event, to work around a bug in old kernels. - */ - if (loop->backend_fd >= 0) { - /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that - * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings. - */ - memset(&dummy, 0, sizeof(dummy)); - epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy); - } -} - - -int uv__io_check_fd(uv_loop_t* loop, int fd) { - struct epoll_event e; - int rc; - - memset(&e, 0, sizeof(e)); - e.events = POLLIN; - e.data.fd = -1; - - rc = 0; - if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e)) - if (errno != EEXIST) - rc = UV__ERR(errno); - - if (rc == 0) - if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e)) - abort(); - - return rc; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes - * effectively infinite on 32 bits architectures. To avoid blocking - * indefinitely, we cap the timeout and poll again if necessary. - * - * Note that "30 minutes" is a simplification because it depends on - * the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200, - * that being the largest value I have seen in the wild (and only once.) - */ - static const int max_safe_timeout = 1789569; - static int no_epoll_pwait_cached; - static int no_epoll_wait_cached; - int no_epoll_pwait; - int no_epoll_wait; - struct epoll_event events[1024]; - struct epoll_event* pe; - struct epoll_event e; - int real_timeout; - QUEUE* q; - uv__io_t* w; - sigset_t sigset; - uint64_t sigmask; - uint64_t base; - int have_signals; - int nevents; - int count; - int nfds; - int fd; - int op; - int i; - int user_timeout; - int reset_timeout; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - memset(&e, 0, sizeof(e)); - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - e.events = w->pevents; - e.data.fd = w->fd; - - if (w->events == 0) - op = EPOLL_CTL_ADD; - else - op = EPOLL_CTL_MOD; - - /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching - * events, skip the syscall and squelch the events after epoll_wait(). - */ - if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) { - if (errno != EEXIST) - abort(); - - assert(op == EPOLL_CTL_ADD); - - /* We've reactivated a file descriptor that's been watched before. */ - if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e)) - abort(); - } - - w->events = w->pevents; - } - - sigmask = 0; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - sigemptyset(&sigset); - sigaddset(&sigset, SIGPROF); - sigmask |= 1 << (SIGPROF - 1); - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - real_timeout = timeout; - - if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { - reset_timeout = 1; - user_timeout = timeout; - timeout = 0; - } else { - reset_timeout = 0; - user_timeout = 0; - } - - /* You could argue there is a dependency between these two but - * ultimately we don't care about their ordering with respect - * to one another. Worst case, we make a few system calls that - * could have been avoided because another thread already knows - * they fail with ENOSYS. Hardly the end of the world. - */ - no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached); - no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached); - - for (;;) { - /* Only need to set the provider_entry_time if timeout != 0. The function - * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. - */ - if (timeout != 0) - uv__metrics_set_provider_entry_time(loop); - - /* See the comment for max_safe_timeout for an explanation of why - * this is necessary. Executive summary: kernel bug workaround. - */ - if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) - timeout = max_safe_timeout; - - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) - abort(); - - if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) { - nfds = epoll_pwait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout, - &sigset); - if (nfds == -1 && errno == ENOSYS) { - uv__store_relaxed(&no_epoll_pwait_cached, 1); - no_epoll_pwait = 1; - } - } else { - nfds = epoll_wait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout); - if (nfds == -1 && errno == ENOSYS) { - uv__store_relaxed(&no_epoll_wait_cached, 1); - no_epoll_wait = 1; - } - } - - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) - abort(); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - assert(timeout != -1); - - if (reset_timeout != 0) { - timeout = user_timeout; - reset_timeout = 0; - } - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* We may have been inside the system call for longer than |timeout| - * milliseconds so we need to update the timestamp to avoid drift. - */ - goto update_timeout; - } - - if (nfds == -1) { - if (errno == ENOSYS) { - /* epoll_wait() or epoll_pwait() failed, try the other system call. */ - assert(no_epoll_wait == 0 || no_epoll_pwait == 0); - continue; - } - - if (errno != EINTR) - abort(); - - if (reset_timeout != 0) { - timeout = user_timeout; - reset_timeout = 0; - } - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - have_signals = 0; - nevents = 0; - - { - /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */ - union { - struct epoll_event* events; - uv__io_t* watchers; - } x; - - x.events = events; - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = x.watchers; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - } - - for (i = 0; i < nfds; i++) { - pe = events + i; - fd = pe->data.fd; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - - assert(fd >= 0); - assert((unsigned) fd < loop->nwatchers); - - w = loop->watchers[fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * - * Ignore all errors because we may be racing with another thread - * when the file descriptor is closed. - */ - epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe); - continue; - } - - /* Give users only events they're interested in. Prevents spurious - * callbacks when previous callback invocation in this loop has stopped - * the current watcher. Also, filters out events that users has not - * requested us to watch. - */ - pe->events &= w->pevents | POLLERR | POLLHUP; - - /* Work around an epoll quirk where it sometimes reports just the - * EPOLLERR or EPOLLHUP event. In order to force the event loop to - * move forward, we merge in the read/write events that the watcher - * is interested in; uv__read() and uv__write() will then deal with - * the error or hangup in the usual fashion. - * - * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user - * reads the available data, calls uv_read_stop(), then sometime later - * calls uv_read_start() again. By then, libuv has forgotten about the - * hangup and the kernel won't report EPOLLIN again because there's - * nothing left to read. If anything, libuv is to blame here. The - * current hack is just a quick bandaid; to properly fix it, libuv - * needs to remember the error/hangup event. We should get that for - * free when we switch over to edge-triggered I/O. - */ - if (pe->events == POLLERR || pe->events == POLLHUP) - pe->events |= - w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); - - if (pe->events != 0) { - /* Run signal watchers last. This also affects child process watchers - * because those are implemented in terms of signal watchers. - */ - if (w == &loop->signal_io_watcher) { - have_signals = 1; - } else { - uv__metrics_update_idle_time(loop); - w->cb(loop, w, pe->events); - } - - nevents++; - } - } - - if (reset_timeout != 0) { - timeout = user_timeout; - reset_timeout = 0; - } - - if (have_signals != 0) { - uv__metrics_update_idle_time(loop); - loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); - } - - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (have_signals != 0) - return; /* Event loop should cycle now so don't poll again. */ - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - real_timeout -= (loop->time - base); - if (real_timeout <= 0) - return; - - timeout = real_timeout; - } -} - uint64_t uv__hrtime(uv_clocktype_t type) { static clock_t fast_clock_id = -1; @@ -602,22 +211,53 @@ err: return UV_EINVAL; } +static int uv__slurp(const char* filename, char* buf, size_t len) { + ssize_t n; + int fd; + + assert(len > 0); + + fd = uv__open_cloexec(filename, O_RDONLY); + if (fd < 0) + return fd; + + do + n = read(fd, buf, len - 1); + while (n == -1 && errno == EINTR); + + if (uv__close_nocheckstdio(fd)) + abort(); + + if (n < 0) + return UV__ERR(errno); + + buf[n] = '\0'; + + return 0; +} int uv_uptime(double* uptime) { static volatile int no_clock_boottime; + char buf[128]; struct timespec now; int r; + /* Try /proc/uptime first, then fallback to clock_gettime(). */ + + if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf))) + if (1 == sscanf(buf, "%lf", uptime)) + return 0; + /* Try CLOCK_BOOTTIME first, fall back to CLOCK_MONOTONIC if not available * (pre-2.6.39 kernels). CLOCK_MONOTONIC doesn't increase when the system * is suspended. */ if (no_clock_boottime) { - retry: r = clock_gettime(CLOCK_MONOTONIC, &now); + retry_clock_gettime: r = clock_gettime(CLOCK_MONOTONIC, &now); } else if ((r = clock_gettime(CLOCK_BOOTTIME, &now)) && errno == EINVAL) { no_clock_boottime = 1; - goto retry; + goto retry_clock_gettime; } if (r) @@ -709,14 +349,19 @@ static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) { } -/* Also reads the CPU frequency on x86. The other architectures only have - * a BogoMIPS field, which may not be very accurate. +/* Also reads the CPU frequency on ppc and x86. The other architectures only + * have a BogoMIPS field, which may not be very accurate. * * Note: Simply returns on error, uv_cpu_info() takes care of the cleanup. */ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { +#if defined(__PPC__) + static const char model_marker[] = "cpu\t\t: "; + static const char speed_marker[] = "clock\t\t: "; +#else static const char model_marker[] = "model name\t: "; static const char speed_marker[] = "cpu MHz\t\t: "; +#endif const char* inferred_model; unsigned int model_idx; unsigned int speed_idx; @@ -738,6 +383,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { #if defined(__arm__) || \ defined(__i386__) || \ defined(__mips__) || \ + defined(__PPC__) || \ defined(__x86_64__) fp = uv__open_file("/proc/cpuinfo"); if (fp == NULL) @@ -786,7 +432,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { } fclose(fp); -#endif /* __arm__ || __i386__ || __mips__ || __x86_64__ */ +#endif /* __arm__ || __i386__ || __mips__ || __PPC__ || __x86_64__ */ /* Now we want to make sure that all the models contain *something* because * it's not safe to leave them as null. Copy the last entry unless there @@ -824,9 +470,9 @@ static int read_times(FILE* statfile_fp, char buf[1024]; ticks = (unsigned int)sysconf(_SC_CLK_TCK); - multiplier = ((uint64_t)1000L / ticks); assert(ticks != (unsigned int) -1); assert(ticks != 0); + multiplier = ((uint64_t)1000L / ticks); rewind(statfile_fp); @@ -1025,32 +671,6 @@ void uv__set_process_title(const char* title) { } -static int uv__slurp(const char* filename, char* buf, size_t len) { - ssize_t n; - int fd; - - assert(len > 0); - - fd = uv__open_cloexec(filename, O_RDONLY); - if (fd < 0) - return fd; - - do - n = read(fd, buf, len - 1); - while (n == -1 && errno == EINTR); - - if (uv__close_nocheckstdio(fd)) - abort(); - - if (n < 0) - return UV__ERR(errno); - - buf[n] = '\0'; - - return 0; -} - - static uint64_t uv__read_proc_meminfo(const char* what) { uint64_t rc; char* p; diff --git a/deps/libuv/src/unix/linux-inotify.c b/deps/libuv/src/unix/linux-inotify.c index 42b601ad..c1bd260e 100644 --- a/deps/libuv/src/unix/linux-inotify.c +++ b/deps/libuv/src/unix/linux-inotify.c @@ -178,7 +178,7 @@ static void uv__inotify_read(uv_loop_t* loop, /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ char buf[4096]; - while (1) { + for (;;) { do size = read(loop->inotify_fd, buf, sizeof(buf)); while (size == -1 && errno == EINTR); diff --git a/deps/libuv/src/unix/linux-syscalls.c b/deps/libuv/src/unix/linux-syscalls.c index 44daaf12..5071cd56 100644 --- a/deps/libuv/src/unix/linux-syscalls.c +++ b/deps/libuv/src/unix/linux-syscalls.c @@ -194,37 +194,37 @@ int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { -#if defined(__NR_preadv) - return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); -#else +#if !defined(__NR_preadv) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 return errno = ENOSYS, -1; +#else + return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); #endif } ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { -#if defined(__NR_pwritev) - return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); -#else +#if !defined(__NR_pwritev) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 return errno = ENOSYS, -1; +#else + return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); #endif } int uv__dup3(int oldfd, int newfd, int flags) { -#if defined(__NR_dup3) - return syscall(__NR_dup3, oldfd, newfd, flags); -#else +#if !defined(__NR_dup3) || defined(__ANDROID_API__) && __ANDROID_API__ < 21 return errno = ENOSYS, -1; +#else + return syscall(__NR_dup3, oldfd, newfd, flags); #endif } ssize_t uv__fs_copy_file_range(int fd_in, - ssize_t* off_in, + off_t* off_in, int fd_out, - ssize_t* off_out, + off_t* off_out, size_t len, unsigned int flags) { @@ -247,21 +247,18 @@ int uv__statx(int dirfd, int flags, unsigned int mask, struct uv__statx* statxbuf) { - /* __NR_statx make Android box killed by SIGSYS. - * That looks like a seccomp2 sandbox filter rejecting the system call. - */ -#if defined(__NR_statx) && !defined(__ANDROID__) - return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); -#else +#if !defined(__NR_statx) || defined(__ANDROID_API__) && __ANDROID_API__ < 30 return errno = ENOSYS, -1; +#else + return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); #endif } ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) { -#if defined(__NR_getrandom) - return syscall(__NR_getrandom, buf, buflen, flags); -#else +#if !defined(__NR_getrandom) || defined(__ANDROID_API__) && __ANDROID_API__ < 28 return errno = ENOSYS, -1; +#else + return syscall(__NR_getrandom, buf, buflen, flags); #endif } diff --git a/deps/libuv/src/unix/linux-syscalls.h b/deps/libuv/src/unix/linux-syscalls.h index 761ff32e..b4d9082d 100644 --- a/deps/libuv/src/unix/linux-syscalls.h +++ b/deps/libuv/src/unix/linux-syscalls.h @@ -22,9 +22,6 @@ #ifndef UV_LINUX_SYSCALL_H_ #define UV_LINUX_SYSCALL_H_ -#undef _GNU_SOURCE -#define _GNU_SOURCE - #include #include #include @@ -66,9 +63,9 @@ ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) int uv__dup3(int oldfd, int newfd, int flags); ssize_t uv__fs_copy_file_range(int fd_in, - ssize_t* off_in, + off_t* off_in, int fd_out, - ssize_t* off_out, + off_t* off_out, size_t len, unsigned int flags); int uv__statx(int dirfd, diff --git a/deps/libuv/src/unix/os390-proctitle.c b/deps/libuv/src/unix/os390-proctitle.c new file mode 100644 index 00000000..ccda97c9 --- /dev/null +++ b/deps/libuv/src/unix/os390-proctitle.c @@ -0,0 +1,136 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +static uv_mutex_t process_title_mutex; +static uv_once_t process_title_mutex_once = UV_ONCE_INIT; +static char* process_title = NULL; +static void* args_mem = NULL; + + +static void init_process_title_mutex_once(void) { + uv_mutex_init(&process_title_mutex); +} + + +char** uv_setup_args(int argc, char** argv) { + char** new_argv; + size_t size; + char* s; + int i; + + if (argc <= 0) + return argv; + + /* Calculate how much memory we need for the argv strings. */ + size = 0; + for (i = 0; i < argc; i++) + size += strlen(argv[i]) + 1; + + /* Add space for the argv pointers. */ + size += (argc + 1) * sizeof(char*); + + new_argv = uv__malloc(size); + if (new_argv == NULL) + return argv; + + /* Copy over the strings and set up the pointer table. */ + s = (char*) &new_argv[argc + 1]; + for (i = 0; i < argc; i++) { + size = strlen(argv[i]) + 1; + memcpy(s, argv[i], size); + new_argv[i] = s; + s += size; + } + new_argv[i] = NULL; + + args_mem = new_argv; + process_title = uv__strdup(argv[0]); + + return new_argv; +} + + +int uv_set_process_title(const char* title) { + char* new_title; + + /* If uv_setup_args wasn't called or failed, we can't continue. */ + if (args_mem == NULL) + return UV_ENOBUFS; + + /* We cannot free this pointer when libuv shuts down, + * the process may still be using it. + */ + new_title = uv__strdup(title); + if (new_title == NULL) + return UV_ENOMEM; + + uv_once(&process_title_mutex_once, init_process_title_mutex_once); + uv_mutex_lock(&process_title_mutex); + + if (process_title != NULL) + uv__free(process_title); + + process_title = new_title; + + uv_mutex_unlock(&process_title_mutex); + + return 0; +} + + +int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return UV_EINVAL; + + /* If uv_setup_args wasn't called or failed, we can't continue. */ + if (args_mem == NULL || process_title == NULL) + return UV_ENOBUFS; + + uv_once(&process_title_mutex_once, init_process_title_mutex_once); + uv_mutex_lock(&process_title_mutex); + + len = strlen(process_title); + + if (size <= len) { + uv_mutex_unlock(&process_title_mutex); + return UV_ENOBUFS; + } + + strcpy(buffer, process_title); + + uv_mutex_unlock(&process_title_mutex); + + return 0; +} + + +void uv__process_title_cleanup(void) { + uv__free(args_mem); /* Keep valgrind happy. */ + args_mem = NULL; +} diff --git a/deps/libuv/src/unix/os390-syscalls.c b/deps/libuv/src/unix/os390-syscalls.c index 491e950c..c1915533 100644 --- a/deps/libuv/src/unix/os390-syscalls.c +++ b/deps/libuv/src/unix/os390-syscalls.c @@ -27,12 +27,6 @@ #include #include -#define CW_INTRPT 1 -#define CW_CONDVAR 32 - -#pragma linkage(BPX4CTW, OS) -#pragma linkage(BPX1CTW, OS) - static QUEUE global_epoll_queue; static uv_mutex_t global_epoll_lock; static uv_once_t once = UV_ONCE_INIT; @@ -55,7 +49,7 @@ int scandir(const char* maindir, struct dirent*** namelist, if (!mdir) return -1; - while (1) { + for (;;) { dirent = readdir(mdir); if (!dirent) break; @@ -381,46 +375,6 @@ void epoll_queue_close(uv__os390_epoll* lst) { } -int nanosleep(const struct timespec* req, struct timespec* rem) { - unsigned nano; - unsigned seconds; - unsigned events; - unsigned secrem; - unsigned nanorem; - int rv; - int err; - int rsn; - - nano = (int)req->tv_nsec; - seconds = req->tv_sec; - events = CW_CONDVAR | CW_INTRPT; - secrem = 0; - nanorem = 0; - -#if defined(_LP64) - BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn); -#else - BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn); -#endif - - /* Don't clobber errno unless BPX1CTW/BPX4CTW errored. - * Don't leak EAGAIN, that just means the timeout expired. - */ - if (rv == -1) - if (err == EAGAIN) - rv = 0; - else - errno = err; - - if (rem != NULL && (rv == 0 || err == EINTR)) { - rem->tv_nsec = nanorem; - rem->tv_sec = secrem; - } - - return rv; -} - - char* mkdtemp(char* path) { static const char* tempchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; @@ -550,15 +504,6 @@ ssize_t os390_readlink(const char* path, char* buf, size_t len) { } -size_t strnlen(const char* str, size_t maxlen) { - char* p = memchr(str, 0, maxlen); - if (p == NULL) - return maxlen; - else - return p - str; -} - - int sem_init(UV_PLATFORM_SEM_T* semid, int pshared, unsigned int value) { UNREACHABLE(); } diff --git a/deps/libuv/src/unix/os390-syscalls.h b/deps/libuv/src/unix/os390-syscalls.h index 86416bbc..7d59b75e 100644 --- a/deps/libuv/src/unix/os390-syscalls.h +++ b/deps/libuv/src/unix/os390-syscalls.h @@ -28,6 +28,7 @@ #include #include #include +#include "zos-base.h" #define EPOLL_CTL_ADD 1 #define EPOLL_CTL_DEL 2 @@ -57,7 +58,6 @@ int epoll_wait(uv__os390_epoll* ep, struct epoll_event *events, int maxevents, i int epoll_file_close(int fd); /* utility functions */ -int nanosleep(const struct timespec* req, struct timespec* rem); int scandir(const char* maindir, struct dirent*** namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, diff --git a/deps/libuv/src/unix/os390.c b/deps/libuv/src/unix/os390.c index 3bb44266..bf0448b5 100644 --- a/deps/libuv/src/unix/os390.c +++ b/deps/libuv/src/unix/os390.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include "zos-base.h" #if defined(__clang__) #include "csrsic.h" #else @@ -61,12 +63,6 @@ /* Address of the rsm control and enumeration area. */ #define CVTRCEP_OFFSET 0x490 -/* - Number of frames currently available to system. - Excluded are frames backing perm storage, frames offline, and bad frames. -*/ -#define RCEPOOL_OFFSET 0x004 - /* Total number of frames currently on all available frame queues. */ #define RCEAFC_OFFSET 0x088 @@ -144,102 +140,8 @@ uint64_t uv__hrtime(uv_clocktype_t type) { } -/* - Get the exe path using the thread entry information - in the address space. -*/ -static int getexe(const int pid, char* buf, size_t len) { - struct { - int pid; - int thid[2]; - char accesspid; - char accessthid; - char asid[2]; - char loginname[8]; - char flag; - char len; - } Input_data; - - union { - struct { - char gthb[4]; - int pid; - int thid[2]; - char accesspid; - char accessthid[3]; - int lenused; - int offsetProcess; - int offsetConTTY; - int offsetPath; - int offsetCommand; - int offsetFileData; - int offsetThread; - } Output_data; - char buf[2048]; - } Output_buf; - - struct Output_path_type { - char gthe[4]; - short int len; - char path[1024]; - }; - - int Input_length; - int Output_length; - void* Input_address; - void* Output_address; - struct Output_path_type* Output_path; - int rv; - int rc; - int rsn; - - Input_length = PGTH_LEN; - Output_length = sizeof(Output_buf); - Output_address = &Output_buf; - Input_address = &Input_data; - memset(&Input_data, 0, sizeof Input_data); - Input_data.flag |= PGTHAPATH; - Input_data.pid = pid; - Input_data.accesspid = PGTH_CURRENT; - -#ifdef _LP64 - BPX4GTH(&Input_length, - &Input_address, - &Output_length, - &Output_address, - &rv, - &rc, - &rsn); -#else - BPX1GTH(&Input_length, - &Input_address, - &Output_length, - &Output_address, - &rv, - &rc, - &rsn); -#endif - - if (rv == -1) { - errno = rc; - return -1; - } - - /* Check highest byte to ensure data availability */ - assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A'); - - /* Get the offset from the lowest 3 bytes */ - Output_path = (struct Output_path_type*) ((char*) (&Output_buf) + - (Output_buf.Output_data.offsetPath & 0x00FFFFFF)); - - if (Output_path->len >= len) { - errno = ENOBUFS; - return -1; - } - - uv__strscpy(buf, Output_path->path, len); - - return 0; +static int getexe(char* buf, size_t len) { + return uv__strscpy(buf, __getargv()[0], len); } @@ -259,8 +161,7 @@ int uv_exepath(char* buffer, size_t* size) { if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; - pid = getpid(); - res = getexe(pid, args, sizeof(args)); + res = getexe(args, sizeof(args)); if (res < 0) return UV_EINVAL; @@ -275,25 +176,25 @@ uint64_t uv_get_free_memory(void) { data_area_ptr rcep = {0}; cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); - freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4; + freeram = (uint64_t)*((uint32_t*)(rcep.deref + RCEAFC_OFFSET)) * 4096; return freeram; } uint64_t uv_get_total_memory(void) { - uint64_t totalram; - - data_area_ptr cvt = {0}; - data_area_ptr rcep = {0}; - cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); - rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); - totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4; - return totalram; + /* Use CVTRLSTG to get the size of actual real storage online at IPL in K. */ + return (uint64_t)((int)((char *__ptr32 *__ptr32 *)0)[4][214]) * 1024; } uint64_t uv_get_constrained_memory(void) { - return 0; /* Memory constraints are unknown. */ + struct rlimit rl; + + /* RLIMIT_MEMLIMIT return value is in megabytes rather than bytes. */ + if (getrlimit(RLIMIT_MEMLIMIT, &rl) == 0) + return rl.rlim_cur * 1024 * 1024; + + return 0; /* There is no memory limit set. */ } @@ -733,6 +634,10 @@ static int os390_message_queue_handler(uv__os390_epoll* ep) { /* Some event that we are not interested in. */ return 0; + /* `__rfim_utok` is treated as text when it should be treated as binary while + * running in ASCII mode, resulting in an unwanted autoconversion. + */ + __a2e_l(msg.__rfim_utok, sizeof(msg.__rfim_utok)); handle = *(uv_fs_event_t**)(msg.__rfim_utok); handle->cb(handle, uv__basename_r(handle->path), events, 0); return 1; @@ -959,9 +864,6 @@ update_timeout: } } -void uv__set_process_title(const char* title) { - /* do nothing */ -} int uv__io_fork(uv_loop_t* loop) { /* diff --git a/deps/libuv/src/unix/pipe.c b/deps/libuv/src/unix/pipe.c index 040d5781..788e038e 100644 --- a/deps/libuv/src/unix/pipe.c +++ b/deps/libuv/src/unix/pipe.c @@ -379,3 +379,57 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { return r != -1 ? 0 : UV__ERR(errno); } + + +int uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) { + uv_os_fd_t temp[2]; + int err; +#if defined(__FreeBSD__) || defined(__linux__) + int flags = O_CLOEXEC; + + if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE)) + flags |= UV_FS_O_NONBLOCK; + + if (pipe2(temp, flags)) + return UV__ERR(errno); + + if (flags & UV_FS_O_NONBLOCK) { + fds[0] = temp[0]; + fds[1] = temp[1]; + return 0; + } +#else + if (pipe(temp)) + return UV__ERR(errno); + + if ((err = uv__cloexec(temp[0], 1))) + goto fail; + + if ((err = uv__cloexec(temp[1], 1))) + goto fail; +#endif + + if (read_flags & UV_NONBLOCK_PIPE) + if ((err = uv__nonblock(temp[0], 1))) + goto fail; + + if (write_flags & UV_NONBLOCK_PIPE) + if ((err = uv__nonblock(temp[1], 1))) + goto fail; + + fds[0] = temp[0]; + fds[1] = temp[1]; + return 0; + +fail: + uv__close(temp[0]); + uv__close(temp[1]); + return err; +} + + +int uv__make_pipe(int fds[2], int flags) { + return uv_pipe(fds, + flags & UV_NONBLOCK_PIPE, + flags & UV_NONBLOCK_PIPE); +} diff --git a/deps/libuv/src/unix/poll.c b/deps/libuv/src/unix/poll.c index 3d5022b2..7a12e2d1 100644 --- a/deps/libuv/src/unix/poll.c +++ b/deps/libuv/src/unix/poll.c @@ -79,9 +79,10 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { * Workaround for e.g. kqueue fds not supporting ioctls. */ err = uv__nonblock(fd, 1); +#if UV__NONBLOCK_IS_IOCTL if (err == UV_ENOTTY) - if (uv__nonblock == uv__nonblock_ioctl) - err = uv__nonblock_fcntl(fd, 1); + err = uv__nonblock_fcntl(fd, 1); +#endif if (err) return err; @@ -116,12 +117,21 @@ int uv_poll_stop(uv_poll_t* handle) { int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { + uv__io_t** watchers; + uv__io_t* w; int events; assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT | UV_PRIORITIZED)) == 0); assert(!uv__is_closing(handle)); + watchers = handle->loop->watchers; + w = &handle->io_watcher; + + if (uv__fd_exists(handle->loop, w->fd)) + if (watchers[w->fd] != w) + return UV_EEXIST; + uv__poll_stop(handle); if (pevents == 0) diff --git a/deps/libuv/src/unix/process.c b/deps/libuv/src/unix/process.c index b021aaeb..f4aebb04 100644 --- a/deps/libuv/src/unix/process.c +++ b/deps/libuv/src/unix/process.c @@ -44,6 +44,10 @@ extern char **environ; # include #endif +#if defined(__MVS__) +# include "zos-base.h" +#endif + static void uv__chld(uv_signal_t* handle, int signum) { uv_process_t* process; @@ -111,68 +115,6 @@ static void uv__chld(uv_signal_t* handle, int signum) { assert(QUEUE_EMPTY(&pending)); } - -static int uv__make_socketpair(int fds[2]) { -#if defined(__FreeBSD__) || defined(__linux__) - if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds)) - return UV__ERR(errno); - - return 0; -#else - int err; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) - return UV__ERR(errno); - - err = uv__cloexec(fds[0], 1); - if (err == 0) - err = uv__cloexec(fds[1], 1); - - if (err != 0) { - uv__close(fds[0]); - uv__close(fds[1]); - return UV__ERR(errno); - } - - return 0; -#endif -} - - -int uv__make_pipe(int fds[2], int flags) { -#if defined(__FreeBSD__) || defined(__linux__) - if (pipe2(fds, flags | O_CLOEXEC)) - return UV__ERR(errno); - - return 0; -#else - if (pipe(fds)) - return UV__ERR(errno); - - if (uv__cloexec(fds[0], 1)) - goto fail; - - if (uv__cloexec(fds[1], 1)) - goto fail; - - if (flags & UV__F_NONBLOCK) { - if (uv__nonblock(fds[0], 1)) - goto fail; - - if (uv__nonblock(fds[1], 1)) - goto fail; - } - - return 0; - -fail: - uv__close(fds[0]); - uv__close(fds[1]); - return UV__ERR(errno); -#endif -} - - /* * Used for initializing stdio streams like options.stdin_stream. Returns * zero on success. See also the cleanup section in uv_spawn(). @@ -192,7 +134,7 @@ 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); + return uv_socketpair(SOCK_STREAM, 0, fds, 0, 0); case UV_INHERIT_FD: case UV_INHERIT_STREAM: @@ -259,6 +201,12 @@ static void uv__write_int(int fd, int val) { } +static void uv__write_errno(int error_fd) { + uv__write_int(error_fd, UV__ERR(errno)); + _exit(127); +} + + #if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) /* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be * avoided. Since this isn't called on those targets, the function @@ -287,10 +235,8 @@ static void uv__process_child_init(const uv_process_options_t* options, if (use_fd < 0 || use_fd >= fd) continue; pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count); - if (pipes[fd][1] == -1) { - uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); - } + if (pipes[fd][1] == -1) + uv__write_errno(error_fd); } for (fd = 0; fd < stdio_count; fd++) { @@ -307,10 +253,8 @@ static void uv__process_child_init(const uv_process_options_t* options, use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); close_fd = use_fd; - if (use_fd < 0) { - uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); - } + if (use_fd < 0) + uv__write_errno(error_fd); } } @@ -319,10 +263,8 @@ static void uv__process_child_init(const uv_process_options_t* options, else fd = dup2(use_fd, fd); - if (fd == -1) { - uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); - } + if (fd == -1) + uv__write_errno(error_fd); if (fd <= 2) uv__nonblock_fcntl(fd, 0); @@ -338,10 +280,8 @@ static void uv__process_child_init(const uv_process_options_t* options, uv__close(use_fd); } - if (options->cwd != NULL && chdir(options->cwd)) { - uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); - } + if (options->cwd != NULL && chdir(options->cwd)) + uv__write_errno(error_fd); if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) { /* When dropping privileges from root, the `setgroups` call will @@ -354,15 +294,11 @@ static void uv__process_child_init(const uv_process_options_t* options, SAVE_ERRNO(setgroups(0, NULL)); } - if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) { - uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); - } + if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) + uv__write_errno(error_fd); - if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) { - uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); - } + if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) + uv__write_errno(error_fd); if (options->env != NULL) { environ = options->env; @@ -385,22 +321,23 @@ static void uv__process_child_init(const uv_process_options_t* options, if (SIG_ERR != signal(n, SIG_DFL)) continue; - uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); + uv__write_errno(error_fd); } /* Reset signal mask. */ sigemptyset(&set); err = pthread_sigmask(SIG_SETMASK, &set, NULL); - if (err != 0) { - uv__write_int(error_fd, UV__ERR(err)); - _exit(127); - } + if (err != 0) + uv__write_errno(error_fd); +#ifdef __MVS__ + execvpe(options->file, options->args, environ); +#else execvp(options->file, options->args); - uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); +#endif + + uv__write_errno(error_fd); } #endif diff --git a/deps/libuv/src/unix/proctitle.c b/deps/libuv/src/unix/proctitle.c index 9ffe5b62..9d1f00dd 100644 --- a/deps/libuv/src/unix/proctitle.c +++ b/deps/libuv/src/unix/proctitle.c @@ -84,10 +84,7 @@ char** uv_setup_args(int argc, char** argv) { } new_argv[i] = NULL; - /* argv is not adjacent on z/os, we use just argv[0] on that platform. */ -#ifndef __MVS__ pt.cap = argv[i - 1] + size - argv[0]; -#endif args_mem = new_argv; process_title = pt; @@ -119,6 +116,7 @@ int uv_set_process_title(const char* title) { memcpy(pt->str, title, len); memset(pt->str + len, '\0', pt->cap - len); pt->len = len; + uv__set_process_title(pt->str); uv_mutex_unlock(&process_title_mutex); diff --git a/deps/libuv/src/unix/signal.c b/deps/libuv/src/unix/signal.c index f40a3e54..1133c73a 100644 --- a/deps/libuv/src/unix/signal.c +++ b/deps/libuv/src/unix/signal.c @@ -265,7 +265,7 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) { if (loop->signal_pipefd[0] != -1) return 0; - err = uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK); + err = uv__make_pipe(loop->signal_pipefd, UV_NONBLOCK_PIPE); if (err) return err; diff --git a/deps/libuv/src/unix/stream.c b/deps/libuv/src/unix/stream.c index 8327f9cc..bc64fe8f 100644 --- a/deps/libuv/src/unix/stream.c +++ b/deps/libuv/src/unix/stream.c @@ -164,7 +164,7 @@ static void uv__stream_osx_select(void* arg) { else max_fd = s->int_fd; - while (1) { + for (;;) { /* Terminate on semaphore */ if (uv_sem_trywait(&s->close_sem) == 0) break; @@ -195,7 +195,7 @@ static void uv__stream_osx_select(void* arg) { /* Empty socketpair's buffer in case of interruption */ if (FD_ISSET(s->int_fd, s->sread)) - while (1) { + for (;;) { r = read(s->int_fd, buf, sizeof(buf)); if (r == sizeof(buf)) @@ -799,33 +799,21 @@ static int uv__handle_fd(uv_handle_t* handle) { } } -static void uv__write(uv_stream_t* stream) { +static int uv__try_write(uv_stream_t* stream, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_stream_t* send_handle) { struct iovec* iov; - QUEUE* q; - uv_write_t* req; int iovmax; int iovcnt; ssize_t n; - int err; - -start: - - assert(uv__stream_fd(stream) >= 0); - - if (QUEUE_EMPTY(&stream->write_queue)) - return; - - q = QUEUE_HEAD(&stream->write_queue); - req = QUEUE_DATA(q, uv_write_t, queue); - assert(req->handle == stream); /* * Cast to iovec. We had to have our own uv_buf_t instead of iovec * because Windows's WSABUF is not an iovec. */ - assert(sizeof(uv_buf_t) == sizeof(struct iovec)); - iov = (struct iovec*) &(req->bufs[req->write_index]); - iovcnt = req->nbufs - req->write_index; + iov = (struct iovec*) bufs; + iovcnt = nbufs; iovmax = uv__getiovmax(); @@ -837,8 +825,7 @@ start: * Now do the actual writev. Note that we've been updating the pointers * inside the iov each time we write. So there is no need to offset it. */ - - if (req->send_handle) { + if (send_handle != NULL) { int fd_to_send; struct msghdr msg; struct cmsghdr *cmsg; @@ -847,12 +834,10 @@ start: struct cmsghdr alias; } scratch; - if (uv__is_closing(req->send_handle)) { - err = UV_EBADF; - goto error; - } + if (uv__is_closing(send_handle)) + return UV_EBADF; - fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle); + fd_to_send = uv__handle_fd((uv_handle_t*) send_handle); memset(&scratch, 0, sizeof(scratch)); @@ -882,44 +867,68 @@ start: do n = sendmsg(uv__stream_fd(stream), &msg, 0); while (n == -1 && RETRY_ON_WRITE_ERROR(errno)); - - /* Ensure the handle isn't sent again in case this is a partial write. */ - if (n >= 0) - req->send_handle = NULL; } else { do n = uv__writev(uv__stream_fd(stream), iov, iovcnt); while (n == -1 && RETRY_ON_WRITE_ERROR(errno)); } - if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) { - err = UV__ERR(errno); - goto error; + if (n >= 0) + return n; + + if (IS_TRANSIENT_WRITE_ERROR(errno, send_handle)) + return UV_EAGAIN; + + return UV__ERR(errno); +} + +static void uv__write(uv_stream_t* stream) { + QUEUE* q; + uv_write_t* req; + ssize_t n; + + assert(uv__stream_fd(stream) >= 0); + + for (;;) { + if (QUEUE_EMPTY(&stream->write_queue)) + return; + + q = QUEUE_HEAD(&stream->write_queue); + req = QUEUE_DATA(q, uv_write_t, queue); + assert(req->handle == stream); + + n = uv__try_write(stream, + &(req->bufs[req->write_index]), + req->nbufs - req->write_index, + req->send_handle); + + /* Ensure the handle isn't sent again in case this is a partial write. */ + if (n >= 0) { + req->send_handle = NULL; + if (uv__write_req_update(stream, req, n)) { + uv__write_req_finish(req); + return; /* TODO(bnoordhuis) Start trying to write the next request. */ + } + } else if (n != UV_EAGAIN) + break; + + /* If this is a blocking stream, try again. */ + if (stream->flags & UV_HANDLE_BLOCKING_WRITES) + continue; + + /* We're not done. */ + uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); + + /* Notify select() thread about state change */ + uv__stream_osx_interrupt_select(stream); + + return; } - if (n >= 0 && uv__write_req_update(stream, req, n)) { - uv__write_req_finish(req); - return; /* TODO(bnoordhuis) Start trying to write the next request. */ - } - - /* If this is a blocking stream, try again. */ - if (stream->flags & UV_HANDLE_BLOCKING_WRITES) - goto start; - - /* We're not done. */ - uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); - - /* Notify select() thread about state change */ - uv__stream_osx_interrupt_select(stream); - - return; - -error: - req->error = err; + req->error = n; + // XXX(jwn): this must call uv__stream_flush_write_queue(stream, n) here, since we won't generate any more events uv__write_req_finish(req); uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); - if (!uv__io_active(&stream->io_watcher, POLLIN)) - uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); } @@ -1001,9 +1010,9 @@ uv_handle_type uv__handle_type(int fd) { static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { stream->flags |= UV_HANDLE_READ_EOF; stream->flags &= ~UV_HANDLE_READING; + stream->flags &= ~UV_HANDLE_READABLE; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); - if (!uv__io_active(&stream->io_watcher, POLLOUT)) - uv__handle_stop(stream); + uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); stream->read_cb(stream, UV_EOF, buf); } @@ -1188,12 +1197,12 @@ static void uv__read(uv_stream_t* stream) { #endif } else { /* Error. User should call uv_close(). */ + stream->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); stream->read_cb(stream, UV__ERR(errno), &buf); if (stream->flags & UV_HANDLE_READING) { stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); - if (!uv__io_active(&stream->io_watcher, POLLOUT)) - uv__handle_stop(stream); + uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); } } @@ -1276,6 +1285,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { req->cb = cb; stream->shutdown_req = req; stream->flags |= UV_HANDLE_SHUTTING; + stream->flags &= ~UV_HANDLE_WRITABLE; uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); @@ -1390,14 +1400,9 @@ static void uv__stream_connect(uv_stream_t* stream) { } -int uv_write2(uv_write_t* req, - uv_stream_t* stream, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - int empty_queue; - +static int uv__check_before_write(uv_stream_t* stream, + unsigned int nbufs, + uv_stream_t* send_handle) { assert(nbufs > 0); assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || @@ -1410,7 +1415,7 @@ int uv_write2(uv_write_t* req, if (!(stream->flags & UV_HANDLE_WRITABLE)) return UV_EPIPE; - if (send_handle) { + if (send_handle != NULL) { if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc) return UV_EINVAL; @@ -1430,6 +1435,22 @@ int uv_write2(uv_write_t* req, #endif } + return 0; +} + +int uv_write2(uv_write_t* req, + uv_stream_t* stream, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_stream_t* send_handle, + uv_write_cb cb) { + int empty_queue; + int err; + + err = uv__check_before_write(stream, nbufs, send_handle); + if (err < 0) + return err; + /* It's legal for write_queue_size > 0 even when the write_queue is empty; * it means there are error-state requests in the write_completed_queue that * will touch up write_queue_size later, see also uv__write_req_finish(). @@ -1498,72 +1519,37 @@ int uv_write(uv_write_t* req, } -void uv_try_write_cb(uv_write_t* req, int status) { - /* Should not be called */ - abort(); -} - - int uv_try_write(uv_stream_t* stream, const uv_buf_t bufs[], unsigned int nbufs) { - int r; - int has_pollout; - size_t written; - size_t req_size; - uv_write_t req; + return uv_try_write2(stream, bufs, nbufs, NULL); +} + + +int uv_try_write2(uv_stream_t* stream, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_stream_t* send_handle) { + int err; /* Connecting or already writing some data */ if (stream->connect_req != NULL || stream->write_queue_size != 0) return UV_EAGAIN; - has_pollout = uv__io_active(&stream->io_watcher, POLLOUT); + err = uv__check_before_write(stream, nbufs, NULL); + if (err < 0) + return err; - r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb); - if (r != 0) - return r; - - /* Remove not written bytes from write queue size */ - written = uv__count_bufs(bufs, nbufs); - if (req.bufs != NULL) - req_size = uv__write_req_size(&req); - else - req_size = 0; - written -= req_size; - stream->write_queue_size -= req_size; - - /* Unqueue request, regardless of immediateness */ - QUEUE_REMOVE(&req.queue); - uv__req_unregister(stream->loop, &req); - if (req.bufs != req.bufsml) - uv__free(req.bufs); - req.bufs = NULL; - - /* Do not poll for writable, if we wasn't before calling this */ - if (!has_pollout) { - uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); - uv__stream_osx_interrupt_select(stream); - } - - if (written == 0 && req_size != 0) - return req.error < 0 ? req.error : UV_EAGAIN; - else - return written; + return uv__try_write(stream, bufs, nbufs, send_handle); } -int uv_read_start(uv_stream_t* stream, - uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { +int uv__read_start(uv_stream_t* stream, + uv_alloc_cb alloc_cb, + uv_read_cb read_cb) { assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY); - if (stream->flags & UV_HANDLE_CLOSING) - return UV_EINVAL; - - if (!(stream->flags & UV_HANDLE_READABLE)) - return UV_ENOTCONN; - /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just * expresses the desired state of the user. */ @@ -1593,8 +1579,7 @@ int uv_read_stop(uv_stream_t* stream) { stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); - if (!uv__io_active(&stream->io_watcher, POLLOUT)) - uv__handle_stop(stream); + uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); stream->read_cb = NULL; diff --git a/deps/libuv/src/unix/sunos.c b/deps/libuv/src/unix/sunos.c index d511c18b..2bf297e5 100644 --- a/deps/libuv/src/unix/sunos.c +++ b/deps/libuv/src/unix/sunos.c @@ -865,3 +865,14 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses, uv__free(addresses); } + + +#if !defined(_POSIX_VERSION) || _POSIX_VERSION < 200809L +size_t strnlen(const char* s, size_t maxlen) { + const char* end; + end = memchr(s, '\0', maxlen); + if (end == NULL) + return maxlen; + return end - s; +} +#endif diff --git a/deps/libuv/src/unix/tcp.c b/deps/libuv/src/unix/tcp.c index 18acd20d..bc0fb661 100644 --- a/deps/libuv/src/unix/tcp.c +++ b/deps/libuv/src/unix/tcp.c @@ -214,14 +214,15 @@ int uv__tcp_connect(uv_connect_t* req, if (handle->connect_req != NULL) return UV_EALREADY; /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */ + if (handle->delayed_error != 0) + goto out; + err = maybe_new_socket(handle, addr->sa_family, UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); if (err) return err; - handle->delayed_error = 0; - do { errno = 0; r = connect(uv__stream_fd(handle), addr, addrlen); @@ -249,6 +250,8 @@ int uv__tcp_connect(uv_connect_t* req, return UV__ERR(errno); } +out: + uv__req_init(handle->loop, req, UV_CONNECT); req->cb = cb; req->handle = (uv_stream_t*) handle; @@ -459,3 +462,49 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { void uv__tcp_close(uv_tcp_t* handle) { uv__stream_close((uv_stream_t*)handle); } + + +int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) { + uv_os_sock_t temp[2]; + int err; +#if defined(__FreeBSD__) || defined(__linux__) + int flags; + + flags = type | SOCK_CLOEXEC; + if ((flags0 & UV_NONBLOCK_PIPE) && (flags1 & UV_NONBLOCK_PIPE)) + flags |= SOCK_NONBLOCK; + + if (socketpair(AF_UNIX, flags, protocol, temp)) + return UV__ERR(errno); + + if (flags & UV_FS_O_NONBLOCK) { + fds[0] = temp[0]; + fds[1] = temp[1]; + return 0; + } +#else + if (socketpair(AF_UNIX, type, protocol, temp)) + return UV__ERR(errno); + + if ((err = uv__cloexec(temp[0], 1))) + goto fail; + if ((err = uv__cloexec(temp[1], 1))) + goto fail; +#endif + + if (flags0 & UV_NONBLOCK_PIPE) + if ((err = uv__nonblock(temp[0], 1))) + goto fail; + if (flags1 & UV_NONBLOCK_PIPE) + if ((err = uv__nonblock(temp[1], 1))) + goto fail; + + fds[0] = temp[0]; + fds[1] = temp[1]; + return 0; + +fail: + uv__close(temp[0]); + uv__close(temp[1]); + return err; +} diff --git a/deps/libuv/src/unix/thread.c b/deps/libuv/src/unix/thread.c index 1a85d1d4..c46450cc 100644 --- a/deps/libuv/src/unix/thread.c +++ b/deps/libuv/src/unix/thread.c @@ -107,8 +107,7 @@ int uv_barrier_wait(uv_barrier_t* barrier) { } last = (--b->out == 0); - if (!last) - uv_cond_signal(&b->cond); /* Not needed for last thread. */ + uv_cond_signal(&b->cond); uv_mutex_unlock(&b->mutex); return last; @@ -122,9 +121,10 @@ void uv_barrier_destroy(uv_barrier_t* barrier) { uv_mutex_lock(&b->mutex); assert(b->in == 0); - assert(b->out == 0); + while (b->out != 0) + uv_cond_wait(&b->cond, &b->mutex); - if (b->in != 0 || b->out != 0) + if (b->in != 0) abort(); uv_mutex_unlock(&b->mutex); @@ -168,7 +168,7 @@ void uv_barrier_destroy(uv_barrier_t* barrier) { * On Linux, threads created by musl have a much smaller stack than threads * created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency. */ -static size_t thread_stack_size(void) { +size_t uv__thread_stack_size(void) { #if defined(__APPLE__) || defined(__linux__) struct rlimit lim; @@ -234,7 +234,7 @@ int uv_thread_create_ex(uv_thread_t* tid, attr = NULL; if (stack_size == 0) { - stack_size = thread_stack_size(); + stack_size = uv__thread_stack_size(); } else { pagesize = (size_t)getpagesize(); /* Round up to the nearest page boundary. */ diff --git a/deps/libuv/src/unix/tty.c b/deps/libuv/src/unix/tty.c index 6f60abaa..9442cf16 100644 --- a/deps/libuv/src/unix/tty.c +++ b/deps/libuv/src/unix/tty.c @@ -242,6 +242,24 @@ static void uv__tty_make_raw(struct termios* tio) { tio->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); tio->c_cflag &= ~(CSIZE | PARENB); tio->c_cflag |= CS8; + + /* + * By default, most software expects a pending read to block until at + * least one byte becomes available. As per termio(7I), this requires + * setting the MIN and TIME parameters appropriately. + * + * As a somewhat unfortunate artifact of history, the MIN and TIME slots + * in the control character array overlap with the EOF and EOL slots used + * for canonical mode processing. Because the EOF character needs to be + * the ASCII EOT value (aka Control-D), it has the byte value 4. When + * switching to raw mode, this is interpreted as a MIN value of 4; i.e., + * reads will block until at least four bytes have been input. + * + * Other platforms with a distinct MIN slot like Linux and FreeBSD appear + * to default to a MIN value of 1, so we'll force that value here: + */ + tio->c_cc[VMIN] = 1; + tio->c_cc[VTIME] = 0; #else cfmakeraw(tio); #endif /* #ifdef __sun */ diff --git a/deps/libuv/src/unix/udp.c b/deps/libuv/src/unix/udp.c index 7d699a16..49051c07 100644 --- a/deps/libuv/src/unix/udp.c +++ b/deps/libuv/src/unix/udp.c @@ -32,8 +32,6 @@ #endif #include -#define UV__UDP_DGRAM_MAXSIZE (64 * 1024) - #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP #endif @@ -504,6 +502,28 @@ static int uv__set_reuse(int fd) { return 0; } +/* + * The Linux kernel suppresses some ICMP error messages by default for UDP + * sockets. Setting IP_RECVERR/IPV6_RECVERR on the socket enables full ICMP + * error reporting, hopefully resulting in faster failover to working name + * servers. + */ +static int uv__set_recverr(int fd, sa_family_t ss_family) { +#if defined(__linux__) + int yes; + + yes = 1; + if (ss_family == AF_INET) { + if (setsockopt(fd, IPPROTO_IP, IP_RECVERR, &yes, sizeof(yes))) + return UV__ERR(errno); + } else if (ss_family == AF_INET6) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVERR, &yes, sizeof(yes))) + return UV__ERR(errno); + } +#endif + return 0; +} + int uv__udp_bind(uv_udp_t* handle, const struct sockaddr* addr, @@ -514,7 +534,7 @@ int uv__udp_bind(uv_udp_t* handle, int fd; /* Check for bad flags. */ - if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR)) + if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR | UV_UDP_LINUX_RECVERR)) return UV_EINVAL; /* Cannot set IPv6-only mode on non-IPv6 socket. */ @@ -530,6 +550,12 @@ int uv__udp_bind(uv_udp_t* handle, handle->io_watcher.fd = fd; } + if (flags & UV_UDP_LINUX_RECVERR) { + err = uv__set_recverr(fd, addr->sa_family); + if (err) + return err; + } + if (flags & UV_UDP_REUSEADDR) { err = uv__set_reuse(fd); if (err) diff --git a/deps/libuv/src/uv-common.c b/deps/libuv/src/uv-common.c index 602e5f49..e81ed79b 100644 --- a/deps/libuv/src/uv-common.c +++ b/deps/libuv/src/uv-common.c @@ -832,6 +832,25 @@ void uv_loop_delete(uv_loop_t* loop) { } +int uv_read_start(uv_stream_t* stream, + uv_alloc_cb alloc_cb, + uv_read_cb read_cb) { + if (stream == NULL || alloc_cb == NULL || read_cb == NULL) + return UV_EINVAL; + + if (stream->flags & UV_HANDLE_CLOSING) + return UV_EINVAL; + + if (stream->flags & UV_HANDLE_READING) + return UV_EALREADY; + + if (!(stream->flags & UV_HANDLE_READABLE)) + return UV_ENOTCONN; + + return uv__read_start(stream, alloc_cb, read_cb); +} + + void uv_os_free_environ(uv_env_item_t* envitems, int count) { int i; @@ -853,7 +872,11 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { } -#ifdef __GNUC__ /* Also covers __clang__ and __INTEL_COMPILER. */ +/* Also covers __clang__ and __INTEL_COMPILER. Disabled on Windows because + * threads have already been forcibly terminated by the operating system + * by the time destructors run, ergo, it's not safe to try to clean them up. + */ +#if defined(__GNUC__) && !defined(_WIN32) __attribute__((destructor)) #endif void uv_library_shutdown(void) { diff --git a/deps/libuv/src/uv-common.h b/deps/libuv/src/uv-common.h index e851291c..8a190bf8 100644 --- a/deps/libuv/src/uv-common.h +++ b/deps/libuv/src/uv-common.h @@ -68,6 +68,8 @@ extern int snprintf(char*, size_t, const char*, ...); #define uv__store_relaxed(p, v) do *p = v; while (0) #endif +#define UV__UDP_DGRAM_MAXSIZE (64 * 1024) + /* Handle flags. Some flags are specific to Windows or UNIX. */ enum { /* Used by all handles. */ @@ -106,8 +108,7 @@ enum { UV_HANDLE_TCP_KEEPALIVE = 0x02000000, UV_HANDLE_TCP_SINGLE_ACCEPT = 0x04000000, UV_HANDLE_TCP_ACCEPT_STATE_CHANGING = 0x08000000, - UV_HANDLE_TCP_SOCKET_CLOSED = 0x10000000, - UV_HANDLE_SHARED_TCP_SOCKET = 0x20000000, + UV_HANDLE_SHARED_TCP_SOCKET = 0x10000000, /* Only used by uv_udp_t handles. */ UV_HANDLE_UDP_PROCESSING = 0x01000000, @@ -136,6 +137,10 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); void uv__loop_close(uv_loop_t* loop); +int uv__read_start(uv_stream_t* stream, + uv_alloc_cb alloc_cb, + uv_read_cb read_cb); + int uv__tcp_bind(uv_tcp_t* tcp, const struct sockaddr* addr, unsigned int addrlen, diff --git a/deps/libuv/src/win/atomicops-inl.h b/deps/libuv/src/win/atomicops-inl.h index 52713cf3..2f984c6d 100644 --- a/deps/libuv/src/win/atomicops-inl.h +++ b/deps/libuv/src/win/atomicops-inl.h @@ -39,10 +39,11 @@ static char INLINE uv__atomic_exchange_set(char volatile* target) { return _InterlockedOr8(target, 1); } -#else /* GCC */ +#else /* GCC, Clang in mingw mode */ -/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */ static inline char uv__atomic_exchange_set(char volatile* target) { +#if defined(__i386__) || defined(__x86_64__) + /* Mingw-32 version, hopefully this works for 64-bit gcc as well. */ const char one = 1; char old_value; __asm__ __volatile__ ("lock xchgb %0, %1\n\t" @@ -50,6 +51,9 @@ static inline char uv__atomic_exchange_set(char volatile* target) { : "0"(one), "m"(*target) : "memory"); return old_value; +#else + return __sync_fetch_and_or(target, 1); +#endif } #endif diff --git a/deps/libuv/src/win/error.c b/deps/libuv/src/win/error.c index 3ec984c8..3a269da8 100644 --- a/deps/libuv/src/win/error.c +++ b/deps/libuv/src/win/error.c @@ -105,7 +105,6 @@ int uv_translate_sys_error(int sys_errno) { case ERROR_SYMLINK_NOT_SUPPORTED: return UV_EINVAL; case WSAEINVAL: return UV_EINVAL; case WSAEPFNOSUPPORT: return UV_EINVAL; - case WSAESOCKTNOSUPPORT: return UV_EINVAL; case ERROR_BEGINNING_OF_MEDIA: return UV_EIO; case ERROR_BUS_RESET: return UV_EIO; case ERROR_CRC: return UV_EIO; @@ -168,6 +167,7 @@ int uv_translate_sys_error(int sys_errno) { case ERROR_NOT_SAME_DEVICE: return UV_EXDEV; case ERROR_INVALID_FUNCTION: return UV_EISDIR; case ERROR_META_EXPANSION_TOO_LONG: return UV_E2BIG; + case WSAESOCKTNOSUPPORT: return UV_ESOCKTNOSUPPORT; default: return UV_UNKNOWN; } } diff --git a/deps/libuv/src/win/fs.c b/deps/libuv/src/win/fs.c index 8a801749..67407040 100644 --- a/deps/libuv/src/win/fs.c +++ b/deps/libuv/src/win/fs.c @@ -92,30 +92,24 @@ return; \ } -#define MILLIONu (1000U * 1000U) -#define BILLIONu (1000U * 1000U * 1000U) +#define MILLION ((int64_t) 1000 * 1000) +#define BILLION ((int64_t) 1000 * 1000 * 1000) -#define FILETIME_TO_UINT(filetime) \ - (*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu) - -#define FILETIME_TO_TIME_T(filetime) \ - (FILETIME_TO_UINT(filetime) / (10u * MILLIONu)) - -#define FILETIME_TO_TIME_NS(filetime, secs) \ - ((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U) - -#define FILETIME_TO_TIMESPEC(ts, filetime) \ - do { \ - (ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime); \ - (ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec); \ - } while(0) +static void uv__filetime_to_timespec(uv_timespec_t *ts, int64_t filetime) { + filetime -= 116444736 * BILLION; + ts->tv_sec = (long) (filetime / (10 * MILLION)); + ts->tv_nsec = (long) ((filetime - ts->tv_sec * 10 * MILLION) * 100U); + if (ts->tv_nsec < 0) { + ts->tv_sec -= 1; + ts->tv_nsec += 1e9; + } +} #define TIME_T_TO_FILETIME(time, filetime_ptr) \ do { \ - uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) + \ - (uint64_t) 116444736 * BILLIONu; \ - (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \ - (filetime_ptr)->dwHighDateTime = bigtime >> 32; \ + int64_t bigtime = ((time) * 10 * MILLION + 116444736 * BILLION); \ + (filetime_ptr)->dwLowDateTime = (uint64_t) bigtime & 0xFFFFFFFF; \ + (filetime_ptr)->dwHighDateTime = (uint64_t) bigtime >> 32; \ } while(0) #define IS_SLASH(c) ((c) == L'\\' || (c) == L'/') @@ -1224,7 +1218,8 @@ void fs__mkdir(uv_fs_t* req) { SET_REQ_RESULT(req, 0); } else { SET_REQ_WIN32_ERROR(req, GetLastError()); - if (req->sys_errno_ == ERROR_INVALID_NAME) + if (req->sys_errno_ == ERROR_INVALID_NAME || + req->sys_errno_ == ERROR_DIRECTORY) req->result = UV_EINVAL; } } @@ -1243,7 +1238,7 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) { uint64_t v; char* path; - path = req->path; + path = (char*)req->path; len = wcslen(req->file.pathw); ep = req->file.pathw + len; if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) { @@ -1791,10 +1786,14 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf, statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) | ((_S_IREAD | _S_IWRITE) >> 6); - FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime); - FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime); - FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime); - FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime); + uv__filetime_to_timespec(&statbuf->st_atim, + file_info.BasicInformation.LastAccessTime.QuadPart); + uv__filetime_to_timespec(&statbuf->st_ctim, + file_info.BasicInformation.ChangeTime.QuadPart); + uv__filetime_to_timespec(&statbuf->st_mtim, + file_info.BasicInformation.LastWriteTime.QuadPart); + uv__filetime_to_timespec(&statbuf->st_birthtim, + file_info.BasicInformation.CreationTime.QuadPart); statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart; diff --git a/deps/libuv/src/win/internal.h b/deps/libuv/src/win/internal.h index b096255e..b1b25b4c 100644 --- a/deps/libuv/src/win/internal.h +++ b/deps/libuv/src/win/internal.h @@ -115,8 +115,8 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle); /* * Pipes */ -int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, - char* name, size_t nameSize); +int uv__create_stdio_pipe_pair(uv_loop_t* loop, + uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags); int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client); diff --git a/deps/libuv/src/win/pipe.c b/deps/libuv/src/win/pipe.c index f81245ec..88ba99bb 100644 --- a/deps/libuv/src/win/pipe.c +++ b/deps/libuv/src/win/pipe.c @@ -202,17 +202,17 @@ static void close_pipe(uv_pipe_t* pipe) { } -int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, - char* name, size_t nameSize) { +static int uv__pipe_server( + HANDLE* pipeHandle_ptr, DWORD access, + char* name, size_t nameSize, char* random) { HANDLE pipeHandle; int err; - char* ptr = (char*)handle; for (;;) { - uv_unique_pipe_name(ptr, name, nameSize); + uv_unique_pipe_name(random, name, nameSize); pipeHandle = CreateNamedPipeA(name, - access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC, + access | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0, NULL); @@ -226,20 +226,11 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, goto error; } - /* Pipe name collision. Increment the pointer and try again. */ - ptr++; + /* Pipe name collision. Increment the random number and try again. */ + random++; } - if (CreateIoCompletionPort(pipeHandle, - loop->iocp, - (ULONG_PTR)handle, - 0) == NULL) { - err = GetLastError(); - goto error; - } - - uv_pipe_connection_init(handle); - handle->handle = pipeHandle; + *pipeHandle_ptr = pipeHandle; return 0; @@ -251,6 +242,214 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, } +static int uv__create_pipe_pair( + HANDLE* server_pipe_ptr, HANDLE* client_pipe_ptr, + unsigned int server_flags, unsigned int client_flags, + int inherit_client, char* random) { + /* allowed flags are: UV_READABLE_PIPE | UV_WRITABLE_PIPE | UV_NONBLOCK_PIPE */ + char pipe_name[64]; + SECURITY_ATTRIBUTES sa; + DWORD server_access; + DWORD client_access; + HANDLE server_pipe; + HANDLE client_pipe; + int err; + + server_pipe = INVALID_HANDLE_VALUE; + client_pipe = INVALID_HANDLE_VALUE; + + server_access = 0; + if (server_flags & UV_READABLE_PIPE) + server_access |= PIPE_ACCESS_INBOUND; + if (server_flags & UV_WRITABLE_PIPE) + server_access |= PIPE_ACCESS_OUTBOUND; + if (server_flags & UV_NONBLOCK_PIPE) + server_access |= FILE_FLAG_OVERLAPPED; + server_access |= WRITE_DAC; + + client_access = 0; + if (client_flags & UV_READABLE_PIPE) + client_access |= GENERIC_READ; + else + client_access |= FILE_READ_ATTRIBUTES; + if (client_flags & UV_WRITABLE_PIPE) + client_access |= GENERIC_WRITE; + else + client_access |= FILE_WRITE_ATTRIBUTES; + client_access |= WRITE_DAC; + + /* Create server pipe handle. */ + err = uv__pipe_server(&server_pipe, + server_access, + pipe_name, + sizeof(pipe_name), + random); + if (err) + goto error; + + /* Create client pipe handle. */ + sa.nLength = sizeof sa; + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = inherit_client; + + client_pipe = CreateFileA(pipe_name, + client_access, + 0, + &sa, + OPEN_EXISTING, + (client_flags & UV_NONBLOCK_PIPE) ? FILE_FLAG_OVERLAPPED : 0, + NULL); + if (client_pipe == INVALID_HANDLE_VALUE) { + err = GetLastError(); + goto error; + } + +#ifndef NDEBUG + /* Validate that the pipe was opened in the right mode. */ + { + DWORD mode; + BOOL r; + r = GetNamedPipeHandleState(client_pipe, &mode, NULL, NULL, NULL, NULL, 0); + if (r == TRUE) { + assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT)); + } else { + fprintf(stderr, "libuv assertion failure: GetNamedPipeHandleState failed\n"); + } + } +#endif + + /* Do a blocking ConnectNamedPipe. This should not block because we have + * both ends of the pipe created. */ + if (!ConnectNamedPipe(server_pipe, NULL)) { + if (GetLastError() != ERROR_PIPE_CONNECTED) { + err = GetLastError(); + goto error; + } + } + + *client_pipe_ptr = client_pipe; + *server_pipe_ptr = server_pipe; + return 0; + + error: + if (server_pipe != INVALID_HANDLE_VALUE) + CloseHandle(server_pipe); + + if (client_pipe != INVALID_HANDLE_VALUE) + CloseHandle(client_pipe); + + return err; +} + + +int uv_pipe(uv_file fds[2], int read_flags, int write_flags) { + uv_file temp[2]; + int err; + HANDLE readh; + HANDLE writeh; + + /* Make the server side the inbound (read) end, */ + /* so that both ends will have FILE_READ_ATTRIBUTES permission. */ + /* TODO: better source of local randomness than &fds? */ + read_flags |= UV_READABLE_PIPE; + write_flags |= UV_WRITABLE_PIPE; + err = uv__create_pipe_pair(&readh, &writeh, read_flags, write_flags, 0, (char*) &fds[0]); + if (err != 0) + return err; + temp[0] = _open_osfhandle((intptr_t) readh, 0); + if (temp[0] == -1) { + if (errno == UV_EMFILE) + err = UV_EMFILE; + else + err = UV_UNKNOWN; + CloseHandle(readh); + CloseHandle(writeh); + return err; + } + temp[1] = _open_osfhandle((intptr_t) writeh, 0); + if (temp[1] == -1) { + if (errno == UV_EMFILE) + err = UV_EMFILE; + else + err = UV_UNKNOWN; + _close(temp[0]); + CloseHandle(writeh); + return err; + } + fds[0] = temp[0]; + fds[1] = temp[1]; + return 0; +} + + +int uv__create_stdio_pipe_pair(uv_loop_t* loop, + uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags) { + /* The parent_pipe is always the server_pipe and kept by libuv. + * The child_pipe is always the client_pipe and is passed to the child. + * The flags are specified with respect to their usage in the child. */ + HANDLE server_pipe; + HANDLE client_pipe; + unsigned int server_flags; + unsigned int client_flags; + int err; + + server_pipe = INVALID_HANDLE_VALUE; + client_pipe = INVALID_HANDLE_VALUE; + + server_flags = 0; + client_flags = 0; + if (flags & UV_READABLE_PIPE) { + /* The server needs inbound (read) access too, otherwise CreateNamedPipe() + * won't give us the FILE_READ_ATTRIBUTES permission. We need that to probe + * the state of the write buffer when we're trying to shutdown the pipe. */ + server_flags |= UV_READABLE_PIPE | UV_WRITABLE_PIPE; + client_flags |= UV_READABLE_PIPE; + } + if (flags & UV_WRITABLE_PIPE) { + server_flags |= UV_READABLE_PIPE; + client_flags |= UV_WRITABLE_PIPE; + } + server_flags |= UV_NONBLOCK_PIPE; + if (flags & UV_NONBLOCK_PIPE || parent_pipe->ipc) { + client_flags |= UV_NONBLOCK_PIPE; + } + + err = uv__create_pipe_pair(&server_pipe, &client_pipe, + server_flags, client_flags, 1, (char*) server_pipe); + if (err) + goto error; + + if (CreateIoCompletionPort(server_pipe, + loop->iocp, + (ULONG_PTR) parent_pipe, + 0) == NULL) { + err = GetLastError(); + goto error; + } + + uv_pipe_connection_init(parent_pipe); + parent_pipe->handle = server_pipe; + *child_pipe_ptr = client_pipe; + + /* The server end is now readable and/or writable. */ + if (flags & UV_READABLE_PIPE) + parent_pipe->flags |= UV_HANDLE_WRITABLE; + if (flags & UV_WRITABLE_PIPE) + parent_pipe->flags |= UV_HANDLE_READABLE; + + return 0; + + error: + if (server_pipe != INVALID_HANDLE_VALUE) + CloseHandle(server_pipe); + + if (client_pipe != INVALID_HANDLE_VALUE) + CloseHandle(client_pipe); + + return err; +} + + static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle, HANDLE pipeHandle, @@ -712,9 +911,8 @@ error: handle->name = NULL; } - if (pipeHandle != INVALID_HANDLE_VALUE) { + if (pipeHandle != INVALID_HANDLE_VALUE) CloseHandle(pipeHandle); - } /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, err); diff --git a/deps/libuv/src/win/poll.c b/deps/libuv/src/win/poll.c index 87858590..9d377596 100644 --- a/deps/libuv/src/win/poll.c +++ b/deps/libuv/src/win/poll.c @@ -488,7 +488,8 @@ static int uv__poll_set(uv_poll_t* handle, int events, uv_poll_cb cb) { assert(handle->type == UV_POLL); assert(!(handle->flags & UV_HANDLE_CLOSING)); - assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); + assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT | + UV_PRIORITIZED)) == 0); handle->events = events; handle->poll_cb = cb; diff --git a/deps/libuv/src/win/process-stdio.c b/deps/libuv/src/win/process-stdio.c index 355d6188..0db35723 100644 --- a/deps/libuv/src/win/process-stdio.c +++ b/deps/libuv/src/win/process-stdio.c @@ -95,102 +95,6 @@ void uv_disable_stdio_inheritance(void) { } -static int uv__create_stdio_pipe_pair(uv_loop_t* loop, - uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) { - char pipe_name[64]; - SECURITY_ATTRIBUTES sa; - DWORD server_access = 0; - DWORD client_access = 0; - HANDLE child_pipe = INVALID_HANDLE_VALUE; - int err; - int overlap; - - if (flags & UV_READABLE_PIPE) { - /* The server needs inbound access too, otherwise CreateNamedPipe() won't - * give us the FILE_READ_ATTRIBUTES permission. We need that to probe the - * state of the write buffer when we're trying to shutdown the pipe. */ - server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND; - client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES; - } - if (flags & UV_WRITABLE_PIPE) { - server_access |= PIPE_ACCESS_INBOUND; - client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES; - } - - /* Create server pipe handle. */ - err = uv_stdio_pipe_server(loop, - server_pipe, - server_access, - pipe_name, - sizeof(pipe_name)); - if (err) - goto error; - - /* Create child pipe handle. */ - sa.nLength = sizeof sa; - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE); - child_pipe = CreateFileA(pipe_name, - client_access, - 0, - &sa, - OPEN_EXISTING, - overlap ? FILE_FLAG_OVERLAPPED : 0, - NULL); - if (child_pipe == INVALID_HANDLE_VALUE) { - err = GetLastError(); - goto error; - } - -#ifndef NDEBUG - /* Validate that the pipe was opened in the right mode. */ - { - DWORD mode; - BOOL r = GetNamedPipeHandleState(child_pipe, - &mode, - NULL, - NULL, - NULL, - NULL, - 0); - assert(r == TRUE); - assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT)); - } -#endif - - /* Do a blocking ConnectNamedPipe. This should not block because we have both - * ends of the pipe created. */ - if (!ConnectNamedPipe(server_pipe->handle, NULL)) { - if (GetLastError() != ERROR_PIPE_CONNECTED) { - err = GetLastError(); - goto error; - } - } - - /* The server end is now readable and/or writable. */ - if (flags & UV_READABLE_PIPE) - server_pipe->flags |= UV_HANDLE_WRITABLE; - if (flags & UV_WRITABLE_PIPE) - server_pipe->flags |= UV_HANDLE_READABLE; - - *child_pipe_ptr = child_pipe; - return 0; - - error: - if (server_pipe->handle != INVALID_HANDLE_VALUE) { - uv_pipe_cleanup(loop, server_pipe); - } - - if (child_pipe != INVALID_HANDLE_VALUE) { - CloseHandle(child_pipe); - } - - return err; -} - - static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) { HANDLE current_process; diff --git a/deps/libuv/src/win/process.c b/deps/libuv/src/win/process.c index 73543c6e..4038fbfd 100644 --- a/deps/libuv/src/win/process.c +++ b/deps/libuv/src/win/process.c @@ -642,7 +642,7 @@ int env_strncmp(const wchar_t* a, int na, const wchar_t* b) { assert(r==nb); B[nb] = L'\0'; - while (1) { + for (;;) { wchar_t AA = *A++; wchar_t BB = *B++; if (AA < BB) { diff --git a/deps/libuv/src/win/stream.c b/deps/libuv/src/win/stream.c index 46a0709a..abf477f6 100644 --- a/deps/libuv/src/win/stream.c +++ b/deps/libuv/src/win/stream.c @@ -65,18 +65,11 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { } -int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { +int uv__read_start(uv_stream_t* handle, + uv_alloc_cb alloc_cb, + uv_read_cb read_cb) { int err; - if (handle->flags & UV_HANDLE_READING) { - return UV_EALREADY; - } - - if (!(handle->flags & UV_HANDLE_READABLE)) { - return UV_ENOTCONN; - } - err = ERROR_INVALID_PARAMETER; switch (handle->type) { case UV_TCP: @@ -195,6 +188,16 @@ int uv_try_write(uv_stream_t* stream, } +int uv_try_write2(uv_stream_t* stream, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_stream_t* send_handle) { + if (send_handle != NULL) + return UV_EAGAIN; + return uv_try_write(stream, bufs, nbufs); +} + + int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { uv_loop_t* loop = handle->loop; diff --git a/deps/libuv/src/win/tcp.c b/deps/libuv/src/win/tcp.c index 0dcaa97d..cf2dbd85 100644 --- a/deps/libuv/src/win/tcp.c +++ b/deps/libuv/src/win/tcp.c @@ -236,12 +236,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); - - if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) { - closesocket(handle->socket); - handle->socket = INVALID_SOCKET; - handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; - } + assert(handle->socket == INVALID_SOCKET); if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) { if (handle->flags & UV_HANDLE_EMULATE_IOCP) { @@ -599,6 +594,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { } } + /* If this flag is set, we already made this listen call in xfer. */ if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) && listen(handle->socket, backlog) == SOCKET_ERROR) { return WSAGetLastError(); @@ -769,7 +765,7 @@ static int uv__is_loopback(const struct sockaddr_storage* storage) { } // Check if Windows version is 10.0.16299 or later -static int uv__is_fast_loopback_fail_supported() { +static int uv__is_fast_loopback_fail_supported(void) { OSVERSIONINFOW os_info; if (!pRtlGetVersion) return 0; @@ -800,9 +796,8 @@ static int uv_tcp_try_connect(uv_connect_t* req, if (err) return err; - if (handle->delayed_error) { - return handle->delayed_error; - } + if (handle->delayed_error != 0) + goto out; if (!(handle->flags & UV_HANDLE_BOUND)) { if (addrlen == sizeof(uv_addr_ip4_any_)) { @@ -815,8 +810,8 @@ static int uv_tcp_try_connect(uv_connect_t* req, err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0); if (err) return err; - if (handle->delayed_error) - return handle->delayed_error; + if (handle->delayed_error != 0) + goto out; } if (!handle->tcp.conn.func_connectex) { @@ -844,11 +839,21 @@ static int uv_tcp_try_connect(uv_connect_t* req, NULL); } +out: + UV_REQ_INIT(req, UV_CONNECT); req->handle = (uv_stream_t*) handle; req->cb = cb; memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); + if (handle->delayed_error != 0) { + /* Process the req without IOCP. */ + handle->reqs_pending++; + REGISTER_HANDLE_REQ(loop, handle, req); + uv_insert_pending_req(loop, (uv_req_t*)req); + return 0; + } + success = handle->tcp.conn.func_connectex(handle->socket, (const struct sockaddr*) &converted, addrlen, @@ -1015,6 +1020,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, */ err = WSAECONNRESET; } + handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); handle->read_cb((uv_stream_t*)handle, uv_translate_sys_error(err), @@ -1096,6 +1102,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, * Unix. */ err = WSAECONNRESET; } + handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); handle->read_cb((uv_stream_t*)handle, uv_translate_sys_error(err), @@ -1149,9 +1156,14 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, } handle->stream.conn.write_reqs_pending--; - if (handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); + if (handle->stream.conn.write_reqs_pending == 0) { + if (handle->flags & UV_HANDLE_CLOSING) { + closesocket(handle->socket); + handle->socket = INVALID_SOCKET; + } + if (handle->stream.conn.shutdown_req != NULL) { + uv_want_endgame(loop, (uv_handle_t*)handle); + } } DECREASE_PENDING_REQ_COUNT(handle); @@ -1215,7 +1227,14 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, UNREGISTER_HANDLE_REQ(loop, handle, req); err = 0; - if (REQ_SUCCESS(req)) { + if (handle->delayed_error) { + /* To smooth over the differences between unixes errors that + * were reported synchronously on the first connect can be delayed + * until the next tick--which is now. + */ + err = handle->delayed_error; + handle->delayed_error = 0; + } else if (REQ_SUCCESS(req)) { if (handle->flags & UV_HANDLE_CLOSING) { /* use UV_ECANCELED for consistency with Unix */ err = ERROR_OPERATION_ABORTED; @@ -1320,7 +1339,7 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int enable) { if (handle->socket != INVALID_SOCKET) { err = uv__tcp_nodelay(handle, handle->socket, enable); if (err) - return err; + return uv_translate_sys_error(err); } if (enable) { @@ -1339,7 +1358,7 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { if (handle->socket != INVALID_SOCKET) { err = uv__tcp_keepalive(handle, handle->socket, enable, delay); if (err) - return err; + return uv_translate_sys_error(err); } if (enable) { @@ -1386,9 +1405,24 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { } -static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) { - SOCKET socket = tcp->socket; +static void uv_tcp_try_cancel_reqs(uv_tcp_t* tcp) { + SOCKET socket; int non_ifs_lsp; + int reading; + int writing; + + socket = tcp->socket; + reading = tcp->flags & UV_HANDLE_READING; + writing = tcp->stream.conn.write_reqs_pending > 0; + if (!reading && !writing) + return; + + /* TODO: in libuv v2, keep explicit track of write_reqs, so we can cancel + * them each explicitly with CancelIoEx (like unix). */ + if (reading) + CancelIoEx((HANDLE) socket, &tcp->read_req.u.io.overlapped); + if (writing) + CancelIo((HANDLE) socket); /* Check if we have any non-IFS LSPs stacked on top of TCP */ non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : @@ -1408,71 +1442,41 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) { NULL, NULL) != 0) { /* Failed. We can't do CancelIo. */ - return -1; + return; } } assert(socket != 0 && socket != INVALID_SOCKET); - if (!CancelIo((HANDLE) socket)) { - return GetLastError(); + if (socket != tcp->socket) { + if (reading) + CancelIoEx((HANDLE) socket, &tcp->read_req.u.io.overlapped); + if (writing) + CancelIo((HANDLE) socket); } - - /* It worked. */ - return 0; } void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { - int close_socket = 1; - - if (tcp->flags & UV_HANDLE_READ_PENDING) { - /* In order for winsock to do a graceful close there must not be any any - * pending reads, or the socket must be shut down for writing */ - if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) { - /* Just do shutdown on non-shared sockets, which ensures graceful close. */ - shutdown(tcp->socket, SD_SEND); - - } else if (uv_tcp_try_cancel_io(tcp) == 0) { - /* In case of a shared socket, we try to cancel all outstanding I/O,. If - * that works, don't close the socket yet - wait for the read req to - * return and close the socket in uv_tcp_endgame. */ - close_socket = 0; - - } else { - /* When cancelling isn't possible - which could happen when an LSP is - * present on an old Windows version, we will have to close the socket - * with a read pending. That is not nice because trailing sent bytes may - * not make it to the other side. */ + if (tcp->flags & UV_HANDLE_CONNECTION) { + uv_tcp_try_cancel_reqs(tcp); + if (tcp->flags & UV_HANDLE_READING) { + uv_read_stop((uv_stream_t*) tcp); } - - } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) && - tcp->tcp.serv.accept_reqs != NULL) { - /* Under normal circumstances closesocket() will ensure that all pending - * accept reqs are canceled. However, when the socket is shared the - * presence of another reference to the socket in another process will keep - * the accept reqs going, so we have to ensure that these are canceled. */ - if (uv_tcp_try_cancel_io(tcp) != 0) { - /* When cancellation is not possible, there is another option: we can - * close the incoming sockets, which will also cancel the accept - * operations. However this is not cool because we might inadvertently - * close a socket that just accepted a new connection, which will cause - * the connection to be aborted. */ + } else { + if (tcp->tcp.serv.accept_reqs != NULL) { + /* First close the incoming sockets to cancel the accept operations before + * we free their resources. */ unsigned int i; for (i = 0; i < uv_simultaneous_server_accepts; i++) { uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i]; - if (req->accept_socket != INVALID_SOCKET && - !HasOverlappedIoCompleted(&req->u.io.overlapped)) { + if (req->accept_socket != INVALID_SOCKET) { closesocket(req->accept_socket); req->accept_socket = INVALID_SOCKET; } } } - } - - if (tcp->flags & UV_HANDLE_READING) { - tcp->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, tcp); + assert(!(tcp->flags & UV_HANDLE_READING)); } if (tcp->flags & UV_HANDLE_LISTENING) { @@ -1480,10 +1484,15 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { DECREASE_ACTIVE_COUNT(loop, tcp); } - if (close_socket) { + /* If any overlapped req failed to cancel, calling `closesocket` now would + * cause Win32 to send an RST packet. Try to avoid that for writes, if + * possibly applicable, by waiting to process the completion notifications + * first (which typically should be cancellations). There's not much we can + * do about canceled reads, which also will generate an RST packet. */ + if (!(tcp->flags & UV_HANDLE_CONNECTION) || + tcp->stream.conn.write_reqs_pending == 0) { closesocket(tcp->socket); tcp->socket = INVALID_SOCKET; - tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; } tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); @@ -1571,3 +1580,118 @@ int uv__tcp_connect(uv_connect_t* req, return 0; } + +#ifndef WSA_FLAG_NO_HANDLE_INHERIT +/* Added in Windows 7 SP1. Specify this to avoid race conditions, */ +/* but also manually clear the inherit flag in case this failed. */ +#define WSA_FLAG_NO_HANDLE_INHERIT 0x80 +#endif + +int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) { + SOCKET server = INVALID_SOCKET; + SOCKET client0 = INVALID_SOCKET; + SOCKET client1 = INVALID_SOCKET; + SOCKADDR_IN name; + LPFN_ACCEPTEX func_acceptex; + WSAOVERLAPPED overlap; + char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32]; + int namelen; + int err; + DWORD bytes; + DWORD flags; + DWORD client0_flags = WSA_FLAG_NO_HANDLE_INHERIT; + DWORD client1_flags = WSA_FLAG_NO_HANDLE_INHERIT; + + if (flags0 & UV_NONBLOCK_PIPE) + client0_flags |= WSA_FLAG_OVERLAPPED; + if (flags1 & UV_NONBLOCK_PIPE) + client1_flags |= WSA_FLAG_OVERLAPPED; + + server = WSASocketW(AF_INET, type, protocol, NULL, 0, + WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); + if (server == INVALID_SOCKET) + goto wsaerror; + if (!SetHandleInformation((HANDLE) server, HANDLE_FLAG_INHERIT, 0)) + goto error; + name.sin_family = AF_INET; + name.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + name.sin_port = 0; + if (bind(server, (SOCKADDR*) &name, sizeof(name)) != 0) + goto wsaerror; + if (listen(server, 1) != 0) + goto wsaerror; + namelen = sizeof(name); + if (getsockname(server, (SOCKADDR*) &name, &namelen) != 0) + goto wsaerror; + client0 = WSASocketW(AF_INET, type, protocol, NULL, 0, client0_flags); + if (client0 == INVALID_SOCKET) + goto wsaerror; + if (!SetHandleInformation((HANDLE) client0, HANDLE_FLAG_INHERIT, 0)) + goto error; + if (connect(client0, (SOCKADDR*) &name, sizeof(name)) != 0) + goto wsaerror; + client1 = WSASocketW(AF_INET, type, protocol, NULL, 0, client1_flags); + if (client1 == INVALID_SOCKET) + goto wsaerror; + if (!SetHandleInformation((HANDLE) client1, HANDLE_FLAG_INHERIT, 0)) + goto error; + if (!uv_get_acceptex_function(server, &func_acceptex)) { + err = WSAEAFNOSUPPORT; + goto cleanup; + } + memset(&overlap, 0, sizeof(overlap)); + if (!func_acceptex(server, + client1, + accept_buffer, + 0, + sizeof(struct sockaddr_storage), + sizeof(struct sockaddr_storage), + &bytes, + &overlap)) { + err = WSAGetLastError(); + if (err == ERROR_IO_PENDING) { + /* Result should complete immediately, since we already called connect, + * but emperically, we sometimes have to poll the kernel a couple times + * until it notices that. */ + while (!WSAGetOverlappedResult(client1, &overlap, &bytes, FALSE, &flags)) { + err = WSAGetLastError(); + if (err != WSA_IO_INCOMPLETE) + goto cleanup; + SwitchToThread(); + } + } + else { + goto cleanup; + } + } + if (setsockopt(client1, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, + (char*) &server, sizeof(server)) != 0) { + goto wsaerror; + } + + closesocket(server); + + fds[0] = client0; + fds[1] = client1; + + return 0; + + wsaerror: + err = WSAGetLastError(); + goto cleanup; + + error: + err = GetLastError(); + goto cleanup; + + cleanup: + if (server != INVALID_SOCKET) + closesocket(server); + if (client0 != INVALID_SOCKET) + closesocket(client0); + if (client1 != INVALID_SOCKET) + closesocket(client1); + + assert(err); + return uv_translate_sys_error(err); +} diff --git a/deps/libuv/src/win/udp.c b/deps/libuv/src/win/udp.c index 68ca728a..3043f2da 100644 --- a/deps/libuv/src/win/udp.c +++ b/deps/libuv/src/win/udp.c @@ -284,7 +284,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { handle->flags &= ~UV_HANDLE_ZERO_READ; handle->recv_buffer = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->recv_buffer); + handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &handle->recv_buffer); if (handle->recv_buffer.base == NULL || handle->recv_buffer.len == 0) { handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0); return; @@ -501,7 +501,7 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, /* Do a nonblocking receive. * TODO: try to read multiple datagrams at once. FIONREAD maybe? */ buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 65536, &buf); + handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf); if (buf.base == NULL || buf.len == 0) { handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); goto done; diff --git a/deps/libuv/src/win/util.c b/deps/libuv/src/win/util.c index aad8f1a1..88602c7e 100644 --- a/deps/libuv/src/win/util.c +++ b/deps/libuv/src/win/util.c @@ -1664,26 +1664,33 @@ int uv_os_unsetenv(const char* name) { int uv_os_gethostname(char* buffer, size_t* size) { - char buf[UV_MAXHOSTNAMESIZE]; + WCHAR buf[UV_MAXHOSTNAMESIZE]; size_t len; + char* utf8_str; + int convert_result; if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; uv__once_init(); /* Initialize winsock */ - if (gethostname(buf, sizeof(buf)) != 0) + if (GetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0) return uv_translate_sys_error(WSAGetLastError()); - buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */ - len = strlen(buf); + convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str); + if (convert_result != 0) + return convert_result; + + len = strlen(utf8_str); if (len >= *size) { *size = len + 1; + uv__free(utf8_str); return UV_ENOBUFS; } - memcpy(buffer, buf, len + 1); + memcpy(buffer, utf8_str, len + 1); + uv__free(utf8_str); *size = len; return 0; } diff --git a/deps/libuv/test/benchmark-async-pummel.c b/deps/libuv/test/benchmark-async-pummel.c index 119ae5ee..49660a6f 100644 --- a/deps/libuv/test/benchmark-async-pummel.c +++ b/deps/libuv/test/benchmark-async-pummel.c @@ -68,7 +68,7 @@ static int test_async_pummel(int nthreads) { int i; tids = calloc(nthreads, sizeof(tids[0])); - ASSERT(tids != NULL); + ASSERT_NOT_NULL(tids); ASSERT(0 == uv_async_init(uv_default_loop(), &handle, async_cb)); ACCESS_ONCE(const char*, handle.data) = running; diff --git a/deps/libuv/test/benchmark-async.c b/deps/libuv/test/benchmark-async.c index e44165f2..5167ecbd 100644 --- a/deps/libuv/test/benchmark-async.c +++ b/deps/libuv/test/benchmark-async.c @@ -79,7 +79,7 @@ static int test_async(int nthreads) { int i; threads = calloc(nthreads, sizeof(threads[0])); - ASSERT(threads != NULL); + ASSERT_NOT_NULL(threads); for (i = 0; i < nthreads; i++) { ctx = threads + i; diff --git a/deps/libuv/test/benchmark-million-async.c b/deps/libuv/test/benchmark-million-async.c index 5395ed54..937a12f8 100644 --- a/deps/libuv/test/benchmark-million-async.c +++ b/deps/libuv/test/benchmark-million-async.c @@ -86,7 +86,7 @@ BENCHMARK_IMPL(million_async) { timeout = 5000; container = malloc(sizeof(*container)); - ASSERT(container != NULL); + ASSERT_NOT_NULL(container); container->async_events = 0; container->handles_seen = 0; diff --git a/deps/libuv/test/benchmark-million-timers.c b/deps/libuv/test/benchmark-million-timers.c index 60a308be..ef25c205 100644 --- a/deps/libuv/test/benchmark-million-timers.c +++ b/deps/libuv/test/benchmark-million-timers.c @@ -49,7 +49,7 @@ BENCHMARK_IMPL(million_timers) { int i; timers = malloc(NUM_TIMERS * sizeof(timers[0])); - ASSERT(timers != NULL); + ASSERT_NOT_NULL(timers); loop = uv_default_loop(); timeout = 0; diff --git a/deps/libuv/test/benchmark-multi-accept.c b/deps/libuv/test/benchmark-multi-accept.c index 5a186233..86b7da5a 100644 --- a/deps/libuv/test/benchmark-multi-accept.c +++ b/deps/libuv/test/benchmark-multi-accept.c @@ -114,7 +114,7 @@ static void ipc_connection_cb(uv_stream_t* ipc_pipe, int status) { buf = uv_buf_init("PING", 4); sc = container_of(ipc_pipe, struct ipc_server_ctx, ipc_pipe); pc = calloc(1, sizeof(*pc)); - ASSERT(pc != NULL); + ASSERT_NOT_NULL(pc); if (ipc_pipe->type == UV_TCP) ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) &pc->peer_handle)); @@ -295,7 +295,7 @@ static void sv_connection_cb(uv_stream_t* server_handle, int status) { ASSERT(status == 0); storage = malloc(sizeof(*storage)); - ASSERT(storage != NULL); + ASSERT_NOT_NULL(storage); if (server_handle->type == UV_TCP) ASSERT(0 == uv_tcp_init(server_handle->loop, (uv_tcp_t*) storage)); @@ -372,8 +372,8 @@ static int test_tcp(unsigned int num_servers, unsigned int num_clients) { servers = calloc(num_servers, sizeof(servers[0])); clients = calloc(num_clients, sizeof(clients[0])); - ASSERT(servers != NULL); - ASSERT(clients != NULL); + ASSERT_NOT_NULL(servers); + ASSERT_NOT_NULL(clients); /* We're making the assumption here that from the perspective of the * OS scheduler, threads are functionally equivalent to and interchangeable diff --git a/deps/libuv/test/benchmark-pound.c b/deps/libuv/test/benchmark-pound.c index 79f36345..830bc554 100644 --- a/deps/libuv/test/benchmark-pound.c +++ b/deps/libuv/test/benchmark-pound.c @@ -114,11 +114,11 @@ static void connect_cb(uv_connect_t* req, int status) { return; } - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); conn = (conn_rec*)req->data; - ASSERT(conn != NULL); + ASSERT_NOT_NULL(conn); #if DEBUG printf("connect_cb %d\n", conn->i); @@ -137,7 +137,7 @@ static void connect_cb(uv_connect_t* req, int status) { static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - ASSERT(stream != NULL); + ASSERT_NOT_NULL(stream); #if DEBUG printf("read_cb %d\n", p->i); @@ -161,7 +161,7 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { static void close_cb(uv_handle_t* handle) { conn_rec* p = (conn_rec*)handle->data; - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); closed_streams++; #if DEBUG diff --git a/deps/libuv/test/benchmark-pump.c b/deps/libuv/test/benchmark-pump.c index 8685258e..7d3977df 100644 --- a/deps/libuv/test/benchmark-pump.c +++ b/deps/libuv/test/benchmark-pump.c @@ -390,6 +390,7 @@ HELPER_IMPL(tcp_pump_server) { r = uv_listen((uv_stream_t*)&tcpServer, MAX_WRITE_HANDLES, connection_cb); ASSERT(r == 0); + notify_parent_process(); uv_run(loop, UV_RUN_DEFAULT); return 0; @@ -411,6 +412,7 @@ HELPER_IMPL(pipe_pump_server) { r = uv_listen((uv_stream_t*)&pipeServer, MAX_WRITE_HANDLES, connection_cb); ASSERT(r == 0); + notify_parent_process(); uv_run(loop, UV_RUN_DEFAULT); MAKE_VALGRIND_HAPPY(); diff --git a/deps/libuv/test/benchmark-tcp-write-batch.c b/deps/libuv/test/benchmark-tcp-write-batch.c index 96921b70..16aa72f6 100644 --- a/deps/libuv/test/benchmark-tcp-write-batch.c +++ b/deps/libuv/test/benchmark-tcp-write-batch.c @@ -71,7 +71,7 @@ static void connect_cb(uv_connect_t* req, int status) { static void write_cb(uv_write_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); write_cb_called++; } @@ -103,7 +103,7 @@ BENCHMARK_IMPL(tcp_write_batch) { int r; write_reqs = malloc(sizeof(*write_reqs) * NUM_WRITE_REQS); - ASSERT(write_reqs != NULL); + ASSERT_NOT_NULL(write_reqs); /* Prepare the data to write out. */ for (i = 0; i < NUM_WRITE_REQS; i++) { diff --git a/deps/libuv/test/benchmark-udp-pummel.c b/deps/libuv/test/benchmark-udp-pummel.c index 68a2373d..1a220570 100644 --- a/deps/libuv/test/benchmark-udp-pummel.c +++ b/deps/libuv/test/benchmark-udp-pummel.c @@ -72,7 +72,7 @@ static void alloc_cb(uv_handle_t* handle, static void send_cb(uv_udp_send_t* req, int status) { struct sender_state* s; - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); if (status != 0) { ASSERT(status == UV_ECANCELED); @@ -127,7 +127,7 @@ static void recv_cb(uv_udp_t* handle, static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } @@ -179,11 +179,11 @@ static int pummel(unsigned int n_senders, uv_unref((uv_handle_t*)&s->udp_handle); } - bufs[0] = uv_buf_init(EXPECTED + 0, 10); - bufs[1] = uv_buf_init(EXPECTED + 10, 10); - bufs[2] = uv_buf_init(EXPECTED + 20, 10); - bufs[3] = uv_buf_init(EXPECTED + 30, 10); - bufs[4] = uv_buf_init(EXPECTED + 40, 5); + bufs[0] = uv_buf_init(&EXPECTED[0], 10); + bufs[1] = uv_buf_init(&EXPECTED[10], 10); + bufs[2] = uv_buf_init(&EXPECTED[20], 10); + bufs[3] = uv_buf_init(&EXPECTED[30], 10); + bufs[4] = uv_buf_init(&EXPECTED[40], 5); for (i = 0; i < n_senders; i++) { struct sender_state* s = senders + i; diff --git a/deps/libuv/test/blackhole-server.c b/deps/libuv/test/blackhole-server.c index ad878b35..0a8758e1 100644 --- a/deps/libuv/test/blackhole-server.c +++ b/deps/libuv/test/blackhole-server.c @@ -47,7 +47,7 @@ static void connection_cb(uv_stream_t* stream, int status) { ASSERT(stream == (uv_stream_t*)&tcp_server); conn = malloc(sizeof *conn); - ASSERT(conn != NULL); + ASSERT_NOT_NULL(conn); r = uv_tcp_init(stream->loop, &conn->handle); ASSERT(r == 0); @@ -114,6 +114,7 @@ HELPER_IMPL(tcp4_blackhole_server) { r = uv_listen((uv_stream_t*)&tcp_server, 128, connection_cb); ASSERT(r == 0); + notify_parent_process(); r = uv_run(loop, UV_RUN_DEFAULT); ASSERT(0 && "Blackhole server dropped out of event loop."); diff --git a/deps/libuv/test/dns-server.c b/deps/libuv/test/dns-server.c index 80052c70..f8ca87f2 100644 --- a/deps/libuv/test/dns-server.c +++ b/deps/libuv/test/dns-server.c @@ -280,7 +280,7 @@ static void on_connection(uv_stream_t* server, int status) { ASSERT(status == 0); handle = (dnshandle*) malloc(sizeof *handle); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); /* initialize read buffer state */ handle->state.prevbuf_ptr = 0; diff --git a/deps/libuv/test/echo-server.c b/deps/libuv/test/echo-server.c index c65142ff..058c9925 100644 --- a/deps/libuv/test/echo-server.c +++ b/deps/libuv/test/echo-server.c @@ -65,25 +65,35 @@ static void after_write(uv_write_t* req, int status) { static void after_shutdown(uv_shutdown_t* req, int status) { + ASSERT_EQ(status, 0); uv_close((uv_handle_t*) req->handle, on_close); free(req); } +static void on_shutdown(uv_shutdown_t* req, int status) { + ASSERT_EQ(status, 0); + free(req); +} + + static void after_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { int i; write_req_t *wr; uv_shutdown_t* sreq; + int shutdown = 0; if (nread < 0) { /* Error or EOF */ - ASSERT(nread == UV_EOF); + ASSERT_EQ(nread, UV_EOF); free(buf->base); sreq = malloc(sizeof* sreq); - ASSERT(0 == uv_shutdown(sreq, handle, after_shutdown)); + if (uv_is_writable(handle)) { + ASSERT_EQ(0, uv_shutdown(sreq, handle, after_shutdown)); + } return; } @@ -96,29 +106,42 @@ static void after_read(uv_stream_t* handle, /* * Scan for the letter Q which signals that we should quit the server. * If we get QS it means close the stream. + * If we get QSS it means shutdown the stream. + * If we get QSH it means disable linger before close the socket. */ - if (!server_closed) { - for (i = 0; i < nread; i++) { - if (buf->base[i] == 'Q') { - if (i + 1 < nread && buf->base[i + 1] == 'S') { - free(buf->base); - uv_close((uv_handle_t*)handle, on_close); - return; - } else { - uv_close(server, on_server_close); - server_closed = 1; - } + for (i = 0; i < nread; i++) { + if (buf->base[i] == 'Q') { + if (i + 1 < nread && buf->base[i + 1] == 'S') { + int reset = 0; + if (i + 2 < nread && buf->base[i + 2] == 'S') + shutdown = 1; + if (i + 2 < nread && buf->base[i + 2] == 'H') + reset = 1; + if (reset && handle->type == UV_TCP) + ASSERT_EQ(0, uv_tcp_close_reset((uv_tcp_t*) handle, on_close)); + else if (shutdown) + break; + else + uv_close((uv_handle_t*) handle, on_close); + free(buf->base); + return; + } else if (!server_closed) { + uv_close(server, on_server_close); + server_closed = 1; } } } wr = (write_req_t*) malloc(sizeof *wr); - ASSERT(wr != NULL); + ASSERT_NOT_NULL(wr); wr->buf = uv_buf_init(buf->base, nread); if (uv_write(&wr->req, handle, &wr->buf, 1, after_write)) { FATAL("uv_write failed"); } + + if (shutdown) + ASSERT_EQ(0, uv_shutdown(malloc(sizeof* sreq), handle, on_shutdown)); } @@ -155,14 +178,14 @@ static void on_connection(uv_stream_t* server, int status) { switch (serverType) { case TCP: stream = malloc(sizeof(uv_tcp_t)); - ASSERT(stream != NULL); + ASSERT_NOT_NULL(stream); r = uv_tcp_init(loop, (uv_tcp_t*)stream); ASSERT(r == 0); break; case PIPE: stream = malloc(sizeof(uv_pipe_t)); - ASSERT(stream != NULL); + ASSERT_NOT_NULL(stream); r = uv_pipe_init(loop, (uv_pipe_t*)stream, 0); ASSERT(r == 0); break; @@ -197,7 +220,7 @@ static uv_udp_send_t* send_alloc(void) { } static void on_send(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); req->data = send_freelist; send_freelist = req; @@ -209,6 +232,7 @@ static void on_recv(uv_udp_t* handle, const struct sockaddr* addr, unsigned flags) { uv_buf_t sndbuf; + uv_udp_send_t* req; if (nread == 0) { /* Everything OK, but nothing read. */ @@ -218,8 +242,8 @@ static void on_recv(uv_udp_t* handle, ASSERT(nread > 0); ASSERT(addr->sa_family == AF_INET); - uv_udp_send_t* req = send_alloc(); - ASSERT(req != NULL); + req = send_alloc(); + ASSERT_NOT_NULL(req); sndbuf = uv_buf_init(rcvbuf->base, nread); ASSERT(0 <= uv_udp_send(req, handle, &sndbuf, 1, addr, on_send)); } @@ -228,7 +252,7 @@ static int tcp4_echo_start(int port) { struct sockaddr_in addr; int r; - ASSERT(0 == uv_ip4_addr("0.0.0.0", port, &addr)); + ASSERT(0 == uv_ip4_addr("127.0.0.1", port, &addr)); server = (uv_handle_t*)&tcpServer; serverType = TCP; diff --git a/deps/libuv/test/run-benchmarks.c b/deps/libuv/test/run-benchmarks.c index 980c9be8..2b343da4 100644 --- a/deps/libuv/test/run-benchmarks.c +++ b/deps/libuv/test/run-benchmarks.c @@ -28,6 +28,16 @@ /* Actual benchmarks and helpers are defined in benchmark-list.h */ #include "benchmark-list.h" +#ifdef __MVS__ +#include "zos-base.h" +/* Initialize environment and zoslib */ +__attribute__((constructor)) void init() { + zoslib_config_t config; + init_zoslib_config(&config); + init_zoslib(config); +} +#endif + static int maybe_run_test(int argc, char **argv); @@ -44,8 +54,6 @@ int main(int argc, char **argv) { fflush(stderr); return EXIT_FAILURE; } - - return EXIT_SUCCESS; } diff --git a/deps/libuv/test/run-tests.c b/deps/libuv/test/run-tests.c index e5e75e17..5e53aaa8 100644 --- a/deps/libuv/test/run-tests.c +++ b/deps/libuv/test/run-tests.c @@ -36,6 +36,16 @@ /* Actual tests and helpers are defined in test-list.h */ #include "test-list.h" +#ifdef __MVS__ +#include "zos-base.h" +/* Initialize environment and zoslib */ +__attribute__((constructor)) void init() { + zoslib_config_t config; + init_zoslib_config(&config); + init_zoslib(config); +} +#endif + int ipc_helper(int listen_after_write); int ipc_helper_heavy_traffic_deadlock_bug(void); int ipc_helper_tcp_connection(void); @@ -50,6 +60,10 @@ int spawn_tcp_server_helper(void); static int maybe_run_test(int argc, char **argv); +#ifdef _WIN32 +typedef BOOL (WINAPI *sCompareObjectHandles)(_In_ HANDLE, _In_ HANDLE); +#endif + int main(int argc, char **argv) { #ifndef _WIN32 @@ -149,7 +163,7 @@ static int maybe_run_test(int argc, char **argv) { if (strcmp(argv[1], "spawn_helper4") == 0) { notify_parent_process(); /* Never surrender, never return! */ - while (1) uv_sleep(10000); + for (;;) uv_sleep(10000); } if (strcmp(argv[1], "spawn_helper5") == 0) { @@ -194,7 +208,7 @@ static int maybe_run_test(int argc, char **argv) { /* Test if the test value from the parent is still set */ test = getenv("ENV_TEST"); - ASSERT(test != NULL); + ASSERT_NOT_NULL(test); r = fprintf(stdout, "%s", test); ASSERT(r > 0); @@ -202,22 +216,36 @@ static int maybe_run_test(int argc, char **argv) { return 1; } -#ifndef _WIN32 if (strcmp(argv[1], "spawn_helper8") == 0) { - int fd; - + uv_os_fd_t closed_fd; + uv_os_fd_t open_fd; +#ifdef _WIN32 + DWORD flags; + HMODULE kernelbase_module; + sCompareObjectHandles pCompareObjectHandles; /* function introduced in Windows 10 */ +#endif notify_parent_process(); - ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd))); - ASSERT(fd > 2); + ASSERT(sizeof(closed_fd) == read(0, &closed_fd, sizeof(closed_fd))); + ASSERT(sizeof(open_fd) == read(0, &open_fd, sizeof(open_fd))); +#ifdef _WIN32 + ASSERT((intptr_t) closed_fd > 0); + ASSERT((intptr_t) open_fd > 0); + ASSERT(0 != GetHandleInformation(open_fd, &flags)); + kernelbase_module = GetModuleHandleA("kernelbase.dll"); + pCompareObjectHandles = (sCompareObjectHandles) + GetProcAddress(kernelbase_module, "CompareObjectHandles"); + ASSERT(pCompareObjectHandles == NULL || !pCompareObjectHandles(open_fd, closed_fd)); +#else + ASSERT(open_fd > 2); + ASSERT(closed_fd > 2); # if defined(__PASE__) /* On IBMi PASE, write() returns 1 */ - ASSERT(1 == write(fd, "x", 1)); + ASSERT(1 == write(closed_fd, "x", 1)); # else - ASSERT(-1 == write(fd, "x", 1)); + ASSERT(-1 == write(closed_fd, "x", 1)); # endif /* !__PASE__ */ - +#endif return 1; } -#endif /* !_WIN32 */ if (strcmp(argv[1], "spawn_helper9") == 0) { notify_parent_process(); diff --git a/deps/libuv/test/runner-unix.c b/deps/libuv/test/runner-unix.c index b7ca1f85..a13648bc 100644 --- a/deps/libuv/test/runner-unix.c +++ b/deps/libuv/test/runner-unix.c @@ -197,7 +197,7 @@ static void* dowait(void* data) { process_info_t* p; for (i = 0; i < args->n; i++) { - p = (process_info_t*)(args->vec + i * sizeof(process_info_t)); + p = &args->vec[i]; if (p->terminated) continue; r = waitpid(p->pid, &p->status, 0); if (r < 0) { @@ -323,7 +323,7 @@ int process_wait(process_info_t* vec, int n, int timeout) { } else { /* Timeout. Kill all the children. */ for (i = 0; i < n; i++) { - p = (process_info_t*)(vec + i * sizeof(process_info_t)); + p = &vec[i]; kill(p->pid, SIGTERM); } retval = -2; diff --git a/deps/libuv/test/runner.c b/deps/libuv/test/runner.c index bb50b43b..78910827 100644 --- a/deps/libuv/test/runner.c +++ b/deps/libuv/test/runner.c @@ -98,8 +98,8 @@ int run_tests(int benchmark_output) { skip = (actual > 0 && 0 == strcmp(TASKS[0].task_name, "platform_output")); qsort(TASKS + skip, actual - skip, sizeof(TASKS[0]), compare_task); - fprintf(stderr, "1..%d\n", total); - fflush(stderr); + fprintf(stdout, "1..%d\n", total); + fflush(stdout); /* Run all tests. */ passed = 0; @@ -156,8 +156,8 @@ void log_tap_result(int test_count, reason[0] = '\0'; } - fprintf(stderr, "%s %d - %s%s%s\n", result, test_count, test, directive, reason); - fflush(stderr); + fprintf(stdout, "%s %d - %s%s%s\n", result, test_count, test, directive, reason); + fflush(stdout); } @@ -307,28 +307,28 @@ out: /* Show error and output from processes if the test failed. */ if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) { if (strlen(errmsg) > 0) - fprintf(stderr, "# %s\n", errmsg); - fprintf(stderr, "# "); - fflush(stderr); + fprintf(stdout, "# %s\n", errmsg); + fprintf(stdout, "# "); + fflush(stdout); for (i = 0; i < process_count; i++) { switch (process_output_size(&processes[i])) { case -1: - fprintf(stderr, "Output from process `%s`: (unavailable)\n", + fprintf(stdout, "Output from process `%s`: (unavailable)\n", process_get_name(&processes[i])); - fflush(stderr); + fflush(stdout); break; case 0: - fprintf(stderr, "Output from process `%s`: (no output)\n", + fprintf(stdout, "Output from process `%s`: (no output)\n", process_get_name(&processes[i])); - fflush(stderr); + fflush(stdout); break; default: - fprintf(stderr, "Output from process `%s`:\n", process_get_name(&processes[i])); - fflush(stderr); - process_copy_output(&processes[i], stderr); + fprintf(stdout, "Output from process `%s`:\n", process_get_name(&processes[i])); + fflush(stdout); + process_copy_output(&processes[i], stdout); break; } } @@ -337,18 +337,18 @@ out: } else if (benchmark_output) { switch (process_output_size(main_proc)) { case -1: - fprintf(stderr, "%s: (unavailable)\n", test); - fflush(stderr); + fprintf(stdout, "%s: (unavailable)\n", test); + fflush(stdout); break; case 0: - fprintf(stderr, "%s: (no output)\n", test); - fflush(stderr); + fprintf(stdout, "%s: (no output)\n", test); + fflush(stdout); break; default: for (i = 0; i < process_count; i++) { - process_copy_output(&processes[i], stderr); + process_copy_output(&processes[i], stdout); } break; } @@ -378,8 +378,8 @@ int run_test_part(const char* test, const char* part) { } } - fprintf(stderr, "No test part with that name: %s:%s\n", test, part); - fflush(stderr); + fprintf(stdout, "No test part with that name: %s:%s\n", test, part); + fflush(stdout); return 255; } diff --git a/deps/libuv/test/task.h b/deps/libuv/test/task.h index 8250f949..a02c8931 100644 --- a/deps/libuv/test/task.h +++ b/deps/libuv/test/task.h @@ -52,6 +52,7 @@ #define TEST_PORT 9123 #define TEST_PORT_2 9124 +#define TEST_PORT_3 9125 #ifdef _WIN32 # define TEST_PIPENAME "\\\\?\\pipe\\uv-test" @@ -113,8 +114,8 @@ typedef enum { #define ASSERT_BASE(a, operator, b, type, conv) \ do { \ - type eval_a = (type) (a); \ - type eval_b = (type) (b); \ + volatile type eval_a = (type) (a); \ + volatile type eval_b = (type) (b); \ if (!(eval_a operator eval_b)) { \ fprintf(stderr, \ "Assertion failed in %s on line %d: `%s %s %s` " \ @@ -196,22 +197,26 @@ typedef enum { } \ } while (0) -#define ASSERT_INT_BASE(a, operator, b, type, conv) \ - ASSERT_BASE(a, operator, b, type, conv) +#define ASSERT_EQ(a, b) ASSERT_BASE(a, ==, b, int64_t, PRId64) +#define ASSERT_GE(a, b) ASSERT_BASE(a, >=, b, int64_t, PRId64) +#define ASSERT_GT(a, b) ASSERT_BASE(a, >, b, int64_t, PRId64) +#define ASSERT_LE(a, b) ASSERT_BASE(a, <=, b, int64_t, PRId64) +#define ASSERT_LT(a, b) ASSERT_BASE(a, <, b, int64_t, PRId64) +#define ASSERT_NE(a, b) ASSERT_BASE(a, !=, b, int64_t, PRId64) -#define ASSERT_EQ(a, b) ASSERT_INT_BASE(a, ==, b, int64_t, PRId64) -#define ASSERT_GE(a, b) ASSERT_INT_BASE(a, >=, b, int64_t, PRId64) -#define ASSERT_GT(a, b) ASSERT_INT_BASE(a, >, b, int64_t, PRId64) -#define ASSERT_LE(a, b) ASSERT_INT_BASE(a, <=, b, int64_t, PRId64) -#define ASSERT_LT(a, b) ASSERT_INT_BASE(a, <, b, int64_t, PRId64) -#define ASSERT_NE(a, b) ASSERT_INT_BASE(a, !=, b, int64_t, PRId64) +#define ASSERT_UINT64_EQ(a, b) ASSERT_BASE(a, ==, b, uint64_t, PRIu64) +#define ASSERT_UINT64_GE(a, b) ASSERT_BASE(a, >=, b, uint64_t, PRIu64) +#define ASSERT_UINT64_GT(a, b) ASSERT_BASE(a, >, b, uint64_t, PRIu64) +#define ASSERT_UINT64_LE(a, b) ASSERT_BASE(a, <=, b, uint64_t, PRIu64) +#define ASSERT_UINT64_LT(a, b) ASSERT_BASE(a, <, b, uint64_t, PRIu64) +#define ASSERT_UINT64_NE(a, b) ASSERT_BASE(a, !=, b, uint64_t, PRIu64) -#define ASSERT_UINT64_EQ(a, b) ASSERT_INT_BASE(a, ==, b, uint64_t, PRIu64) -#define ASSERT_UINT64_GE(a, b) ASSERT_INT_BASE(a, >=, b, uint64_t, PRIu64) -#define ASSERT_UINT64_GT(a, b) ASSERT_INT_BASE(a, >, b, uint64_t, PRIu64) -#define ASSERT_UINT64_LE(a, b) ASSERT_INT_BASE(a, <=, b, uint64_t, PRIu64) -#define ASSERT_UINT64_LT(a, b) ASSERT_INT_BASE(a, <, b, uint64_t, PRIu64) -#define ASSERT_UINT64_NE(a, b) ASSERT_INT_BASE(a, !=, b, uint64_t, PRIu64) +#define ASSERT_DOUBLE_EQ(a, b) ASSERT_BASE(a, ==, b, double, "f") +#define ASSERT_DOUBLE_GE(a, b) ASSERT_BASE(a, >=, b, double, "f") +#define ASSERT_DOUBLE_GT(a, b) ASSERT_BASE(a, >, b, double, "f") +#define ASSERT_DOUBLE_LE(a, b) ASSERT_BASE(a, <=, b, double, "f") +#define ASSERT_DOUBLE_LT(a, b) ASSERT_BASE(a, <, b, double, "f") +#define ASSERT_DOUBLE_NE(a, b) ASSERT_BASE(a, !=, b, double, "f") #define ASSERT_STR_EQ(a, b) \ ASSERT_BASE_STR(strcmp(a, b) == 0, a, == , b, char*, "s") diff --git a/deps/libuv/test/test-active.c b/deps/libuv/test/test-active.c index b17bd176..38438956 100644 --- a/deps/libuv/test/test-active.c +++ b/deps/libuv/test/test-active.c @@ -30,7 +30,7 @@ static int close_cb_called = 0; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-async.c b/deps/libuv/test/test-async.c index 6f5351bf..619be620 100644 --- a/deps/libuv/test/test-async.c +++ b/deps/libuv/test/test-async.c @@ -70,7 +70,7 @@ static void thread_cb(void *arg) { static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-callback-stack.c b/deps/libuv/test/test-callback-stack.c index 1871e7e9..a5195c7b 100644 --- a/deps/libuv/test/test-callback-stack.c +++ b/deps/libuv/test/test-callback-stack.c @@ -48,7 +48,7 @@ static int shutdown_cb_called = 0; static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { buf->len = size; buf->base = malloc(size); - ASSERT(buf->base != NULL); + ASSERT_NOT_NULL(buf->base); } diff --git a/deps/libuv/test/test-close-fd.c b/deps/libuv/test/test-close-fd.c index cea4a1b0..0d3927f6 100644 --- a/deps/libuv/test/test-close-fd.c +++ b/deps/libuv/test/test-close-fd.c @@ -19,12 +19,11 @@ * IN THE SOFTWARE. */ -#if !defined(_WIN32) - #include "uv.h" #include "task.h" -#include +#ifndef _WIN32 #include +#endif static unsigned int read_cb_called; @@ -51,14 +50,25 @@ static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { TEST_IMPL(close_fd) { uv_pipe_t pipe_handle; - int fd[2]; + uv_fs_t req; + uv_buf_t bufs[1]; + uv_file fd[2]; + bufs[0] = uv_buf_init("", 1); - ASSERT(0 == pipe(fd)); + ASSERT(0 == uv_pipe(fd, 0, 0)); ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0])); - fd[0] = -1; /* uv_pipe_open() takes ownership of the file descriptor. */ - ASSERT(1 == write(fd[1], "", 1)); + /* uv_pipe_open() takes ownership of the file descriptor. */ + fd[0] = -1; + + ASSERT(1 == uv_fs_write(NULL, &req, fd[1], bufs, 1, -1, NULL)); + ASSERT(1 == req.result); + uv_fs_req_cleanup(&req); +#ifdef _WIN32 + ASSERT(0 == _close(fd[1])); +#else ASSERT(0 == close(fd[1])); +#endif fd[1] = -1; ASSERT(0 == uv_read_start((uv_stream_t *) &pipe_handle, alloc_cb, read_cb)); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); @@ -72,9 +82,3 @@ TEST_IMPL(close_fd) { MAKE_VALGRIND_HAPPY(); return 0; } - -#else - -typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */ - -#endif /* !_WIN32 */ diff --git a/deps/libuv/test/test-close-order.c b/deps/libuv/test/test-close-order.c index 2b24f6d6..c2fd6c3d 100644 --- a/deps/libuv/test/test-close-order.c +++ b/deps/libuv/test/test-close-order.c @@ -32,7 +32,7 @@ static uv_timer_t timer_handle2; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-default-loop-close.c b/deps/libuv/test/test-default-loop-close.c index fd11cfa8..51e1e7dc 100644 --- a/deps/libuv/test/test-default-loop-close.c +++ b/deps/libuv/test/test-default-loop-close.c @@ -37,7 +37,7 @@ TEST_IMPL(default_loop_close) { uv_timer_t timer_handle; loop = uv_default_loop(); - ASSERT(loop != NULL); + ASSERT_NOT_NULL(loop); ASSERT(0 == uv_timer_init(loop, &timer_handle)); ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 1, 0)); @@ -46,7 +46,7 @@ TEST_IMPL(default_loop_close) { ASSERT(0 == uv_loop_close(loop)); loop = uv_default_loop(); - ASSERT(loop != NULL); + ASSERT_NOT_NULL(loop); ASSERT(0 == uv_timer_init(loop, &timer_handle)); ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 1, 0)); diff --git a/deps/libuv/test/test-delayed-accept.c b/deps/libuv/test/test-delayed-accept.c index 513e69bd..88b31e26 100644 --- a/deps/libuv/test/test-delayed-accept.c +++ b/deps/libuv/test/test-delayed-accept.c @@ -37,7 +37,7 @@ static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); free(handle); @@ -50,8 +50,8 @@ static void do_accept(uv_timer_t* timer_handle) { uv_tcp_t* accepted_handle = (uv_tcp_t*)malloc(sizeof *accepted_handle); int r; - ASSERT(timer_handle != NULL); - ASSERT(accepted_handle != NULL); + ASSERT_NOT_NULL(timer_handle); + ASSERT_NOT_NULL(accepted_handle); r = uv_tcp_init(uv_default_loop(), accepted_handle); ASSERT(r == 0); @@ -82,7 +82,7 @@ static void connection_cb(uv_stream_t* tcp, int status) { ASSERT(status == 0); timer_handle = (uv_timer_t*)malloc(sizeof *timer_handle); - ASSERT(timer_handle != NULL); + ASSERT_NOT_NULL(timer_handle); /* Accept the client after 1 second */ r = uv_timer_init(uv_default_loop(), timer_handle); @@ -103,7 +103,7 @@ static void start_server(void) { int r; ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - ASSERT(server != NULL); + ASSERT_NOT_NULL(server); r = uv_tcp_init(uv_default_loop(), server); ASSERT(r == 0); @@ -125,7 +125,7 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { if (nread >= 0) { ASSERT(nread == 0); } else { - ASSERT(tcp != NULL); + ASSERT_NOT_NULL(tcp); ASSERT(nread == UV_EOF); uv_close((uv_handle_t*)tcp, close_cb); } @@ -135,7 +135,7 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { static void connect_cb(uv_connect_t* req, int status) { int r; - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); /* Not that the server will send anything, but otherwise we'll never know @@ -156,8 +156,8 @@ static void client_connect(void) { int r; ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(client != NULL); - ASSERT(connect_req != NULL); + ASSERT_NOT_NULL(client); + ASSERT_NOT_NULL(connect_req); r = uv_tcp_init(uv_default_loop(), client); ASSERT(r == 0); diff --git a/deps/libuv/test/test-dlerror.c b/deps/libuv/test/test-dlerror.c index 42ad6882..a436ec01 100644 --- a/deps/libuv/test/test-dlerror.c +++ b/deps/libuv/test/test-dlerror.c @@ -34,26 +34,26 @@ TEST_IMPL(dlerror) { lib.errmsg = NULL; lib.handle = NULL; msg = uv_dlerror(&lib); - ASSERT(msg != NULL); - ASSERT(strstr(msg, dlerror_no_error) != NULL); + ASSERT_NOT_NULL(msg); + ASSERT_NOT_NULL(strstr(msg, dlerror_no_error)); r = uv_dlopen(path, &lib); ASSERT(r == -1); msg = uv_dlerror(&lib); - ASSERT(msg != NULL); + ASSERT_NOT_NULL(msg); #if !defined(__OpenBSD__) && !defined(__QNX__) - ASSERT(strstr(msg, path) != NULL); + ASSERT_NOT_NULL(strstr(msg, path)); #endif - ASSERT(strstr(msg, dlerror_no_error) == NULL); + ASSERT_NULL(strstr(msg, dlerror_no_error)); /* Should return the same error twice in a row. */ msg = uv_dlerror(&lib); - ASSERT(msg != NULL); + ASSERT_NOT_NULL(msg); #if !defined(__OpenBSD__) && !defined(__QNX__) - ASSERT(strstr(msg, path) != NULL); + ASSERT_NOT_NULL(strstr(msg, path)); #endif - ASSERT(strstr(msg, dlerror_no_error) == NULL); + ASSERT_NULL(strstr(msg, dlerror_no_error)); uv_dlclose(&lib); diff --git a/deps/libuv/test/test-error.c b/deps/libuv/test/test-error.c index 7f44f4a1..f0fb8646 100644 --- a/deps/libuv/test/test-error.c +++ b/deps/libuv/test/test-error.c @@ -37,6 +37,9 @@ * See https://github.com/joyent/libuv/issues/210 */ TEST_IMPL(error_message) { +#if defined(__ASAN__) + RETURN_SKIP("Test does not currently work in ASAN"); +#endif char buf[32]; /* Cop out. Can't do proper checks on systems with @@ -47,13 +50,13 @@ TEST_IMPL(error_message) { return 0; } - ASSERT(strstr(uv_strerror(UV_EINVAL), "Success") == NULL); + ASSERT_NULL(strstr(uv_strerror(UV_EINVAL), "Success")); ASSERT(strcmp(uv_strerror(1337), "Unknown error") == 0); ASSERT(strcmp(uv_strerror(-1337), "Unknown error") == 0); - ASSERT(strstr(uv_strerror_r(UV_EINVAL, buf, sizeof(buf)), "Success") == NULL); - ASSERT(strstr(uv_strerror_r(1337, buf, sizeof(buf)), "1337") != NULL); - ASSERT(strstr(uv_strerror_r(-1337, buf, sizeof(buf)), "-1337") != NULL); + ASSERT_NULL(strstr(uv_strerror_r(UV_EINVAL, buf, sizeof(buf)), "Success")); + ASSERT_NOT_NULL(strstr(uv_strerror_r(1337, buf, sizeof(buf)), "1337")); + ASSERT_NOT_NULL(strstr(uv_strerror_r(-1337, buf, sizeof(buf)), "-1337")); return 0; } diff --git a/deps/libuv/test/test-fs-copyfile.c b/deps/libuv/test/test-fs-copyfile.c index c785a4b5..fa00fe4e 100644 --- a/deps/libuv/test/test-fs-copyfile.c +++ b/deps/libuv/test/test-fs-copyfile.c @@ -96,6 +96,9 @@ static void touch_file(const char* name, unsigned int size) { TEST_IMPL(fs_copyfile) { +#if defined(__ASAN__) + RETURN_SKIP("Test does not currently work in ASAN"); +#endif const char src[] = "test_file_src"; uv_loop_t* loop; uv_fs_t req; diff --git a/deps/libuv/test/test-fs-event.c b/deps/libuv/test/test-fs-event.c index 28a6a1eb..ec163868 100644 --- a/deps/libuv/test/test-fs-event.c +++ b/deps/libuv/test/test-fs-event.c @@ -118,7 +118,7 @@ static void touch_file(const char* name) { } static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } @@ -337,7 +337,7 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename, static void timer_cb_close_handle(uv_timer_t* timer) { uv_handle_t* handle; - ASSERT(timer != NULL); + ASSERT_NOT_NULL(timer); handle = timer->data; uv_close((uv_handle_t*)timer, NULL); @@ -673,6 +673,9 @@ TEST_IMPL(fs_event_watch_file_exact_path) { TEST_IMPL(fs_event_watch_file_twice) { #if defined(NO_FS_EVENTS) RETURN_SKIP(NO_FS_EVENTS); +#endif +#if defined(__ASAN__) + RETURN_SKIP("Test does not currently work in ASAN"); #endif const char path[] = "test/fixtures/empty_file"; uv_fs_event_t watchers[2]; @@ -755,7 +758,7 @@ TEST_IMPL(fs_event_watch_file_root_dir) { const char* sys_drive = getenv("SystemDrive"); char path[] = "\\\\?\\X:\\bootsect.bak"; - ASSERT(sys_drive != NULL); + ASSERT_NOT_NULL(sys_drive); strncpy(path + sizeof("\\\\?\\") - 1, sys_drive, 1); loop = uv_default_loop(); @@ -1069,7 +1072,7 @@ static void timer_cb_nop(uv_timer_t* handle) { } static void fs_event_error_report_close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; /* handle is allocated on-stack, no need to free it */ diff --git a/deps/libuv/test/test-fs-poll.c b/deps/libuv/test/test-fs-poll.c index 9dfd5fdd..76fe6fc3 100644 --- a/deps/libuv/test/test-fs-poll.c +++ b/deps/libuv/test/test-fs-poll.c @@ -105,8 +105,8 @@ static void poll_cb(uv_fs_poll_t* handle, ASSERT(handle == &poll_handle); ASSERT(1 == uv_is_active((uv_handle_t*) handle)); - ASSERT(prev != NULL); - ASSERT(curr != NULL); + ASSERT_NOT_NULL(prev); + ASSERT_NOT_NULL(curr); switch (poll_cb_called++) { case 0: diff --git a/deps/libuv/test/test-fs-readdir.c b/deps/libuv/test/test-fs-readdir.c index 5efc853c..41e1d373 100644 --- a/deps/libuv/test/test-fs-readdir.c +++ b/deps/libuv/test/test-fs-readdir.c @@ -77,7 +77,7 @@ static void empty_opendir_cb(uv_fs_t* req) { ASSERT(req == &opendir_req); ASSERT(req->fs_type == UV_FS_OPENDIR); ASSERT(req->result == 0); - ASSERT(req->ptr != NULL); + ASSERT_NOT_NULL(req->ptr); dir = req->ptr; dir->dirents = dirents; dir->nentries = ARRAY_SIZE(dirents); @@ -118,7 +118,7 @@ TEST_IMPL(fs_readdir_empty_dir) { ASSERT(r == 0); ASSERT(opendir_req.fs_type == UV_FS_OPENDIR); ASSERT(opendir_req.result == 0); - ASSERT(opendir_req.ptr != NULL); + ASSERT_NOT_NULL(opendir_req.ptr); dir = opendir_req.ptr; uv_fs_req_cleanup(&opendir_req); @@ -171,7 +171,7 @@ static void non_existing_opendir_cb(uv_fs_t* req) { ASSERT(req == &opendir_req); ASSERT(req->fs_type == UV_FS_OPENDIR); ASSERT(req->result == UV_ENOENT); - ASSERT(req->ptr == NULL); + ASSERT_NULL(req->ptr); uv_fs_req_cleanup(req); ++non_existing_opendir_cb_count; @@ -191,7 +191,7 @@ TEST_IMPL(fs_readdir_non_existing_dir) { ASSERT(r == UV_ENOENT); ASSERT(opendir_req.fs_type == UV_FS_OPENDIR); ASSERT(opendir_req.result == UV_ENOENT); - ASSERT(opendir_req.ptr == NULL); + ASSERT_NULL(opendir_req.ptr); uv_fs_req_cleanup(&opendir_req); /* Fill the req to ensure that required fields are cleaned up. */ @@ -223,13 +223,16 @@ static void file_opendir_cb(uv_fs_t* req) { ASSERT(req == &opendir_req); ASSERT(req->fs_type == UV_FS_OPENDIR); ASSERT(req->result == UV_ENOTDIR); - ASSERT(req->ptr == NULL); + ASSERT_NULL(req->ptr); uv_fs_req_cleanup(req); ++file_opendir_cb_count; } TEST_IMPL(fs_readdir_file) { +#if defined(__ASAN__) + RETURN_SKIP("Test does not currently work in ASAN"); +#endif const char* path; int r; @@ -244,7 +247,7 @@ TEST_IMPL(fs_readdir_file) { ASSERT(r == UV_ENOTDIR); ASSERT(opendir_req.fs_type == UV_FS_OPENDIR); ASSERT(opendir_req.result == UV_ENOTDIR); - ASSERT(opendir_req.ptr == NULL); + ASSERT_NULL(opendir_req.ptr); uv_fs_req_cleanup(&opendir_req); @@ -326,7 +329,7 @@ static void non_empty_opendir_cb(uv_fs_t* req) { ASSERT(req == &opendir_req); ASSERT(req->fs_type == UV_FS_OPENDIR); ASSERT(req->result == 0); - ASSERT(req->ptr != NULL); + ASSERT_NOT_NULL(req->ptr); dir = req->ptr; dir->dirents = dirents; @@ -400,7 +403,7 @@ TEST_IMPL(fs_readdir_non_empty_dir) { ASSERT(r == 0); ASSERT(opendir_req.fs_type == UV_FS_OPENDIR); ASSERT(opendir_req.result == 0); - ASSERT(opendir_req.ptr != NULL); + ASSERT_NOT_NULL(opendir_req.ptr); entries_count = 0; dir = opendir_req.ptr; diff --git a/deps/libuv/test/test-fs.c b/deps/libuv/test/test-fs.c index 63189d01..034c971d 100644 --- a/deps/libuv/test/test-fs.c +++ b/deps/libuv/test/test-fs.c @@ -343,7 +343,7 @@ static void statfs_cb(uv_fs_t* req) { ASSERT(req->fs_type == UV_FS_STATFS); ASSERT(req->result == 0); - ASSERT(req->ptr != NULL); + ASSERT_NOT_NULL(req->ptr); stats = req->ptr; #if defined(_WIN32) || defined(__sun) || defined(_AIX) || defined(__MVS__) || \ @@ -366,7 +366,7 @@ static void statfs_cb(uv_fs_t* req) { ASSERT(stats->f_ffree <= stats->f_files); #endif uv_fs_req_cleanup(req); - ASSERT(req->ptr == NULL); + ASSERT_NULL(req->ptr); statfs_cb_count++; } @@ -630,7 +630,7 @@ static void empty_scandir_cb(uv_fs_t* req) { ASSERT(req == &scandir_req); ASSERT(req->fs_type == UV_FS_SCANDIR); ASSERT(req->result == 0); - ASSERT(req->ptr == NULL); + ASSERT_NULL(req->ptr); ASSERT(UV_EOF == uv_fs_scandir_next(req, &dent)); uv_fs_req_cleanup(req); scandir_cb_count++; @@ -642,7 +642,7 @@ static void non_existent_scandir_cb(uv_fs_t* req) { ASSERT(req == &scandir_req); ASSERT(req->fs_type == UV_FS_SCANDIR); ASSERT(req->result == UV_ENOENT); - ASSERT(req->ptr == NULL); + ASSERT_NULL(req->ptr); ASSERT(UV_ENOENT == uv_fs_scandir_next(req, &dent)); uv_fs_req_cleanup(req); scandir_cb_count++; @@ -653,7 +653,7 @@ static void file_scandir_cb(uv_fs_t* req) { ASSERT(req == &scandir_req); ASSERT(req->fs_type == UV_FS_SCANDIR); ASSERT(req->result == UV_ENOTDIR); - ASSERT(req->ptr == NULL); + ASSERT_NULL(req->ptr); uv_fs_req_cleanup(req); scandir_cb_count++; } @@ -673,7 +673,7 @@ static void stat_cb(uv_fs_t* req) { static void sendfile_cb(uv_fs_t* req) { ASSERT(req == &sendfile_req); ASSERT(req->fs_type == UV_FS_SENDFILE); - ASSERT(req->result == 65546); + ASSERT(req->result == 65545); sendfile_cb_count++; uv_fs_req_cleanup(req); } @@ -816,13 +816,44 @@ static void check_utime(const char* path, else r = uv_fs_stat(loop, &req, path, NULL); - ASSERT(r == 0); + ASSERT_EQ(r, 0); - ASSERT(req.result == 0); + ASSERT_EQ(req.result, 0); s = &req.statbuf; - ASSERT(s->st_atim.tv_sec + (s->st_atim.tv_nsec / 1000000000.0) == atime); - ASSERT(s->st_mtim.tv_sec + (s->st_mtim.tv_nsec / 1000000000.0) == mtime); + if (s->st_atim.tv_nsec == 0 && s->st_mtim.tv_nsec == 0) { + /* + * Test sub-second timestamps only when supported (such as Windows with + * NTFS). Some other platforms support sub-second timestamps, but that + * support is filesystem-dependent. Notably OS X (HFS Plus) does NOT + * support sub-second timestamps. But kernels may round or truncate in + * either direction, so we may accept either possible answer. + */ +#ifdef _WIN32 + ASSERT_DOUBLE_EQ(atime, (long) atime); + ASSERT_DOUBLE_EQ(mtime, (long) atime); +#endif + if (atime > 0 || (long) atime == atime) + ASSERT_EQ(s->st_atim.tv_sec, (long) atime); + if (mtime > 0 || (long) mtime == mtime) + ASSERT_EQ(s->st_mtim.tv_sec, (long) mtime); + ASSERT_GE(s->st_atim.tv_sec, (long) atime - 1); + ASSERT_GE(s->st_mtim.tv_sec, (long) mtime - 1); + ASSERT_LE(s->st_atim.tv_sec, (long) atime); + ASSERT_LE(s->st_mtim.tv_sec, (long) mtime); + } else { + double st_atim; + double st_mtim; +#ifndef __APPLE__ + /* TODO(vtjnash): would it be better to normalize this? */ + ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0); + ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0); +#endif + st_atim = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9; + st_mtim = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9; + ASSERT_DOUBLE_EQ(st_atim, atime); + ASSERT_DOUBLE_EQ(st_mtim, mtime); + } uv_fs_req_cleanup(&req); } @@ -1159,6 +1190,8 @@ TEST_IMPL(fs_async_dir) { static int test_sendfile(void (*setup)(int), uv_fs_cb cb, off_t expected_size) { int f, r; struct stat s1, s2; + uv_fs_t req; + char buf1[1]; loop = uv_default_loop(); @@ -1188,7 +1221,7 @@ static int test_sendfile(void (*setup)(int), uv_fs_cb cb, off_t expected_size) { uv_fs_req_cleanup(&open_req2); r = uv_fs_sendfile(loop, &sendfile_req, open_req2.result, open_req1.result, - 0, 131072, cb); + 1, 131072, cb); ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); @@ -1203,9 +1236,26 @@ static int test_sendfile(void (*setup)(int), uv_fs_cb cb, off_t expected_size) { ASSERT(0 == stat("test_file", &s1)); ASSERT(0 == stat("test_file2", &s2)); - ASSERT(s1.st_size == s2.st_size); ASSERT(s2.st_size == expected_size); + if (expected_size > 0) { + ASSERT_UINT64_EQ(s1.st_size, s2.st_size + 1); + r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDWR, 0, NULL); + ASSERT(r >= 0); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + memset(buf1, 0, sizeof(buf1)); + iov = uv_buf_init(buf1, sizeof(buf1)); + r = uv_fs_read(NULL, &req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r >= 0); + ASSERT(req.result >= 0); + ASSERT_EQ(buf1[0], 'e'); /* 'e' from begin */ + uv_fs_req_cleanup(&req); + } else { + ASSERT_UINT64_EQ(s1.st_size, s2.st_size); + } + /* Cleanup. */ unlink("test_file"); unlink("test_file2"); @@ -1223,7 +1273,7 @@ static void sendfile_setup(int f) { TEST_IMPL(fs_async_sendfile) { - return test_sendfile(sendfile_setup, sendfile_cb, 65546); + return test_sendfile(sendfile_setup, sendfile_cb, 65545); } @@ -1403,7 +1453,8 @@ TEST_IMPL(fs_fstat) { ASSERT(s->st_mtim.tv_nsec == t.st_mtimespec.tv_nsec); ASSERT(s->st_ctim.tv_sec == t.st_ctimespec.tv_sec); ASSERT(s->st_ctim.tv_nsec == t.st_ctimespec.tv_nsec); -#elif defined(_AIX) +#elif defined(_AIX) || \ + defined(__MVS__) ASSERT(s->st_atim.tv_sec == t.st_atime); ASSERT(s->st_atim.tv_nsec == 0); ASSERT(s->st_mtim.tv_sec == t.st_mtime); @@ -1961,12 +2012,12 @@ TEST_IMPL(fs_readlink) { ASSERT(0 == uv_fs_readlink(loop, &req, "no_such_file", dummy_cb)); ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); ASSERT(dummy_cb_count == 1); - ASSERT(req.ptr == NULL); + ASSERT_NULL(req.ptr); ASSERT(req.result == UV_ENOENT); uv_fs_req_cleanup(&req); ASSERT(UV_ENOENT == uv_fs_readlink(NULL, &req, "no_such_file", NULL)); - ASSERT(req.ptr == NULL); + ASSERT_NULL(req.ptr); ASSERT(req.result == UV_ENOENT); uv_fs_req_cleanup(&req); @@ -1982,7 +2033,7 @@ TEST_IMPL(fs_realpath) { ASSERT(0 == uv_fs_realpath(loop, &req, "no_such_file", dummy_cb)); ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); ASSERT(dummy_cb_count == 1); - ASSERT(req.ptr == NULL); + ASSERT_NULL(req.ptr); #ifdef _WIN32 /* * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() @@ -1996,7 +2047,7 @@ TEST_IMPL(fs_realpath) { uv_fs_req_cleanup(&req); ASSERT(UV_ENOENT == uv_fs_realpath(NULL, &req, "no_such_file", NULL)); - ASSERT(req.ptr == NULL); + ASSERT_NULL(req.ptr); ASSERT(req.result == UV_ENOENT); uv_fs_req_cleanup(&req); @@ -2523,29 +2574,16 @@ TEST_IMPL(fs_utime) { uv_fs_req_cleanup(&req); uv_fs_close(loop, &req, r, NULL); - atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ - - /* - * Test sub-second timestamps only on Windows (assuming NTFS). Some other - * platforms support sub-second timestamps, but that support is filesystem- - * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps. - */ -#ifdef _WIN32 - mtime += 0.444; /* 1982-09-10 11:22:33.444 */ -#endif + atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */ r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); - r = uv_fs_stat(NULL, &req, path, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); check_utime(path, atime, mtime, /* test_lutime */ 0); - uv_fs_req_cleanup(&req); - atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ + atime = mtime = 1291404900.25; /* 2010-12-03 20:35:00.25 - mees <3 */ checkme.path = path; checkme.atime = atime; checkme.mtime = mtime; @@ -2565,6 +2603,45 @@ TEST_IMPL(fs_utime) { } +TEST_IMPL(fs_utime_round) { + const char path[] = "test_file"; + double atime; + double mtime; + uv_fs_t req; + int r; + + loop = uv_default_loop(); + unlink(path); + r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); + ASSERT_GE(r, 0); + ASSERT_GE(req.result, 0); + uv_fs_req_cleanup(&req); + ASSERT_EQ(0, uv_fs_close(loop, &req, r, NULL)); + + atime = mtime = -14245440.25; /* 1969-07-20T02:56:00.25Z */ + + r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL); +#if !defined(__linux__) && \ + !defined(_WIN32) && \ + !defined(__APPLE__) && \ + !defined(__FreeBSD__) && \ + !defined(__sun) + if (r != 0) { + ASSERT_EQ(r, UV_EINVAL); + RETURN_SKIP("utime on some OS (z/OS, IBM i PASE, AIX) or filesystems may reject pre-epoch timestamps"); + } +#endif + ASSERT_EQ(0, r); + ASSERT_EQ(0, req.result); + uv_fs_req_cleanup(&req); + check_utime(path, atime, mtime, /* test_lutime */ 0); + unlink(path); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + #ifdef _WIN32 TEST_IMPL(fs_stat_root) { int r; @@ -2618,16 +2695,7 @@ TEST_IMPL(fs_futime) { uv_fs_req_cleanup(&req); uv_fs_close(loop, &req, r, NULL); - atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ - - /* - * Test sub-second timestamps only on Windows (assuming NTFS). Some other - * platforms support sub-second timestamps, but that support is filesystem- - * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps. - */ -#ifdef _WIN32 - mtime += 0.444; /* 1982-09-10 11:22:33.444 */ -#endif + atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */ r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL); ASSERT(r >= 0); @@ -2645,11 +2713,7 @@ TEST_IMPL(fs_futime) { #endif uv_fs_req_cleanup(&req); - r = uv_fs_stat(NULL, &req, path, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); check_utime(path, atime, mtime, /* test_lutime */ 0); - uv_fs_req_cleanup(&req); atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ @@ -2708,11 +2772,7 @@ TEST_IMPL(fs_lutime) { uv_fs_req_cleanup(&req); /* Test the synchronous version. */ - atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ - -#ifdef _WIN32 - mtime += 0.444; /* 1982-09-10 11:22:33.444 */ -#endif + atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */ checkme.atime = atime; checkme.mtime = mtime; @@ -2784,7 +2844,7 @@ TEST_IMPL(fs_scandir_empty_dir) { r = uv_fs_scandir(NULL, &req, path, 0, NULL); ASSERT(r == 0); ASSERT(req.result == 0); - ASSERT(req.ptr == NULL); + ASSERT_NULL(req.ptr); ASSERT(UV_EOF == uv_fs_scandir_next(&req, &dent)); uv_fs_req_cleanup(&req); @@ -2821,7 +2881,7 @@ TEST_IMPL(fs_scandir_non_existent_dir) { r = uv_fs_scandir(NULL, &req, path, 0, NULL); ASSERT(r == UV_ENOENT); ASSERT(req.result == UV_ENOENT); - ASSERT(req.ptr == NULL); + ASSERT_NULL(req.ptr); ASSERT(UV_ENOENT == uv_fs_scandir_next(&req, &dent)); uv_fs_req_cleanup(&req); @@ -2837,6 +2897,9 @@ TEST_IMPL(fs_scandir_non_existent_dir) { } TEST_IMPL(fs_scandir_file) { +#if defined(__ASAN__) + RETURN_SKIP("Test does not currently work in ASAN"); +#endif const char* path; int r; @@ -2870,7 +2933,7 @@ TEST_IMPL(fs_open_dir) { r = uv_fs_open(NULL, &req, path, O_RDONLY, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); - ASSERT(req.ptr == NULL); + ASSERT_NULL(req.ptr); file = r; uv_fs_req_cleanup(&req); @@ -3083,6 +3146,9 @@ static void fs_read_bufs(int add_flags) { uv_fs_req_cleanup(&close_req); } TEST_IMPL(fs_read_bufs) { +#if defined(__ASAN__) + RETURN_SKIP("Test does not currently work in ASAN"); +#endif fs_read_bufs(0); fs_read_bufs(UV_FS_O_FILEMAP); @@ -3267,7 +3333,7 @@ static void fs_write_alotof_bufs(int add_flags) { loop = uv_default_loop(); iovs = malloc(sizeof(*iovs) * iovcount); - ASSERT(iovs != NULL); + ASSERT_NOT_NULL(iovs); iovmax = uv_test_getiovmax(); r = uv_fs_open(NULL, @@ -3296,7 +3362,7 @@ static void fs_write_alotof_bufs(int add_flags) { /* Read the strings back to separate buffers. */ buffer = malloc(sizeof(test_buf) * iovcount); - ASSERT(buffer != NULL); + ASSERT_NOT_NULL(buffer); for (index = 0; index < iovcount; ++index) iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), @@ -3379,7 +3445,7 @@ static void fs_write_alotof_bufs_with_offset(int add_flags) { loop = uv_default_loop(); iovs = malloc(sizeof(*iovs) * iovcount); - ASSERT(iovs != NULL); + ASSERT_NOT_NULL(iovs); iovmax = uv_test_getiovmax(); r = uv_fs_open(NULL, @@ -3415,7 +3481,7 @@ static void fs_write_alotof_bufs_with_offset(int add_flags) { /* Read the strings back to separate buffers. */ buffer = malloc(sizeof(test_buf) * iovcount); - ASSERT(buffer != NULL); + ASSERT_NOT_NULL(buffer); for (index = 0; index < iovcount; ++index) iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), @@ -3611,16 +3677,16 @@ static void test_fs_partial(int doread) { iovcount = 54321; iovs = malloc(sizeof(*iovs) * iovcount); - ASSERT(iovs != NULL); + ASSERT_NOT_NULL(iovs); ctx.pid = pthread_self(); ctx.doread = doread; ctx.interval = 1000; ctx.size = sizeof(test_buf) * iovcount; ctx.data = malloc(ctx.size); - ASSERT(ctx.data != NULL); + ASSERT_NOT_NULL(ctx.data); buffer = malloc(ctx.size); - ASSERT(buffer != NULL); + ASSERT_NOT_NULL(buffer); for (index = 0; index < iovcount; ++index) iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), sizeof(test_buf)); @@ -3708,15 +3774,15 @@ TEST_IMPL(fs_read_write_null_arguments) { /* Validate some memory management on failed input validation before sending fs work to the thread pool. */ ASSERT(r == UV_EINVAL); - ASSERT(write_req.path == NULL); - ASSERT(write_req.ptr == NULL); + ASSERT_NULL(write_req.path); + ASSERT_NULL(write_req.ptr); #ifdef _WIN32 - ASSERT(write_req.file.pathw == NULL); - ASSERT(write_req.fs.info.new_pathw == NULL); - ASSERT(write_req.fs.info.bufs == NULL); + ASSERT_NULL(write_req.file.pathw); + ASSERT_NULL(write_req.fs.info.new_pathw); + ASSERT_NULL(write_req.fs.info.bufs); #else - ASSERT(write_req.new_path == NULL); - ASSERT(write_req.bufs == NULL); + ASSERT_NULL(write_req.new_path); + ASSERT_NULL(write_req.bufs); #endif uv_fs_req_cleanup(&write_req); @@ -4372,6 +4438,7 @@ TEST_IMPL(fs_invalid_mkdir_name) { loop = uv_default_loop(); r = uv_fs_mkdir(loop, &req, "invalid>", 0, NULL); ASSERT(r == UV_EINVAL); + ASSERT_EQ(UV_EINVAL, uv_fs_mkdir(loop, &req, "test:lol", 0, NULL)); return 0; } diff --git a/deps/libuv/test/test-get-currentexe.c b/deps/libuv/test/test-get-currentexe.c index 8eba7b73..dc239cc8 100644 --- a/deps/libuv/test/test-get-currentexe.c +++ b/deps/libuv/test/test-get-currentexe.c @@ -49,7 +49,7 @@ TEST_IMPL(get_currentexe) { #ifdef _WIN32 snprintf(path, sizeof(path), "%s", executable_path); #else - ASSERT(NULL != realpath(executable_path, path)); + ASSERT_NOT_NULL(realpath(executable_path, path)); #endif match = strstr(buffer, path); diff --git a/deps/libuv/test/test-get-passwd.c b/deps/libuv/test/test-get-passwd.c index abe8be36..865c07d6 100644 --- a/deps/libuv/test/test-get-passwd.c +++ b/deps/libuv/test/test-get-passwd.c @@ -40,7 +40,7 @@ TEST_IMPL(get_passwd) { ASSERT(len > 0); #ifdef _WIN32 - ASSERT(pwd.shell == NULL); + ASSERT_NULL(pwd.shell); #else len = strlen(pwd.shell); # ifndef __PASE__ @@ -74,16 +74,16 @@ TEST_IMPL(get_passwd) { /* Test uv_os_free_passwd() */ uv_os_free_passwd(&pwd); - ASSERT(pwd.username == NULL); - ASSERT(pwd.shell == NULL); - ASSERT(pwd.homedir == NULL); + ASSERT_NULL(pwd.username); + ASSERT_NULL(pwd.shell); + ASSERT_NULL(pwd.homedir); /* Test a double free */ uv_os_free_passwd(&pwd); - ASSERT(pwd.username == NULL); - ASSERT(pwd.shell == NULL); - ASSERT(pwd.homedir == NULL); + ASSERT_NULL(pwd.username); + ASSERT_NULL(pwd.shell); + ASSERT_NULL(pwd.homedir); /* Test invalid input */ r = uv_os_get_passwd(NULL); diff --git a/deps/libuv/test/test-getaddrinfo.c b/deps/libuv/test/test-getaddrinfo.c index 628e4d13..d0b6a505 100644 --- a/deps/libuv/test/test-getaddrinfo.c +++ b/deps/libuv/test/test-getaddrinfo.c @@ -42,7 +42,7 @@ static void getaddrinfo_fail_cb(uv_getaddrinfo_t* req, ASSERT(fail_cb_called == 0); ASSERT(status < 0); - ASSERT(res == NULL); + ASSERT_NULL(res); uv_freeaddrinfo(res); /* Should not crash. */ fail_cb_called++; } @@ -100,7 +100,7 @@ TEST_IMPL(getaddrinfo_fail) { ASSERT(0 == uv_getaddrinfo(uv_default_loop(), &req, getaddrinfo_fail_cb, - "xyzzy.xyzzy.xyzzy.", + "example.invalid.", NULL, NULL)); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); @@ -122,7 +122,7 @@ TEST_IMPL(getaddrinfo_fail_sync) { ASSERT(0 > uv_getaddrinfo(uv_default_loop(), &req, NULL, - "xyzzy.xyzzy.xyzzy.", + "example.invalid.", NULL, NULL)); uv_freeaddrinfo(req.addrinfo); @@ -191,7 +191,7 @@ TEST_IMPL(getaddrinfo_concurrent) { callback_counts[i] = 0; data = (int*)malloc(sizeof(int)); - ASSERT(data != NULL); + ASSERT_NOT_NULL(data); *data = i; getaddrinfo_handles[i].data = data; diff --git a/deps/libuv/test/test-getnameinfo.c b/deps/libuv/test/test-getnameinfo.c index eb326451..2bfedd3a 100644 --- a/deps/libuv/test/test-getnameinfo.c +++ b/deps/libuv/test/test-getnameinfo.c @@ -38,10 +38,10 @@ static void getnameinfo_req(uv_getnameinfo_t* handle, int status, const char* hostname, const char* service) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); ASSERT(status == 0); - ASSERT(hostname != NULL); - ASSERT(service != NULL); + ASSERT_NOT_NULL(hostname); + ASSERT_NOT_NULL(service); } diff --git a/deps/libuv/test/test-getsockname.c b/deps/libuv/test/test-getsockname.c index 565c17fe..7c77fcb0 100644 --- a/deps/libuv/test/test-getsockname.c +++ b/deps/libuv/test/test-getsockname.c @@ -116,7 +116,7 @@ static void on_connection(uv_stream_t* server, int status) { ASSERT(status == 0); handle = malloc(sizeof(*handle)); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); r = uv_tcp_init(loop, handle); ASSERT(r == 0); diff --git a/deps/libuv/test/test-getters-setters.c b/deps/libuv/test/test-getters-setters.c index 42c9dcaf..2a37122d 100644 --- a/deps/libuv/test/test-getters-setters.c +++ b/deps/libuv/test/test-getters-setters.c @@ -33,9 +33,9 @@ TEST_IMPL(handle_type_name) { ASSERT(strcmp(uv_handle_type_name(UV_NAMED_PIPE), "pipe") == 0); ASSERT(strcmp(uv_handle_type_name(UV_UDP), "udp") == 0); ASSERT(strcmp(uv_handle_type_name(UV_FILE), "file") == 0); - ASSERT(uv_handle_type_name(UV_HANDLE_TYPE_MAX) == NULL); - ASSERT(uv_handle_type_name(UV_HANDLE_TYPE_MAX + 1) == NULL); - ASSERT(uv_handle_type_name(UV_UNKNOWN_HANDLE) == NULL); + ASSERT_NULL(uv_handle_type_name(UV_HANDLE_TYPE_MAX)); + ASSERT_NULL(uv_handle_type_name(UV_HANDLE_TYPE_MAX + 1)); + ASSERT_NULL(uv_handle_type_name(UV_UNKNOWN_HANDLE)); return 0; } @@ -44,9 +44,9 @@ TEST_IMPL(req_type_name) { ASSERT(strcmp(uv_req_type_name(UV_REQ), "req") == 0); ASSERT(strcmp(uv_req_type_name(UV_UDP_SEND), "udp_send") == 0); ASSERT(strcmp(uv_req_type_name(UV_WORK), "work") == 0); - ASSERT(uv_req_type_name(UV_REQ_TYPE_MAX) == NULL); - ASSERT(uv_req_type_name(UV_REQ_TYPE_MAX + 1) == NULL); - ASSERT(uv_req_type_name(UV_UNKNOWN_REQ) == NULL); + ASSERT_NULL(uv_req_type_name(UV_REQ_TYPE_MAX)); + ASSERT_NULL(uv_req_type_name(UV_REQ_TYPE_MAX + 1)); + ASSERT_NULL(uv_req_type_name(UV_UNKNOWN_REQ)); return 0; } @@ -58,7 +58,7 @@ TEST_IMPL(getters_setters) { int r; loop = malloc(uv_loop_size()); - ASSERT(loop != NULL); + ASSERT_NOT_NULL(loop); r = uv_loop_init(loop); ASSERT(r == 0); diff --git a/deps/libuv/test/test-idna.c b/deps/libuv/test/test-idna.c index b76853cb..f4fad965 100644 --- a/deps/libuv/test/test-idna.c +++ b/deps/libuv/test/test-idna.c @@ -96,6 +96,25 @@ TEST_IMPL(utf8_decode1) { return 0; } +TEST_IMPL(utf8_decode1_overrun) { + const char* p; + char b[1]; + + /* Single byte. */ + p = b; + b[0] = 0x7F; + ASSERT_EQ(0x7F, uv__utf8_decode1(&p, b + 1)); + ASSERT_EQ(p, b + 1); + + /* Multi-byte. */ + p = b; + b[0] = 0xC0; + ASSERT_EQ((unsigned) -1, uv__utf8_decode1(&p, b + 1)); + ASSERT_EQ(p, b + 1); + + return 0; +} + /* Doesn't work on z/OS because that platform uses EBCDIC, not ASCII. */ #ifndef __MVS__ diff --git a/deps/libuv/test/test-ipc-heavy-traffic-deadlock-bug.c b/deps/libuv/test/test-ipc-heavy-traffic-deadlock-bug.c index 753fb7b7..89b977d2 100644 --- a/deps/libuv/test/test-ipc-heavy-traffic-deadlock-bug.c +++ b/deps/libuv/test/test-ipc-heavy-traffic-deadlock-bug.c @@ -66,7 +66,7 @@ static void do_write(uv_stream_t* handle) { int r; write_info = malloc(sizeof *write_info); - ASSERT(write_info != NULL); + ASSERT_NOT_NULL(write_info); for (i = 0; i < BUFFERS_PER_WRITE; i++) { memset(&write_info->buffers[i], BUFFER_CONTENT, BUFFER_SIZE); diff --git a/deps/libuv/test/test-ipc.c b/deps/libuv/test/test-ipc.c index 39ef4f11..68a0e1bb 100644 --- a/deps/libuv/test/test-ipc.c +++ b/deps/libuv/test/test-ipc.c @@ -203,7 +203,7 @@ static void on_read(uv_stream_t* handle, /* Make sure that the expected data is correctly multiplexed. */ ASSERT_MEM_EQ("hello\n", buf->base, nread); - outbuf = uv_buf_init("world\n", 6); + outbuf = uv_buf_init("foobar\n", 7); r = uv_write(&write_req, (uv_stream_t*)pipe, &outbuf, 1, NULL); ASSERT_EQ(r, 0); @@ -693,6 +693,11 @@ static void ipc_on_connection(uv_stream_t* server, int status) { } +static void close_and_free_cb(uv_handle_t* handle) { + close_cb_called++; + free(handle); +} + static void ipc_on_connection_tcp_conn(uv_stream_t* server, int status) { int r; uv_buf_t buf; @@ -721,7 +726,7 @@ static void ipc_on_connection_tcp_conn(uv_stream_t* server, int status) { on_tcp_child_process_read); ASSERT_EQ(r, 0); - uv_close((uv_handle_t*)conn, close_cb); + uv_close((uv_handle_t*)conn, close_and_free_cb); } diff --git a/deps/libuv/test/test-list.h b/deps/libuv/test/test-list.h index 52b17a69..59b95da9 100644 --- a/deps/libuv/test/test-list.h +++ b/deps/libuv/test/test-list.h @@ -116,7 +116,8 @@ TEST_DECLARE (tcp_open_bound) TEST_DECLARE (tcp_open_connected) TEST_DECLARE (tcp_connect_error_after_write) TEST_DECLARE (tcp_shutdown_after_write) -TEST_DECLARE (tcp_bind_error_addrinuse) +TEST_DECLARE (tcp_bind_error_addrinuse_connect) +TEST_DECLARE (tcp_bind_error_addrinuse_listen) TEST_DECLARE (tcp_bind_error_addrnotavail_1) TEST_DECLARE (tcp_bind_error_addrnotavail_2) TEST_DECLARE (tcp_bind_error_fault) @@ -205,6 +206,7 @@ TEST_DECLARE (connection_fail_doesnt_auto_close) TEST_DECLARE (shutdown_close_tcp) TEST_DECLARE (shutdown_close_pipe) TEST_DECLARE (shutdown_eof) +TEST_DECLARE (shutdown_simultaneous) TEST_DECLARE (shutdown_twice) TEST_DECLARE (callback_stack) TEST_DECLARE (env_vars) @@ -359,6 +361,7 @@ TEST_DECLARE (fs_open_flags) TEST_DECLARE (fs_fd_hash) #endif TEST_DECLARE (fs_utime) +TEST_DECLARE (fs_utime_round) TEST_DECLARE (fs_futime) TEST_DECLARE (fs_lutime) TEST_DECLARE (fs_file_open_append) @@ -451,12 +454,16 @@ TEST_DECLARE (poll_nested_epoll) #ifdef UV_HAVE_KQUEUE TEST_DECLARE (poll_nested_kqueue) #endif +TEST_DECLARE (poll_multiple_handles) TEST_DECLARE (ip4_addr) TEST_DECLARE (ip6_addr_link_local) TEST_DECLARE (poll_close_doesnt_corrupt_stack) TEST_DECLARE (poll_closesocket) +TEST_DECLARE (close_fd) +TEST_DECLARE (closed_fd_events) +TEST_DECLARE (spawn_fs_open) #ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) #if !defined(USING_UV_SHARED) @@ -471,8 +478,6 @@ TEST_DECLARE (ipc_listen_after_bind_twice) TEST_DECLARE (win32_signum_number) #else TEST_DECLARE (emfile) -TEST_DECLARE (close_fd) -TEST_DECLARE (spawn_fs_open) TEST_DECLARE (spawn_setuid_setgid) TEST_DECLARE (we_get_signal) TEST_DECLARE (we_get_signals) @@ -481,7 +486,6 @@ 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__ TEST_DECLARE (osx_select) @@ -501,6 +505,10 @@ TEST_DECLARE (handle_type_name) TEST_DECLARE (req_type_name) TEST_DECLARE (getters_setters) +TEST_DECLARE (not_writable_after_shutdown) +TEST_DECLARE (not_readable_nor_writable_on_read_error) +TEST_DECLARE (not_readable_on_eof) + #ifndef _WIN32 TEST_DECLARE (fork_timer) TEST_DECLARE (fork_socketpair) @@ -521,6 +529,7 @@ TEST_DECLARE (fork_threadpool_queue_work_simple) TEST_DECLARE (idna_toascii) TEST_DECLARE (utf8_decode1) +TEST_DECLARE (utf8_decode1_overrun) TEST_DECLARE (uname) TEST_DECLARE (metrics_idle_time) @@ -567,7 +576,8 @@ TASK_LIST_START #ifndef _WIN32 TEST_ENTRY (pipe_close_stdout_read_stdin) #endif - TEST_ENTRY (pipe_set_non_blocking) + /* Seems to be either about 0.5s or 5s, depending on the OS. */ + TEST_ENTRY_CUSTOM (pipe_set_non_blocking, 0, 0, 20000) TEST_ENTRY (pipe_set_chmod) TEST_ENTRY (tty) #ifdef _WIN32 @@ -671,7 +681,13 @@ TASK_LIST_START TEST_HELPER (tcp_shutdown_after_write, tcp4_echo_server) TEST_ENTRY (tcp_connect_error_after_write) - TEST_ENTRY (tcp_bind_error_addrinuse) + TEST_ENTRY (tcp_bind_error_addrinuse_connect) + /* tcp4_echo_server steals the port. It needs to be a separate process + * because libuv sets setsockopt(SO_REUSEADDR) that lets you steal an + * existing bind if it originates from the same process. + */ + TEST_HELPER (tcp_bind_error_addrinuse_connect, tcp4_echo_server) + TEST_ENTRY (tcp_bind_error_addrinuse_listen) TEST_ENTRY (tcp_bind_error_addrnotavail_1) TEST_ENTRY (tcp_bind_error_addrnotavail_2) TEST_ENTRY (tcp_bind_error_fault) @@ -769,6 +785,9 @@ TASK_LIST_START TEST_ENTRY (shutdown_eof) TEST_HELPER (shutdown_eof, tcp4_echo_server) + TEST_ENTRY (shutdown_simultaneous) + TEST_HELPER (shutdown_simultaneous, tcp4_echo_server) + TEST_ENTRY (shutdown_twice) TEST_HELPER (shutdown_twice, tcp4_echo_server) @@ -894,6 +913,7 @@ TASK_LIST_START #ifdef UV_HAVE_KQUEUE TEST_ENTRY (poll_nested_kqueue) #endif + TEST_ENTRY (poll_multiple_handles) TEST_ENTRY (socket_buffer_size) @@ -935,6 +955,9 @@ TASK_LIST_START TEST_ENTRY (poll_close_doesnt_corrupt_stack) TEST_ENTRY (poll_closesocket) + TEST_ENTRY (close_fd) + TEST_ENTRY (closed_fd_events) + TEST_ENTRY (spawn_fs_open) #ifdef _WIN32 TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) #if !defined(USING_UV_SHARED) @@ -949,8 +972,6 @@ TASK_LIST_START TEST_ENTRY (win32_signum_number) #else TEST_ENTRY (emfile) - TEST_ENTRY (close_fd) - TEST_ENTRY (spawn_fs_open) TEST_ENTRY (spawn_setuid_setgid) TEST_ENTRY (we_get_signal) TEST_ENTRY (we_get_signals) @@ -959,7 +980,6 @@ TASK_LIST_START TEST_ENTRY (signal_multiple_loops) TEST_ENTRY (signal_pending_on_close) TEST_ENTRY (signal_close_loop_alive) - TEST_ENTRY (closed_fd_events) #endif #ifdef __APPLE__ @@ -988,6 +1008,7 @@ TASK_LIST_START #endif TEST_ENTRY (fs_chown) TEST_ENTRY (fs_utime) + TEST_ENTRY (fs_utime_round) TEST_ENTRY (fs_futime) TEST_ENTRY (fs_lutime) TEST_ENTRY (fs_readlink) @@ -1108,6 +1129,7 @@ TASK_LIST_START #endif TEST_ENTRY (utf8_decode1) + TEST_ENTRY (utf8_decode1_overrun) TEST_ENTRY (uname) /* Doesn't work on z/OS because that platform uses EBCDIC, not ASCII. */ @@ -1115,6 +1137,13 @@ TASK_LIST_START TEST_ENTRY (idna_toascii) #endif + TEST_ENTRY (not_writable_after_shutdown) + TEST_HELPER (not_writable_after_shutdown, tcp4_echo_server) + TEST_ENTRY (not_readable_nor_writable_on_read_error) + TEST_HELPER (not_readable_nor_writable_on_read_error, tcp4_echo_server) + TEST_ENTRY (not_readable_on_eof) + TEST_HELPER (not_readable_on_eof, tcp4_echo_server) + TEST_ENTRY (metrics_idle_time) TEST_ENTRY (metrics_idle_time_thread) TEST_ENTRY (metrics_idle_time_zero) diff --git a/deps/libuv/test/test-loop-handles.c b/deps/libuv/test/test-loop-handles.c index 13109880..05cb8466 100644 --- a/deps/libuv/test/test-loop-handles.c +++ b/deps/libuv/test/test-loop-handles.c @@ -143,7 +143,7 @@ static void idle_1_cb(uv_idle_t* handle) { fprintf(stderr, "%s", "IDLE_1_CB\n"); fflush(stderr); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); ASSERT(idles_1_active > 0); /* Init idle_2 and make it active */ @@ -170,7 +170,7 @@ static void idle_1_close_cb(uv_handle_t* handle) { fprintf(stderr, "%s", "IDLE_1_CLOSE_CB\n"); fflush(stderr); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); idle_1_close_cb_called++; } diff --git a/deps/libuv/test/test-multiple-listen.c b/deps/libuv/test/test-multiple-listen.c index 4ae5fa67..0b285141 100644 --- a/deps/libuv/test/test-multiple-listen.c +++ b/deps/libuv/test/test-multiple-listen.c @@ -32,7 +32,7 @@ static uv_tcp_t client; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } @@ -65,7 +65,7 @@ static void start_server(void) { static void connect_cb(uv_connect_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); free(req); uv_close((uv_handle_t*)&client, close_cb); @@ -79,7 +79,7 @@ static void client_connect(void) { int r; ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(connect_req != NULL); + ASSERT_NOT_NULL(connect_req); r = uv_tcp_init(uv_default_loop(), &client); ASSERT(r == 0); diff --git a/deps/libuv/test/test-not-readable-nor-writable-on-read-error.c b/deps/libuv/test/test-not-readable-nor-writable-on-read-error.c new file mode 100644 index 00000000..ae951e39 --- /dev/null +++ b/deps/libuv/test/test-not-readable-nor-writable-on-read-error.c @@ -0,0 +1,104 @@ +/* Copyright the 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" + +static uv_loop_t loop; +static uv_tcp_t tcp_client; +static uv_connect_t connect_req; +static uv_write_t write_req; +static char reset_me_cmd[] = {'Q', 'S', 'H'}; + +static int connect_cb_called; +static int read_cb_called; +static int write_cb_called; +static int close_cb_called; + +static void write_cb(uv_write_t* req, int status) { + write_cb_called++; + ASSERT(status == 0); +} + +static void alloc_cb(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) { + static char slab[64]; + buf->base = slab; + buf->len = sizeof(slab); +} + +static void close_cb(uv_handle_t* handle) { + close_cb_called++; +} + +static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { + read_cb_called++; + + ASSERT((nread < 0) && (nread != UV_EOF)); + ASSERT(0 == uv_is_writable(handle)); + ASSERT(0 == uv_is_readable(handle)); + + uv_close((uv_handle_t*) handle, close_cb); +} + +static void connect_cb(uv_connect_t* req, int status) { + int r; + uv_buf_t reset_me; + + connect_cb_called++; + ASSERT(status == 0); + + r = uv_read_start((uv_stream_t*) &tcp_client, alloc_cb, read_cb); + ASSERT(r == 0); + + reset_me = uv_buf_init(reset_me_cmd, sizeof(reset_me_cmd)); + + r = uv_write(&write_req, + (uv_stream_t*) &tcp_client, + &reset_me, + 1, + write_cb); + + ASSERT(r == 0); +} + +TEST_IMPL(not_readable_nor_writable_on_read_error) { + struct sockaddr_in sa; + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &sa)); + ASSERT(0 == uv_loop_init(&loop)); + ASSERT(0 == uv_tcp_init(&loop, &tcp_client)); + + ASSERT(0 == uv_tcp_connect(&connect_req, + &tcp_client, + (const struct sockaddr*) &sa, + connect_cb)); + + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + + ASSERT(connect_cb_called == 1); + ASSERT(read_cb_called == 1); + ASSERT(write_cb_called == 1); + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/libuv/test/test-not-readable-on-eof.c b/deps/libuv/test/test-not-readable-on-eof.c new file mode 100644 index 00000000..2bb5f4ee --- /dev/null +++ b/deps/libuv/test/test-not-readable-on-eof.c @@ -0,0 +1,103 @@ +/* Copyright the 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" + +static uv_loop_t loop; +static uv_tcp_t tcp_client; +static uv_connect_t connect_req; +static uv_write_t write_req; +static char close_me_cmd[] = {'Q', 'S'}; + +static int connect_cb_called; +static int read_cb_called; +static int write_cb_called; +static int close_cb_called; + +static void write_cb(uv_write_t* req, int status) { + write_cb_called++; + ASSERT(status == 0); +} + +static void alloc_cb(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) { + static char slab[64]; + buf->base = slab; + buf->len = sizeof(slab); +} + +static void close_cb(uv_handle_t* handle) { + close_cb_called++; +} + +static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { + read_cb_called++; + + ASSERT(nread == UV_EOF); + ASSERT(0 == uv_is_readable(handle)); + + uv_close((uv_handle_t*) handle, close_cb); +} + +static void connect_cb(uv_connect_t* req, int status) { + int r; + uv_buf_t close_me; + + connect_cb_called++; + ASSERT(status == 0); + + r = uv_read_start((uv_stream_t*) &tcp_client, alloc_cb, read_cb); + ASSERT(r == 0); + + close_me = uv_buf_init(close_me_cmd, sizeof(close_me_cmd)); + + r = uv_write(&write_req, + (uv_stream_t*) &tcp_client, + &close_me, + 1, + write_cb); + + ASSERT(r == 0); +} + +TEST_IMPL(not_readable_on_eof) { + struct sockaddr_in sa; + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &sa)); + ASSERT(0 == uv_loop_init(&loop)); + ASSERT(0 == uv_tcp_init(&loop, &tcp_client)); + + ASSERT(0 == uv_tcp_connect(&connect_req, + &tcp_client, + (const struct sockaddr*) &sa, + connect_cb)); + + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + + ASSERT(connect_cb_called == 1); + ASSERT(read_cb_called == 1); + ASSERT(write_cb_called == 1); + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/libuv/test/test-not-writable-after-shutdown.c b/deps/libuv/test/test-not-writable-after-shutdown.c new file mode 100644 index 00000000..9cd93703 --- /dev/null +++ b/deps/libuv/test/test-not-writable-after-shutdown.c @@ -0,0 +1,69 @@ +/* Copyright the 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" + +static uv_shutdown_t shutdown_req; + +static void close_cb(uv_handle_t* handle) { + +} + +static void shutdown_cb(uv_shutdown_t* req, int status) { + uv_close((uv_handle_t*) req->handle, close_cb); +} + +static void connect_cb(uv_connect_t* req, int status) { + int r; + ASSERT(status == 0); + + r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb); + ASSERT(r == 0); + + ASSERT(0 == uv_is_writable(req->handle)); +} + +TEST_IMPL(not_writable_after_shutdown) { + int r; + struct sockaddr_in addr; + uv_loop_t* loop; + uv_tcp_t socket; + uv_connect_t connect_req; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + loop = uv_default_loop(); + + r = uv_tcp_init(loop, &socket); + ASSERT(r == 0); + + r = uv_tcp_connect(&connect_req, + &socket, + (const struct sockaddr*) &addr, + connect_cb); + ASSERT(r == 0); + + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + ASSERT(r == 0); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/libuv/test/test-ping-pong.c b/deps/libuv/test/test-ping-pong.c index 7f7758b3..4a26e4de 100644 --- a/deps/libuv/test/test-ping-pong.c +++ b/deps/libuv/test/test-ping-pong.c @@ -24,6 +24,7 @@ #include #include +#include /* strlen */ static int completed_pingers = 0; @@ -33,23 +34,21 @@ static int completed_pingers = 0; #define NUM_PINGS 1000 #endif -/* 64 bytes is enough for a pinger */ -#define BUFSIZE 10240 - static char PING[] = "PING\n"; +static char PONG[] = "PONG\n"; static int pinger_on_connect_count; typedef struct { int vectored_writes; - int pongs; - int state; + unsigned pongs; + unsigned state; union { uv_tcp_t tcp; uv_pipe_t pipe; } stream; uv_connect_t connect_req; - char read_buffer[BUFSIZE]; + char* pong; } pinger_t; @@ -59,28 +58,44 @@ static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { } +static void ponger_on_close(uv_handle_t* handle) { + if (handle->data) + free(handle->data); + else + free(handle); +} + + static void pinger_on_close(uv_handle_t* handle) { - pinger_t* pinger = (pinger_t*)handle->data; + pinger_t* pinger = (pinger_t*) handle->data; - ASSERT(NUM_PINGS == pinger->pongs); + ASSERT_EQ(NUM_PINGS, pinger->pongs); - free(pinger); + if (handle == (uv_handle_t*) &pinger->stream.tcp) { + free(pinger); /* also frees handle */ + } else { + uv_close((uv_handle_t*) &pinger->stream.tcp, ponger_on_close); + free(handle); + } completed_pingers++; } static void pinger_after_write(uv_write_t* req, int status) { - ASSERT(status == 0); + ASSERT_EQ(status, 0); free(req); } static void pinger_write_ping(pinger_t* pinger) { + uv_stream_t* stream; uv_write_t* req; uv_buf_t bufs[sizeof PING - 1]; int i, nbufs; + stream = (uv_stream_t*) &pinger->stream.tcp; + if (!pinger->vectored_writes) { /* Write a single buffer. */ nbufs = 1; @@ -94,13 +109,8 @@ static void pinger_write_ping(pinger_t* pinger) { } req = malloc(sizeof(*req)); - if (uv_write(req, - (uv_stream_t*) &pinger->stream.tcp, - bufs, - nbufs, - pinger_after_write)) { - FATAL("uv_write failed"); - } + ASSERT_NOT_NULL(req); + ASSERT_EQ(0, uv_write(req, stream, bufs, nbufs, pinger_after_write)); puts("PING"); } @@ -115,20 +125,20 @@ static void pinger_read_cb(uv_stream_t* stream, pinger = (pinger_t*) stream->data; if (nread < 0) { - ASSERT(nread == UV_EOF); + ASSERT_EQ(nread, UV_EOF); puts("got EOF"); free(buf->base); - uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close); + uv_close((uv_handle_t*) stream, pinger_on_close); return; } - /* Now we count the pings */ + /* Now we count the pongs */ for (i = 0; i < nread; i++) { - ASSERT(buf->base[i] == PING[pinger->state]); - pinger->state = (pinger->state + 1) % (sizeof(PING) - 1); + ASSERT_EQ(buf->base[i], pinger->pong[pinger->state]); + pinger->state = (pinger->state + 1) % strlen(pinger->pong); if (pinger->state != 0) continue; @@ -139,7 +149,7 @@ static void pinger_read_cb(uv_stream_t* stream, if (pinger->pongs < NUM_PINGS) { pinger_write_ping(pinger); } else { - uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close); + uv_close((uv_handle_t*) stream, pinger_on_close); break; } } @@ -148,20 +158,53 @@ static void pinger_read_cb(uv_stream_t* stream, } +static void ponger_read_cb(uv_stream_t* stream, + ssize_t nread, + const uv_buf_t* buf) { + uv_buf_t writebuf; + uv_write_t* req; + int i; + + if (nread < 0) { + ASSERT_EQ(nread, UV_EOF); + + puts("got EOF"); + free(buf->base); + + uv_close((uv_handle_t*) stream, ponger_on_close); + + return; + } + + /* Echo back */ + for (i = 0; i < nread; i++) { + if (buf->base[i] == 'I') + buf->base[i] = 'O'; + } + + writebuf = uv_buf_init(buf->base, nread); + req = malloc(sizeof(*req)); + ASSERT_NOT_NULL(req); + ASSERT_EQ(0, uv_write(req, stream, &writebuf, 1, pinger_after_write)); +} + + static void pinger_on_connect(uv_connect_t* req, int status) { - pinger_t* pinger = (pinger_t*)req->handle->data; + pinger_t* pinger = (pinger_t*) req->handle->data; pinger_on_connect_count++; - ASSERT(status == 0); + ASSERT_EQ(status, 0); - ASSERT(1 == uv_is_readable(req->handle)); - ASSERT(1 == uv_is_writable(req->handle)); - ASSERT(0 == uv_is_closing((uv_handle_t *) req->handle)); + ASSERT_EQ(1, uv_is_readable(req->handle)); + ASSERT_EQ(1, uv_is_writable(req->handle)); + ASSERT_EQ(0, uv_is_closing((uv_handle_t *) req->handle)); pinger_write_ping(pinger); - uv_read_start((uv_stream_t*)(req->handle), alloc_cb, pinger_read_cb); + ASSERT_EQ(0, uv_read_start((uv_stream_t*) req->handle, + alloc_cb, + pinger_read_cb)); } @@ -172,17 +215,18 @@ static void tcp_pinger_v6_new(int vectored_writes) { pinger_t* pinger; - ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &server_addr)); + ASSERT_EQ(0, uv_ip6_addr("::1", TEST_PORT, &server_addr)); pinger = malloc(sizeof(*pinger)); - ASSERT(pinger != NULL); + ASSERT_NOT_NULL(pinger); pinger->vectored_writes = vectored_writes; pinger->state = 0; pinger->pongs = 0; + pinger->pong = PING; /* Try to connect to the server and do NUM_PINGS ping-pongs. */ r = uv_tcp_init(uv_default_loop(), &pinger->stream.tcp); pinger->stream.tcp.data = pinger; - ASSERT(!r); + ASSERT_EQ(0, r); /* We are never doing multiple reads/connects at a time anyway, so these * handles can be pre-initialized. */ @@ -190,10 +234,10 @@ static void tcp_pinger_v6_new(int vectored_writes) { &pinger->stream.tcp, (const struct sockaddr*) &server_addr, pinger_on_connect); - ASSERT(!r); + ASSERT_EQ(0, r); /* Synchronous connect callbacks are not allowed. */ - ASSERT(pinger_on_connect_count == 0); + ASSERT_EQ(pinger_on_connect_count, 0); } @@ -202,17 +246,18 @@ static void tcp_pinger_new(int vectored_writes) { struct sockaddr_in server_addr; pinger_t* pinger; - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); + ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); pinger = malloc(sizeof(*pinger)); - ASSERT(pinger != NULL); + ASSERT_NOT_NULL(pinger); pinger->vectored_writes = vectored_writes; pinger->state = 0; pinger->pongs = 0; + pinger->pong = PING; /* Try to connect to the server and do NUM_PINGS ping-pongs. */ r = uv_tcp_init(uv_default_loop(), &pinger->stream.tcp); pinger->stream.tcp.data = pinger; - ASSERT(!r); + ASSERT_EQ(0, r); /* We are never doing multiple reads/connects at a time anyway, so these * handles can be pre-initialized. */ @@ -220,10 +265,10 @@ static void tcp_pinger_new(int vectored_writes) { &pinger->stream.tcp, (const struct sockaddr*) &server_addr, pinger_on_connect); - ASSERT(!r); + ASSERT_EQ(0, r); /* Synchronous connect callbacks are not allowed. */ - ASSERT(pinger_on_connect_count == 0); + ASSERT_EQ(pinger_on_connect_count, 0); } @@ -232,15 +277,16 @@ static void pipe_pinger_new(int vectored_writes) { pinger_t* pinger; pinger = malloc(sizeof(*pinger)); - ASSERT(pinger != NULL); + ASSERT_NOT_NULL(pinger); pinger->vectored_writes = vectored_writes; pinger->state = 0; pinger->pongs = 0; + pinger->pong = PING; /* Try to connect to the server and do NUM_PINGS ping-pongs. */ r = uv_pipe_init(uv_default_loop(), &pinger->stream.pipe, 0); pinger->stream.pipe.data = pinger; - ASSERT(!r); + ASSERT_EQ(0, r); /* We are never doing multiple reads/connects at a time anyway, so these * handles can be pre-initialized. */ @@ -248,13 +294,86 @@ static void pipe_pinger_new(int vectored_writes) { pinger_on_connect); /* Synchronous connect callbacks are not allowed. */ - ASSERT(pinger_on_connect_count == 0); + ASSERT_EQ(pinger_on_connect_count, 0); } +static void socketpair_pinger_new(int vectored_writes) { + pinger_t* pinger; + uv_os_sock_t fds[2]; + uv_tcp_t* ponger; + + pinger = malloc(sizeof(*pinger)); + ASSERT_NOT_NULL(pinger); + pinger->vectored_writes = vectored_writes; + pinger->state = 0; + pinger->pongs = 0; + pinger->pong = PONG; + + /* Try to make a socketpair and do NUM_PINGS ping-pongs. */ + (void)uv_default_loop(); /* ensure WSAStartup has been performed */ + ASSERT_EQ(0, uv_socketpair(SOCK_STREAM, 0, fds, UV_NONBLOCK_PIPE, UV_NONBLOCK_PIPE)); +#ifndef _WIN32 + /* On Windows, this is actually a UV_TCP, but libuv doesn't detect that. */ + ASSERT_EQ(uv_guess_handle((uv_file) fds[0]), UV_NAMED_PIPE); + ASSERT_EQ(uv_guess_handle((uv_file) fds[1]), UV_NAMED_PIPE); +#endif + + ASSERT_EQ(0, uv_tcp_init(uv_default_loop(), &pinger->stream.tcp)); + pinger->stream.pipe.data = pinger; + ASSERT_EQ(0, uv_tcp_open(&pinger->stream.tcp, fds[1])); + + ponger = malloc(sizeof(*ponger)); + ASSERT_NOT_NULL(ponger); + ponger->data = NULL; + ASSERT_EQ(0, uv_tcp_init(uv_default_loop(), ponger)); + ASSERT_EQ(0, uv_tcp_open(ponger, fds[0])); + + pinger_write_ping(pinger); + + ASSERT_EQ(0, uv_read_start((uv_stream_t*) &pinger->stream.tcp, + alloc_cb, + pinger_read_cb)); + ASSERT_EQ(0, uv_read_start((uv_stream_t*) ponger, + alloc_cb, + ponger_read_cb)); +} + + +static void pipe2_pinger_new(int vectored_writes) { + uv_file fds[2]; + pinger_t* pinger; + uv_pipe_t* ponger; + + /* Try to make a pipe and do NUM_PINGS pings. */ + ASSERT_EQ(0, uv_pipe(fds, UV_NONBLOCK_PIPE, UV_NONBLOCK_PIPE)); + ASSERT_EQ(uv_guess_handle(fds[0]), UV_NAMED_PIPE); + ASSERT_EQ(uv_guess_handle(fds[1]), UV_NAMED_PIPE); + + ponger = malloc(sizeof(*ponger)); + ASSERT_NOT_NULL(ponger); + ASSERT_EQ(0, uv_pipe_init(uv_default_loop(), ponger, 0)); + ASSERT_EQ(0, uv_pipe_open(ponger, fds[0])); + + pinger = malloc(sizeof(*pinger)); + ASSERT_NOT_NULL(pinger); + pinger->vectored_writes = vectored_writes; + pinger->state = 0; + pinger->pongs = 0; + pinger->pong = PING; + ASSERT_EQ(0, uv_pipe_init(uv_default_loop(), &pinger->stream.pipe, 0)); + ASSERT_EQ(0, uv_pipe_open(&pinger->stream.pipe, fds[1])); + pinger->stream.pipe.data = pinger; /* record for close_cb */ + ponger->data = pinger; /* record for read_cb */ + + pinger_write_ping(pinger); + + ASSERT_EQ(0, uv_read_start((uv_stream_t*) ponger, alloc_cb, pinger_read_cb)); +} + static int run_ping_pong_test(void) { uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(completed_pingers == 1); + ASSERT_EQ(completed_pingers, 1); MAKE_VALGRIND_HAPPY(); return 0; @@ -263,12 +382,20 @@ static int run_ping_pong_test(void) { TEST_IMPL(tcp_ping_pong) { tcp_pinger_new(0); + run_ping_pong_test(); + + completed_pingers = 0; + socketpair_pinger_new(0); return run_ping_pong_test(); } TEST_IMPL(tcp_ping_pong_vec) { tcp_pinger_new(1); + run_ping_pong_test(); + + completed_pingers = 0; + socketpair_pinger_new(1); return run_ping_pong_test(); } @@ -291,11 +418,19 @@ TEST_IMPL(tcp6_ping_pong_vec) { TEST_IMPL(pipe_ping_pong) { pipe_pinger_new(0); + run_ping_pong_test(); + + completed_pingers = 0; + pipe2_pinger_new(0); return run_ping_pong_test(); } TEST_IMPL(pipe_ping_pong_vec) { pipe_pinger_new(1); + run_ping_pong_test(); + + completed_pingers = 0; + pipe2_pinger_new(1); return run_ping_pong_test(); } diff --git a/deps/libuv/test/test-pipe-bind-error.c b/deps/libuv/test/test-pipe-bind-error.c index 9cf93165..ce35052f 100644 --- a/deps/libuv/test/test-pipe-bind-error.c +++ b/deps/libuv/test/test-pipe-bind-error.c @@ -36,7 +36,7 @@ static int close_cb_called = 0; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-pipe-connect-error.c b/deps/libuv/test/test-pipe-connect-error.c index ebb2a6ca..30c270d9 100644 --- a/deps/libuv/test/test-pipe-connect-error.c +++ b/deps/libuv/test/test-pipe-connect-error.c @@ -37,7 +37,7 @@ static int connect_cb_called = 0; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } @@ -76,6 +76,9 @@ TEST_IMPL(pipe_connect_bad_name) { TEST_IMPL(pipe_connect_to_file) { +#if defined(__ASAN__) + RETURN_SKIP("Test does not currently work in ASAN"); +#endif const char* path = "test/fixtures/empty_file"; uv_pipe_t client; uv_connect_t req; diff --git a/deps/libuv/test/test-pipe-connect-prepare.c b/deps/libuv/test/test-pipe-connect-prepare.c index a86e7284..08b57cbf 100644 --- a/deps/libuv/test/test-pipe-connect-prepare.c +++ b/deps/libuv/test/test-pipe-connect-prepare.c @@ -42,7 +42,7 @@ static uv_connect_t conn_req; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-pipe-getsockname.c b/deps/libuv/test/test-pipe-getsockname.c index 48ee400e..79db8eba 100644 --- a/deps/libuv/test/test-pipe-getsockname.c +++ b/deps/libuv/test/test-pipe-getsockname.c @@ -96,7 +96,7 @@ TEST_IMPL(pipe_getsockname) { int r; loop = uv_default_loop(); - ASSERT(loop != NULL); + ASSERT_NOT_NULL(loop); r = uv_pipe_init(loop, &pipe_server, 0); ASSERT(r == 0); @@ -225,7 +225,9 @@ TEST_IMPL(pipe_getsockname_blocking) { ASSERT(r != -1); r = uv_pipe_open(&pipe_client, readfd); ASSERT(r == 0); - r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); + r = uv_read_start((uv_stream_t*) &pipe_client, + (uv_alloc_cb) abort, + (uv_read_cb) abort); ASSERT(r == 0); Sleep(100); r = uv_read_stop((uv_stream_t*)&pipe_client); @@ -236,7 +238,9 @@ TEST_IMPL(pipe_getsockname_blocking) { ASSERT(r == 0); ASSERT(len1 == 0); /* It's an annonymous pipe. */ - r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); + r = uv_read_start((uv_stream_t*)&pipe_client, + (uv_alloc_cb) abort, + (uv_read_cb) abort); ASSERT(r == 0); Sleep(100); diff --git a/deps/libuv/test/test-pipe-server-close.c b/deps/libuv/test/test-pipe-server-close.c index ea9977dd..25305b39 100644 --- a/deps/libuv/test/test-pipe-server-close.c +++ b/deps/libuv/test/test-pipe-server-close.c @@ -68,7 +68,7 @@ TEST_IMPL(pipe_server_close) { int r; loop = uv_default_loop(); - ASSERT(loop != NULL); + ASSERT_NOT_NULL(loop); r = uv_pipe_init(loop, &pipe_server, 0); ASSERT(r == 0); diff --git a/deps/libuv/test/test-pipe-set-non-blocking.c b/deps/libuv/test/test-pipe-set-non-blocking.c index 626b53f0..8246afaf 100644 --- a/deps/libuv/test/test-pipe-set-non-blocking.c +++ b/deps/libuv/test/test-pipe-set-non-blocking.c @@ -16,18 +16,10 @@ #include "uv.h" #include "task.h" -#ifdef _WIN32 - -TEST_IMPL(pipe_set_non_blocking) { - RETURN_SKIP("Test not implemented on Windows."); -} - -#else /* !_WIN32 */ - #include /* memset */ +#ifndef _WIN32 #include /* close */ -#include -#include +#endif struct thread_ctx { uv_barrier_t barrier; @@ -54,9 +46,28 @@ static void thread_main(void* arg) { uv_fs_req_cleanup(&req); } while (n > 0 || (n == -1 && uv_errno == UV_EINTR)); +#ifdef _WIN32 + ASSERT(n == UV_EOF); +#else ASSERT(n == 0); +#endif } + +#ifdef _WIN32 +static void write_cb(uv_write_t* req, int status) { + ASSERT(status == 0); + req->handle = NULL; /* signal completion of write_cb */ +} +#endif + +#ifdef _WIN32 +#define NWRITES (10 << 16) +#else +#define NWRITES (10 << 20) +#endif + + TEST_IMPL(pipe_set_non_blocking) { struct thread_ctx ctx; uv_pipe_t pipe_handle; @@ -66,9 +77,12 @@ TEST_IMPL(pipe_set_non_blocking) { uv_buf_t buf; uv_file fd[2]; int n; +#ifdef _WIN32 + uv_write_t write_req; +#endif ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); - ASSERT(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, fd)); + ASSERT(0 == uv_pipe(fd, 0, 0)); ASSERT(0 == uv_pipe_open(&pipe_handle, fd[1])); ASSERT(0 == uv_stream_set_blocking((uv_stream_t*) &pipe_handle, 1)); fd[1] = -1; /* fd[1] is owned by pipe_handle now. */ @@ -83,11 +97,20 @@ TEST_IMPL(pipe_set_non_blocking) { memset(data, '.', sizeof(data)); nwritten = 0; - while (nwritten < 10 << 20) { + while (nwritten < NWRITES) { /* The stream is in blocking mode so uv_try_write() should always succeed * with the exact number of bytes that we wanted written. */ n = uv_try_write((uv_stream_t*) &pipe_handle, &buf, 1); +#ifdef _WIN32 + ASSERT(n == UV_EAGAIN); /* E_NOTIMPL */ + ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &pipe_handle, &buf, 1, write_cb)); + ASSERT_NOT_NULL(write_req.handle); + ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* queue write_cb */ + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* process write_cb */ + ASSERT_NULL(write_req.handle); /* check for signaled completion of write_cb */ + n = buf.len; +#endif ASSERT(n == sizeof(data)); nwritten += n; } @@ -96,12 +119,14 @@ TEST_IMPL(pipe_set_non_blocking) { ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); ASSERT(0 == uv_thread_join(&thread)); +#ifdef _WIN32 + ASSERT(0 == _close(fd[0])); /* fd[1] is closed by uv_close(). */ +#else ASSERT(0 == close(fd[0])); /* fd[1] is closed by uv_close(). */ +#endif fd[0] = -1; uv_barrier_destroy(&ctx.barrier); MAKE_VALGRIND_HAPPY(); return 0; } - -#endif /* !_WIN32 */ diff --git a/deps/libuv/test/test-platform-output.c b/deps/libuv/test/test-platform-output.c index f547ddfd..341c7ae5 100644 --- a/deps/libuv/test/test-platform-output.c +++ b/deps/libuv/test/test-platform-output.c @@ -155,6 +155,7 @@ TEST_IMPL(platform_output) { printf(" username: %s\n", pwd.username); printf(" shell: %s\n", pwd.shell); printf(" home directory: %s\n", pwd.homedir); + uv_os_free_passwd(&pwd); pid = uv_os_getpid(); ASSERT(pid > 0); diff --git a/deps/libuv/test/test-poll-multiple-handles.c b/deps/libuv/test/test-poll-multiple-handles.c new file mode 100644 index 00000000..fc2205dd --- /dev/null +++ b/deps/libuv/test/test-poll-multiple-handles.c @@ -0,0 +1,99 @@ +/* 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 + +#ifndef _WIN32 +# include +# include +# include +#endif + +#include "uv.h" +#include "task.h" + + +static int close_cb_called = 0; + + +static void close_cb(uv_handle_t* handle) { + close_cb_called++; +} + +static void poll_cb(uv_poll_t* handle, int status, int events) { + /* Not a bound socket, linux immediately reports UV_READABLE, other OS do not */ + ASSERT(events == UV_READABLE); +} + +TEST_IMPL(poll_multiple_handles) { + uv_os_sock_t sock; + uv_poll_t first_poll_handle, second_poll_handle; + +#ifdef _WIN32 + { + struct WSAData wsa_data; + int r = WSAStartup(MAKEWORD(2, 2), &wsa_data); + ASSERT(r == 0); + } +#endif + + sock = socket(AF_INET, SOCK_STREAM, 0); +#ifdef _WIN32 + ASSERT(sock != INVALID_SOCKET); +#else + ASSERT(sock != -1); +#endif + ASSERT(0 == uv_poll_init_socket(uv_default_loop(), &first_poll_handle, sock)); + ASSERT(0 == uv_poll_init_socket(uv_default_loop(), &second_poll_handle, sock)); + + ASSERT(0 == uv_poll_start(&first_poll_handle, UV_READABLE, poll_cb)); + + /* We may not start polling while another polling handle is active + * on that fd. + */ +#ifndef _WIN32 + /* We do not track handles in an O(1) lookupable way on Windows, + * so not checking that here. + */ + ASSERT(uv_poll_start(&second_poll_handle, UV_READABLE, poll_cb) == UV_EEXIST); +#endif + + /* After stopping the other polling handle, we now should be able to poll */ + ASSERT(0 == uv_poll_stop(&first_poll_handle)); + ASSERT(0 == uv_poll_start(&second_poll_handle, UV_READABLE, poll_cb)); + + /* Closing an already stopped polling handle is safe in any case */ + uv_close((uv_handle_t*) &first_poll_handle, close_cb); + + uv_unref((uv_handle_t*) &second_poll_handle); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + ASSERT(close_cb_called == 1); + uv_ref((uv_handle_t*) &second_poll_handle); + + ASSERT(uv_is_active((uv_handle_t*) &second_poll_handle)); + uv_close((uv_handle_t*) &second_poll_handle, close_cb); + + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + ASSERT(close_cb_called == 2); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/libuv/test/test-poll.c b/deps/libuv/test/test-poll.c index edd75d38..3bc422d2 100644 --- a/deps/libuv/test/test-poll.c +++ b/deps/libuv/test/test-poll.c @@ -147,7 +147,7 @@ static connection_context_t* create_connection_context( connection_context_t* context; context = (connection_context_t*) malloc(sizeof *context); - ASSERT(context != NULL); + ASSERT_NOT_NULL(context); context->sock = sock; context->is_server_connection = is_server_connection; @@ -464,7 +464,7 @@ static server_context_t* create_server_context( server_context_t* context; context = (server_context_t*) malloc(sizeof *context); - ASSERT(context != NULL); + ASSERT_NOT_NULL(context); context->sock = sock; context->connections = 0; diff --git a/deps/libuv/test/test-ref.c b/deps/libuv/test/test-ref.c index 05728c83..d24ea4a0 100644 --- a/deps/libuv/test/test-ref.c +++ b/deps/libuv/test/test-ref.c @@ -154,7 +154,7 @@ TEST_IMPL(check_ref) { static void prepare_cb(uv_prepare_t* h) { - ASSERT(h != NULL); + ASSERT_NOT_NULL(h); uv_unref((uv_handle_t*)h); } diff --git a/deps/libuv/test/test-shutdown-eof.c b/deps/libuv/test/test-shutdown-eof.c index 9f95e756..0abab917 100644 --- a/deps/libuv/test/test-shutdown-eof.c +++ b/deps/libuv/test/test-shutdown-eof.c @@ -89,7 +89,13 @@ static void connect_cb(uv_connect_t *req, int status) { ASSERT(req == &connect_req); /* Start reading from our connection so we can receive the EOF. */ - uv_read_start((uv_stream_t*)&tcp, alloc_cb, read_cb); + ASSERT_EQ(0, uv_read_start((uv_stream_t*)&tcp, alloc_cb, read_cb)); + + /* Check error handling. */ + ASSERT_EQ(UV_EALREADY, uv_read_start((uv_stream_t*)&tcp, alloc_cb, read_cb)); + ASSERT_EQ(UV_EINVAL, uv_read_start(NULL, alloc_cb, read_cb)); + ASSERT_EQ(UV_EINVAL, uv_read_start((uv_stream_t*)&tcp, NULL, read_cb)); + ASSERT_EQ(UV_EINVAL, uv_read_start((uv_stream_t*)&tcp, alloc_cb, NULL)); /* * Write the letter 'Q' to gracefully kill the echo-server. This will not diff --git a/deps/libuv/test/test-shutdown-simultaneous.c b/deps/libuv/test/test-shutdown-simultaneous.c new file mode 100644 index 00000000..7de3bd42 --- /dev/null +++ b/deps/libuv/test/test-shutdown-simultaneous.c @@ -0,0 +1,135 @@ +/* Copyright libuv project and 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 +#include + +static uv_tcp_t tcp; +static uv_connect_t connect_req; +static uv_shutdown_t shutdown_req; +static uv_buf_t qbuf; +static int got_q; +static int got_eof; +static int called_connect_cb; +static int called_shutdown_cb; +static int called_tcp_close_cb; + + +static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { + buf->base = malloc(size); + buf->len = size; +} + + +static void shutdown_cb(uv_shutdown_t *req, int status) { + ASSERT_PTR_EQ(req, &shutdown_req); + + ASSERT_EQ(called_connect_cb, 1); + ASSERT_EQ(called_tcp_close_cb, 0); +} + + +static void read_cb(uv_stream_t* t, ssize_t nread, const uv_buf_t* buf) { + ASSERT_PTR_EQ((uv_tcp_t*)t, &tcp); + + if (nread == 0) { + free(buf->base); + return; + } + + if (!got_q) { + ASSERT_EQ(nread, 4); + ASSERT_EQ(got_eof, 0); + ASSERT_MEM_EQ(buf->base, "QQSS", 4); + free(buf->base); + got_q = 1; + puts("got QQSS"); + /* Shutdown our end of the connection simultaneously */ + uv_shutdown(&shutdown_req, (uv_stream_t*) &tcp, shutdown_cb); + called_shutdown_cb++; + } else { + ASSERT_EQ(nread, UV_EOF); + if (buf->base) { + free(buf->base); + } + got_eof = 1; + puts("got EOF"); + } +} + + +static void connect_cb(uv_connect_t *req, int status) { + ASSERT_EQ(status, 0); + ASSERT_PTR_EQ(req, &connect_req); + + /* Start reading from our connection so we can receive the EOF. */ + ASSERT_EQ(0, uv_read_start((uv_stream_t*)&tcp, alloc_cb, read_cb)); + + /* Check error handling. */ + ASSERT_EQ(UV_EALREADY, uv_read_start((uv_stream_t*)&tcp, alloc_cb, read_cb)); + ASSERT_EQ(UV_EINVAL, uv_read_start(NULL, alloc_cb, read_cb)); + ASSERT_EQ(UV_EINVAL, uv_read_start((uv_stream_t*)&tcp, NULL, read_cb)); + ASSERT_EQ(UV_EINVAL, uv_read_start((uv_stream_t*)&tcp, alloc_cb, NULL)); + + /* + * Write the letter 'Q' and 'QSS` to gracefully kill the echo-server. This + * will not effect our connection. + */ + ASSERT_EQ(qbuf.len, uv_try_write((uv_stream_t*) &tcp, &qbuf, 1)); + + called_connect_cb++; + ASSERT_EQ(called_shutdown_cb, 0); +} + + +/* + * This test has a client which connects to the echo_server and immediately + * issues a shutdown. We check that this does not cause libuv to hang. + */ +TEST_IMPL(shutdown_simultaneous) { + struct sockaddr_in server_addr; + int r; + + qbuf.base = "QQSS"; + qbuf.len = 4; + + ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); + r = uv_tcp_init(uv_default_loop(), &tcp); + ASSERT_EQ(r, 0); + + r = uv_tcp_connect(&connect_req, + &tcp, + (const struct sockaddr*) &server_addr, + connect_cb); + ASSERT_EQ(r, 0); + + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + ASSERT_EQ(called_connect_cb, 1); + ASSERT_EQ(called_shutdown_cb, 1); + ASSERT_EQ(got_eof, 1); + ASSERT_EQ(got_q, 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/libuv/test/test-signal-multiple-loops.c b/deps/libuv/test/test-signal-multiple-loops.c index 09d9cacb..7d61ff61 100644 --- a/deps/libuv/test/test-signal-multiple-loops.c +++ b/deps/libuv/test/test-signal-multiple-loops.c @@ -170,7 +170,7 @@ static void loop_creating_worker(void* context) { int r; loop = malloc(sizeof(*loop)); - ASSERT(loop != NULL); + ASSERT_NOT_NULL(loop); ASSERT(0 == uv_loop_init(loop)); r = uv_signal_init(loop, &signal); diff --git a/deps/libuv/test/test-signal-pending-on-close.c b/deps/libuv/test/test-signal-pending-on-close.c index 23b9ec8d..428a97ef 100644 --- a/deps/libuv/test/test-signal-pending-on-close.c +++ b/deps/libuv/test/test-signal-pending-on-close.c @@ -49,7 +49,7 @@ static void close_cb(uv_handle_t *handle) { static void write_cb(uv_write_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == UV_EPIPE); free(buf); uv_close((uv_handle_t *) &pipe_hdl, close_cb); @@ -76,7 +76,7 @@ TEST_IMPL(signal_pending_on_close) { /* Write data large enough so it needs loop iteration */ buf = malloc(1<<24); - ASSERT(buf != NULL); + ASSERT_NOT_NULL(buf); memset(buf, '.', 1<<24); buffer = uv_buf_init(buf, 1<<24); diff --git a/deps/libuv/test/test-spawn.c b/deps/libuv/test/test-spawn.c index d1757337..9f2eb24b 100644 --- a/deps/libuv/test/test-spawn.c +++ b/deps/libuv/test/test-spawn.c @@ -29,11 +29,9 @@ #include #ifdef _WIN32 -# if defined(__MINGW32__) -# include -# endif # include # include + typedef BOOL (WINAPI *sCompareObjectHandles)(_In_ HANDLE, _In_ HANDLE); #else # include # include @@ -49,9 +47,7 @@ static char exepath[1024]; static size_t exepath_size = 1024; static char* args[5]; static int no_term_signal; -#ifndef _WIN32 static int timer_counter; -#endif static uv_tcp_t tcp_server; #define OUTPUT_SIZE 1024 @@ -140,12 +136,10 @@ static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { } -#ifndef _WIN32 static void on_read_once(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { uv_read_stop(tcp); on_read(tcp, nread, buf); } -#endif static void write_cb(uv_write_t* req, int status) { @@ -154,6 +148,11 @@ static void write_cb(uv_write_t* req, int status) { } +static void write_null_cb(uv_write_t* req, int status) { + ASSERT(status == 0); +} + + static void init_process_options(char* test, uv_exit_cb exit_cb) { /* Note spawn_helper1 defined in test/run-tests.c */ int r = uv_exepath(exepath, &exepath_size); @@ -177,11 +176,9 @@ static void timer_cb(uv_timer_t* handle) { } -#ifndef _WIN32 static void timer_counter_cb(uv_timer_t* handle) { ++timer_counter; } -#endif TEST_IMPL(spawn_fails) { @@ -1179,7 +1176,7 @@ TEST_IMPL(argument_escaping) { WCHAR* non_verbatim_output; test_output = calloc(count, sizeof(WCHAR*)); - ASSERT(test_output != NULL); + ASSERT_NOT_NULL(test_output); for (i = 0; i < count; ++i) { test_output[i] = calloc(2 * (wcslen(test_str[i]) + 2), sizeof(WCHAR)); quote_cmd_arg(test_str[i], test_output[i]); @@ -1188,7 +1185,7 @@ TEST_IMPL(argument_escaping) { total_size += wcslen(test_output[i]) + 1; } command_line = calloc(total_size + 1, sizeof(WCHAR)); - ASSERT(command_line != NULL); + ASSERT_NOT_NULL(command_line); for (i = 0; i < count; ++i) { wcscat(command_line, test_output[i]); wcscat(command_line, L" "); @@ -1328,9 +1325,8 @@ TEST_IMPL(environment_creation) { found = 1; } } - if (prev) { /* verify sort order -- requires Vista */ -#if _WIN32_WINNT >= 0x0600 && \ - (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR)) + if (prev) { /* verify sort order */ +#if !defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR) ASSERT(CompareStringOrdinal(prev, -1, str, -1, TRUE) == 1); #endif } @@ -1355,7 +1351,7 @@ TEST_IMPL(spawn_with_an_odd_path) { char newpath[2048]; char *path = getenv("PATH"); - ASSERT(path != NULL); + ASSERT_NOT_NULL(path); snprintf(newpath, 2048, ";.;%s", path); SetEnvironmentVariable("PATH", newpath); @@ -1389,7 +1385,7 @@ TEST_IMPL(spawn_setuid_setgid) { /* become the "nobody" user. */ pw = getpwnam("nobody"); - ASSERT(pw != NULL); + ASSERT_NOT_NULL(pw); options.uid = pw->pw_uid; options.gid = pw->pw_gid; snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid); @@ -1427,7 +1423,7 @@ TEST_IMPL(spawn_setuid_fails) { if (uid == 0) { struct passwd* pw; pw = getpwnam("nobody"); - ASSERT(pw != NULL); + ASSERT_NOT_NULL(pw); ASSERT(0 == setgid(pw->pw_gid)); ASSERT(0 == setuid(pw->pw_uid)); } @@ -1478,7 +1474,7 @@ TEST_IMPL(spawn_setgid_fails) { if (uid == 0) { struct passwd* pw; pw = getpwnam("nobody"); - ASSERT(pw != NULL); + ASSERT_NOT_NULL(pw); ASSERT(0 == setgid(pw->pw_gid)); ASSERT(0 == setuid(pw->pw_uid)); } @@ -1579,17 +1575,27 @@ TEST_IMPL(spawn_auto_unref) { } -#ifndef _WIN32 TEST_IMPL(spawn_fs_open) { - int fd; + int r; + uv_os_fd_t fd; + uv_os_fd_t dup_fd; uv_fs_t fs_req; uv_pipe_t in; uv_write_t write_req; + uv_write_t write_req2; uv_buf_t buf; uv_stdio_container_t stdio[1]; +#ifdef _WIN32 + const char dev_null[] = "NUL"; + HMODULE kernelbase_module; + sCompareObjectHandles pCompareObjectHandles; /* function introduced in Windows 10 */ +#else + const char dev_null[] = "/dev/null"; +#endif - fd = uv_fs_open(NULL, &fs_req, "/dev/null", O_RDWR, 0, NULL); - ASSERT(fd >= 0); + r = uv_fs_open(NULL, &fs_req, dev_null, O_RDWR, 0, NULL); + ASSERT(r != -1); + fd = uv_get_osfhandle((uv_file) fs_req.result); uv_fs_req_cleanup(&fs_req); init_process_options("spawn_helper8", exit_cb); @@ -1601,13 +1607,28 @@ TEST_IMPL(spawn_fs_open) { options.stdio[0].data.stream = (uv_stream_t*) ∈ options.stdio_count = 1; + /* make an inheritable copy */ +#ifdef _WIN32 + ASSERT(0 != DuplicateHandle(GetCurrentProcess(), fd, GetCurrentProcess(), &dup_fd, + 0, /* inherit */ TRUE, DUPLICATE_SAME_ACCESS)); + kernelbase_module = GetModuleHandleA("kernelbase.dll"); + pCompareObjectHandles = (sCompareObjectHandles) + GetProcAddress(kernelbase_module, "CompareObjectHandles"); + ASSERT(pCompareObjectHandles == NULL || pCompareObjectHandles(fd, dup_fd)); +#else + dup_fd = dup(fd); +#endif + ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); buf = uv_buf_init((char*) &fd, sizeof(fd)); - ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb)); + ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_null_cb)); + + buf = uv_buf_init((char*) &dup_fd, sizeof(fd)); + ASSERT(0 == uv_write(&write_req2, (uv_stream_t*) &in, &buf, 1, write_cb)); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(0 == uv_fs_close(NULL, &fs_req, fd, NULL)); + ASSERT(0 == uv_fs_close(NULL, &fs_req, r, NULL)); ASSERT(exit_cb_called == 1); ASSERT(close_cb_called == 2); /* One for `in`, one for process */ @@ -1615,17 +1636,20 @@ TEST_IMPL(spawn_fs_open) { MAKE_VALGRIND_HAPPY(); return 0; } -#endif /* !_WIN32 */ -#ifndef _WIN32 TEST_IMPL(closed_fd_events) { uv_stdio_container_t stdio[3]; uv_pipe_t pipe_handle; - int fd[2]; + uv_fs_t req; + uv_buf_t bufs[1]; + uv_file fd[2]; + bufs[0] = uv_buf_init("", 1); /* create a pipe and share it with a child process */ - ASSERT(0 == pipe(fd)); + ASSERT(0 == uv_pipe(fd, 0, 0)); + ASSERT(fd[0] > 2); + ASSERT(fd[1] > 2); /* spawn_helper4 blocks indefinitely. */ init_process_options("spawn_helper4", exit_cb); @@ -1642,12 +1666,18 @@ TEST_IMPL(closed_fd_events) { /* read from the pipe with uv */ ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0])); + /* uv_pipe_open() takes ownership of the file descriptor. */ fd[0] = -1; ASSERT(0 == uv_read_start((uv_stream_t*) &pipe_handle, on_alloc, on_read_once)); - ASSERT(1 == write(fd[1], "", 1)); + ASSERT(1 == uv_fs_write(NULL, &req, fd[1], bufs, 1, -1, NULL)); + ASSERT(req.result == 1); + uv_fs_req_cleanup(&req); +#ifdef _WIN32 + ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_ONCE)); +#endif ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* should have received just one byte */ @@ -1656,7 +1686,9 @@ TEST_IMPL(closed_fd_events) { /* close the pipe and see if we still get events */ uv_close((uv_handle_t*) &pipe_handle, close_cb); - ASSERT(1 == write(fd[1], "", 1)); + ASSERT(1 == uv_fs_write(NULL, &req, fd[1], bufs, 1, -1, NULL)); + ASSERT(req.result == 1); + uv_fs_req_cleanup(&req); ASSERT(0 == uv_timer_init(uv_default_loop(), &timer)); ASSERT(0 == uv_timer_start(&timer, timer_counter_cb, 10, 0)); @@ -1669,13 +1701,17 @@ TEST_IMPL(closed_fd_events) { ASSERT(timer_counter == 1); /* cleanup */ - ASSERT(0 == uv_process_kill(&process, /* SIGTERM */ 15)); + ASSERT(0 == uv_process_kill(&process, SIGTERM)); +#ifdef _WIN32 + ASSERT(0 == _close(fd[1])); +#else ASSERT(0 == close(fd[1])); +#endif MAKE_VALGRIND_HAPPY(); return 0; } -#endif /* !_WIN32 */ + TEST_IMPL(spawn_reads_child_path) { int r; @@ -1746,38 +1782,6 @@ TEST_IMPL(spawn_reads_child_path) { return 0; } -#ifndef _WIN32 -static int mpipe(int *fds) { - if (pipe(fds) == -1) - return -1; - if (fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 || - fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) { - close(fds[0]); - close(fds[1]); - return -1; - } - return 0; -} -#else -static int mpipe(int *fds) { - SECURITY_ATTRIBUTES attr; - HANDLE readh, writeh; - attr.nLength = sizeof(attr); - attr.lpSecurityDescriptor = NULL; - attr.bInheritHandle = FALSE; - if (!CreatePipe(&readh, &writeh, &attr, 0)) - return -1; - fds[0] = _open_osfhandle((intptr_t)readh, 0); - fds[1] = _open_osfhandle((intptr_t)writeh, 0); - if (fds[0] == -1 || fds[1] == -1) { - CloseHandle(readh); - CloseHandle(writeh); - return -1; - } - return 0; -} -#endif /* !_WIN32 */ - TEST_IMPL(spawn_inherit_streams) { uv_process_t child_req; uv_stdio_container_t child_stdio[2]; @@ -1803,8 +1807,8 @@ TEST_IMPL(spawn_inherit_streams) { ASSERT(uv_pipe_init(loop, &pipe_stdin_parent, 0) == 0); ASSERT(uv_pipe_init(loop, &pipe_stdout_parent, 0) == 0); - ASSERT(mpipe(fds_stdin) != -1); - ASSERT(mpipe(fds_stdout) != -1); + ASSERT(uv_pipe(fds_stdin, 0, 0) == 0); + ASSERT(uv_pipe(fds_stdout, 0, 0) == 0); ASSERT(uv_pipe_open(&pipe_stdin_child, fds_stdin[0]) == 0); ASSERT(uv_pipe_open(&pipe_stdout_child, fds_stdout[1]) == 0); diff --git a/deps/libuv/test/test-tcp-alloc-cb-fail.c b/deps/libuv/test/test-tcp-alloc-cb-fail.c index 61ca667a..b6f4ca38 100644 --- a/deps/libuv/test/test-tcp-alloc-cb-fail.c +++ b/deps/libuv/test/test-tcp-alloc-cb-fail.c @@ -53,7 +53,7 @@ static void conn_read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { ASSERT(nread == UV_ENOBUFS); - ASSERT(buf->base == NULL); + ASSERT_NULL(buf->base); ASSERT(buf->len == 0); uv_close((uv_handle_t*) &incoming, close_cb); diff --git a/deps/libuv/test/test-tcp-bind-error.c b/deps/libuv/test/test-tcp-bind-error.c index f95efd9f..fdd1fe07 100644 --- a/deps/libuv/test/test-tcp-bind-error.c +++ b/deps/libuv/test/test-tcp-bind-error.c @@ -25,16 +25,59 @@ #include +static int connect_cb_called = 0; static int close_cb_called = 0; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } -TEST_IMPL(tcp_bind_error_addrinuse) { +static void connect_cb(uv_connect_t* req, int status) { + ASSERT(status == UV_EADDRINUSE); + uv_close((uv_handle_t*) req->handle, close_cb); + connect_cb_called++; +} + + +TEST_IMPL(tcp_bind_error_addrinuse_connect) { + struct sockaddr_in addr; + int addrlen; + uv_connect_t req; + uv_tcp_t conn; + + /* 127.0.0.1: is already taken by tcp4_echo_server running in + * another process. uv_tcp_bind() and uv_tcp_connect() should still succeed + * (greatest common denominator across platforms) but the connect callback + * should receive an UV_EADDRINUSE error. + */ + ASSERT(0 == uv_tcp_init(uv_default_loop(), &conn)); + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT(0 == uv_tcp_bind(&conn, (const struct sockaddr*) &addr, 0)); + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT + 1, &addr)); + ASSERT(0 == uv_tcp_connect(&req, + &conn, + (const struct sockaddr*) &addr, + connect_cb)); + + addrlen = sizeof(addr); + ASSERT(UV_EADDRINUSE == uv_tcp_getsockname(&conn, + (struct sockaddr*) &addr, + &addrlen)); + + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + ASSERT(connect_cb_called == 1); + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tcp_bind_error_addrinuse_listen) { struct sockaddr_in addr; uv_tcp_t server1, server2; int r; @@ -240,7 +283,9 @@ TEST_IMPL(tcp_bind_writable_flags) { ASSERT(r == UV_EPIPE); r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL); ASSERT(r == UV_ENOTCONN); - r = uv_read_start((uv_stream_t*) &server, NULL, NULL); + r = uv_read_start((uv_stream_t*) &server, + (uv_alloc_cb) abort, + (uv_read_cb) abort); ASSERT(r == UV_ENOTCONN); uv_close((uv_handle_t*)&server, close_cb); diff --git a/deps/libuv/test/test-tcp-bind6-error.c b/deps/libuv/test/test-tcp-bind6-error.c index b762bcb3..86181b70 100644 --- a/deps/libuv/test/test-tcp-bind6-error.c +++ b/deps/libuv/test/test-tcp-bind6-error.c @@ -29,7 +29,7 @@ static int close_cb_called = 0; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-tcp-close.c b/deps/libuv/test/test-tcp-close.c index e65885aa..5a7bd689 100644 --- a/deps/libuv/test/test-tcp-close.c +++ b/deps/libuv/test/test-tcp-close.c @@ -46,7 +46,7 @@ static void connect_cb(uv_connect_t* conn_req, int status) { buf = uv_buf_init("PING", 4); for (i = 0; i < NUM_WRITE_REQS; i++) { req = malloc(sizeof *req); - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); r = uv_write(req, (uv_stream_t*)&tcp_handle, &buf, 1, write_cb); ASSERT(r == 0); diff --git a/deps/libuv/test/test-tcp-connect-error.c b/deps/libuv/test/test-tcp-connect-error.c index eab1eeb2..dda30a58 100644 --- a/deps/libuv/test/test-tcp-connect-error.c +++ b/deps/libuv/test/test-tcp-connect-error.c @@ -31,14 +31,14 @@ static int close_cb_called = 0; static void connect_cb(uv_connect_t* handle, int status) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); connect_cb_called++; } static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-tcp-connect-timeout.c b/deps/libuv/test/test-tcp-connect-timeout.c index a67d3252..3c34e54a 100644 --- a/deps/libuv/test/test-tcp-connect-timeout.c +++ b/deps/libuv/test/test-tcp-connect-timeout.c @@ -111,7 +111,7 @@ static int is_supported_system(void) { if (cnt != 3) { return 0; } - // relase >= 10.0.16299 + /* relase >= 10.0.16299 */ for (cnt = 0; cnt < 3; ++cnt) { if (semver[cnt] > min_semver[cnt]) return 1; diff --git a/deps/libuv/test/test-tcp-connect6-error.c b/deps/libuv/test/test-tcp-connect6-error.c index 91ac0a3a..2f6e9cbc 100644 --- a/deps/libuv/test/test-tcp-connect6-error.c +++ b/deps/libuv/test/test-tcp-connect6-error.c @@ -30,13 +30,13 @@ static int close_cb_called = 0; static void connect_cb(uv_connect_t* handle, int status) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); connect_cb_called++; } static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-tcp-create-socket-early.c b/deps/libuv/test/test-tcp-create-socket-early.c index b87e7324..f2bc60d7 100644 --- a/deps/libuv/test/test-tcp-create-socket-early.c +++ b/deps/libuv/test/test-tcp-create-socket-early.c @@ -44,7 +44,7 @@ static void on_connection(uv_stream_t* server, int status) { ASSERT(status == 0); handle = malloc(sizeof(*handle)); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); r = uv_tcp_init_ex(server->loop, handle, AF_INET); ASSERT(r == 0); diff --git a/deps/libuv/test/test-tcp-open.c b/deps/libuv/test/test-tcp-open.c index 0d92886d..7e49139c 100644 --- a/deps/libuv/test/test-tcp-open.c +++ b/deps/libuv/test/test-tcp-open.c @@ -96,7 +96,7 @@ static void alloc_cb(uv_handle_t* handle, static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } @@ -111,7 +111,7 @@ static void shutdown_cb(uv_shutdown_t* req, int status) { static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - ASSERT(tcp != NULL); + ASSERT_NOT_NULL(tcp); if (nread >= 0) { ASSERT(nread == 4); @@ -126,7 +126,7 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { static void read1_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { int i; - ASSERT(tcp != NULL); + ASSERT_NOT_NULL(tcp); if (nread >= 0) { for (i = 0; i < nread; ++i) @@ -140,7 +140,7 @@ static void read1_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { static void write_cb(uv_write_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); if (status) { fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); @@ -155,7 +155,7 @@ static void write1_cb(uv_write_t* req, int status) { uv_buf_t buf; int r; - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); if (status) { ASSERT(shutdown_cb_called); return; @@ -237,6 +237,7 @@ TEST_IMPL(tcp_open) { struct sockaddr_in addr; uv_os_sock_t sock; int r; + uv_tcp_t client2; ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); @@ -257,8 +258,6 @@ TEST_IMPL(tcp_open) { #ifndef _WIN32 { - uv_tcp_t client2; - r = uv_tcp_init(uv_default_loop(), &client2); ASSERT(r == 0); @@ -267,7 +266,9 @@ TEST_IMPL(tcp_open) { uv_close((uv_handle_t*) &client2, NULL); } -#endif /* !_WIN32 */ +#else /* _WIN32 */ + (void)client2; +#endif uv_run(uv_default_loop(), UV_RUN_DEFAULT); diff --git a/deps/libuv/test/test-tcp-write-fail.c b/deps/libuv/test/test-tcp-write-fail.c index 5256a9f4..58ee00fa 100644 --- a/deps/libuv/test/test-tcp-write-fail.c +++ b/deps/libuv/test/test-tcp-write-fail.c @@ -52,13 +52,13 @@ static void close_socket(uv_tcp_t* sock) { static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } static void write_cb(uv_write_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status != 0); fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); diff --git a/deps/libuv/test/test-tcp-write-to-half-open-connection.c b/deps/libuv/test/test-tcp-write-to-half-open-connection.c index 2fa2ae72..ae425131 100644 --- a/deps/libuv/test/test-tcp-write-to-half-open-connection.c +++ b/deps/libuv/test/test-tcp-write-to-half-open-connection.c @@ -110,7 +110,7 @@ TEST_IMPL(tcp_write_to_half_open_connection) { ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); loop = uv_default_loop(); - ASSERT(loop != NULL); + ASSERT_NOT_NULL(loop); r = uv_tcp_init(loop, &tcp_server); ASSERT(r == 0); diff --git a/deps/libuv/test/test-tcp-writealot.c b/deps/libuv/test/test-tcp-writealot.c index 7206fdc2..40dce96e 100644 --- a/deps/libuv/test/test-tcp-writealot.c +++ b/deps/libuv/test/test-tcp-writealot.c @@ -57,7 +57,7 @@ static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } @@ -82,7 +82,7 @@ static void shutdown_cb(uv_shutdown_t* req, int status) { static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - ASSERT(tcp != NULL); + ASSERT_NOT_NULL(tcp); if (nread >= 0) { bytes_received_done += nread; @@ -98,7 +98,7 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { static void write_cb(uv_write_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); if (status) { fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); @@ -152,7 +152,7 @@ TEST_IMPL(tcp_writealot) { ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); send_buffer = calloc(1, TOTAL_BYTES); - ASSERT(send_buffer != NULL); + ASSERT_NOT_NULL(send_buffer); r = uv_tcp_init(uv_default_loop(), &client); ASSERT(r == 0); diff --git a/deps/libuv/test/test-thread.c b/deps/libuv/test/test-thread.c index 432c2439..8de5a6f0 100644 --- a/deps/libuv/test/test-thread.c +++ b/deps/libuv/test/test-thread.c @@ -194,11 +194,11 @@ TEST_IMPL(threadpool_multiple_event_loops) { static void tls_thread(void* arg) { - ASSERT(NULL == uv_key_get(&tls_key)); + ASSERT_NULL(uv_key_get(&tls_key)); uv_key_set(&tls_key, arg); ASSERT(arg == uv_key_get(&tls_key)); uv_key_set(&tls_key, NULL); - ASSERT(NULL == uv_key_get(&tls_key)); + ASSERT_NULL(uv_key_get(&tls_key)); } @@ -206,7 +206,7 @@ TEST_IMPL(thread_local_storage) { char name[] = "main"; uv_thread_t threads[2]; ASSERT(0 == uv_key_create(&tls_key)); - ASSERT(NULL == uv_key_get(&tls_key)); + ASSERT_NULL(uv_key_get(&tls_key)); uv_key_set(&tls_key, name); ASSERT(name == uv_key_get(&tls_key)); ASSERT(0 == uv_thread_create(threads + 0, tls_thread, threads + 0)); diff --git a/deps/libuv/test/test-threadpool-cancel.c b/deps/libuv/test/test-threadpool-cancel.c index be252c6f..1e867c51 100644 --- a/deps/libuv/test/test-threadpool-cancel.c +++ b/deps/libuv/test/test-threadpool-cancel.c @@ -98,7 +98,7 @@ static void getaddrinfo_cb(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { ASSERT(status == UV_EAI_CANCELED); - ASSERT(res == NULL); + ASSERT_NULL(res); uv_freeaddrinfo(res); /* Should not crash. */ } @@ -108,8 +108,8 @@ static void getnameinfo_cb(uv_getnameinfo_t* handle, const char* hostname, const char* service) { ASSERT(status == UV_EAI_CANCELED); - ASSERT(hostname == NULL); - ASSERT(service == NULL); + ASSERT_NULL(hostname); + ASSERT_NULL(service); } diff --git a/deps/libuv/test/test-timer-again.c b/deps/libuv/test/test-timer-again.c index e87d2edf..834b59d7 100644 --- a/deps/libuv/test/test-timer-again.c +++ b/deps/libuv/test/test-timer-again.c @@ -35,7 +35,7 @@ static uint64_t start_time; static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } diff --git a/deps/libuv/test/test-timer.c b/deps/libuv/test/test-timer.c index ee8331c2..d0921a96 100644 --- a/deps/libuv/test/test-timer.c +++ b/deps/libuv/test/test-timer.c @@ -37,7 +37,7 @@ static uv_timer_t huge_timer2; static void once_close_cb(uv_handle_t* handle) { printf("ONCE_CLOSE_CB\n"); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); ASSERT(0 == uv_is_active(handle)); once_close_cb_called++; @@ -47,7 +47,7 @@ static void once_close_cb(uv_handle_t* handle) { static void once_cb(uv_timer_t* handle) { printf("ONCE_CB %d\n", once_cb_called); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); ASSERT(0 == uv_is_active((uv_handle_t*) handle)); once_cb_called++; @@ -62,7 +62,7 @@ static void once_cb(uv_timer_t* handle) { static void repeat_close_cb(uv_handle_t* handle) { printf("REPEAT_CLOSE_CB\n"); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); repeat_close_cb_called++; } @@ -71,7 +71,7 @@ static void repeat_close_cb(uv_handle_t* handle) { static void repeat_cb(uv_timer_t* handle) { printf("REPEAT_CB\n"); - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); ASSERT(1 == uv_is_active((uv_handle_t*) handle)); repeat_cb_called++; diff --git a/deps/libuv/test/test-tty-duplicate-key.c b/deps/libuv/test/test-tty-duplicate-key.c index 1ec2f369..efd79e14 100644 --- a/deps/libuv/test/test-tty-duplicate-key.c +++ b/deps/libuv/test/test-tty-duplicate-key.c @@ -55,7 +55,7 @@ static void print_err_msg(const char* expect, ssize_t expect_len, static void tty_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf) { buf->base = malloc(size); - ASSERT(buf->base != NULL); + ASSERT_NOT_NULL(buf->base); buf->len = size; } diff --git a/deps/libuv/test/test-tty-escape-sequence-processing.c b/deps/libuv/test/test-tty-escape-sequence-processing.c index c4461e91..ef34e592 100644 --- a/deps/libuv/test/test-tty-escape-sequence-processing.c +++ b/deps/libuv/test/test-tty-escape-sequence-processing.c @@ -212,9 +212,9 @@ static void capture_screen(uv_tty_t* tty_out, struct captured_screen* cs) { origin.X = 0; origin.Y = cs->si.csbi.srWindow.Top; cs->text = malloc(cs->si.length * sizeof(*cs->text)); - ASSERT(cs->text != NULL); + ASSERT_NOT_NULL(cs->text); cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes)); - ASSERT(cs->attributes != NULL); + ASSERT_NOT_NULL(cs->attributes); ASSERT(ReadConsoleOutputCharacter( tty_out->handle, cs->text, cs->si.length, origin, &length)); ASSERT((unsigned int) cs->si.length == length); diff --git a/deps/libuv/test/test-tty.c b/deps/libuv/test/test-tty.c index a9d38f22..ff7d388d 100644 --- a/deps/libuv/test/test-tty.c +++ b/deps/libuv/test/test-tty.c @@ -426,6 +426,9 @@ TEST_IMPL(tty_pty) { #if defined(__QEMU__) RETURN_SKIP("Test does not currently work in QEMU"); #endif +#if defined(__ASAN__) + RETURN_SKIP("Test does not currently work in ASAN"); +#endif #if defined(__APPLE__) || \ defined(__DragonFly__) || \ diff --git a/deps/libuv/test/test-udp-alloc-cb-fail.c b/deps/libuv/test/test-udp-alloc-cb-fail.c index 0cee09c9..6b098016 100644 --- a/deps/libuv/test/test-udp-alloc-cb-fail.c +++ b/deps/libuv/test/test-udp-alloc-cb-fail.c @@ -83,7 +83,7 @@ static void cl_recv_cb(uv_udp_t* handle, static void cl_send_cb(uv_udp_send_t* req, int status) { int r; - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); @@ -95,7 +95,7 @@ static void cl_send_cb(uv_udp_send_t* req, int status) { static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); @@ -121,14 +121,14 @@ static void sv_recv_cb(uv_udp_t* handle, if (nread == 0) { /* Returning unused buffer. Don't count towards sv_recv_cb_called */ - ASSERT(addr == NULL); + ASSERT_NULL(addr); return; } CHECK_HANDLE(handle); ASSERT(flags == 0); - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(nread == 4); ASSERT(!memcmp("PING", rcvbuf->base, nread)); @@ -136,7 +136,7 @@ static void sv_recv_cb(uv_udp_t* handle, ASSERT(r == 0); req = malloc(sizeof *req); - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); sndbuf = uv_buf_init("PONG", 4); r = uv_udp_send(req, handle, &sndbuf, 1, addr, sv_send_cb); diff --git a/deps/libuv/test/test-udp-connect.c b/deps/libuv/test/test-udp-connect.c index 41ace117..89ca1a84 100644 --- a/deps/libuv/test/test-udp-connect.c +++ b/deps/libuv/test/test-udp-connect.c @@ -61,7 +61,7 @@ static void close_cb(uv_handle_t* handle) { static void cl_send_cb(uv_udp_send_t* req, int status) { int r; - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); if (++cl_send_cb_called == 1) { @@ -87,7 +87,7 @@ static void sv_recv_cb(uv_udp_t* handle, unsigned flags) { if (nread > 0) { ASSERT(nread == 4); - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(memcmp("EXIT", rcvbuf->base, nread) == 0); if (++sv_recv_cb_called == 4) { uv_close((uv_handle_t*) &server, close_cb); @@ -124,7 +124,7 @@ TEST_IMPL(udp_connect) { buf = uv_buf_init("EXIT", 4); - // connect() to INADDR_ANY fails on Windows wih WSAEADDRNOTAVAIL + /* connect() to INADDR_ANY fails on Windows wih WSAEADDRNOTAVAIL */ ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &tmp_addr)); r = uv_udp_connect(&client, (const struct sockaddr*) &tmp_addr); #ifdef _WIN32 diff --git a/deps/libuv/test/test-udp-mmsg.c b/deps/libuv/test/test-udp-mmsg.c index 08628a50..fb241151 100644 --- a/deps/libuv/test/test-udp-mmsg.c +++ b/deps/libuv/test/test-udp-mmsg.c @@ -54,7 +54,7 @@ static void alloc_cb(uv_handle_t* handle, /* Actually malloc to exercise free'ing the buffer later */ buf->base = malloc(buffer_size); - ASSERT(buf->base != NULL); + ASSERT_NOT_NULL(buf->base); buf->len = buffer_size; alloc_cb_called++; } @@ -77,13 +77,13 @@ static void recv_cb(uv_udp_t* handle, /* free and return if this is a mmsg free-only callback invocation */ if (flags & UV_UDP_MMSG_FREE) { ASSERT_EQ(nread, 0); - ASSERT(addr == NULL); + ASSERT_NULL(addr); free(rcvbuf->base); return; } ASSERT_EQ(nread, 4); - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT_MEM_EQ("PING", rcvbuf->base, nread); recv_cb_called++; diff --git a/deps/libuv/test/test-udp-multicast-interface.c b/deps/libuv/test/test-udp-multicast-interface.c index 9d36098d..bd9a61c9 100644 --- a/deps/libuv/test/test-udp-multicast-interface.c +++ b/deps/libuv/test/test-udp-multicast-interface.c @@ -43,7 +43,7 @@ static void close_cb(uv_handle_t* handle) { static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0 || status == UV_ENETUNREACH || status == UV_EPERM); CHECK_HANDLE(req->handle); diff --git a/deps/libuv/test/test-udp-multicast-interface6.c b/deps/libuv/test/test-udp-multicast-interface6.c index 23a68a00..be11514c 100644 --- a/deps/libuv/test/test-udp-multicast-interface6.c +++ b/deps/libuv/test/test-udp-multicast-interface6.c @@ -43,7 +43,7 @@ static void close_cb(uv_handle_t* handle) { static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); diff --git a/deps/libuv/test/test-udp-multicast-join.c b/deps/libuv/test/test-udp-multicast-join.c index cb3ff871..9e603a84 100644 --- a/deps/libuv/test/test-udp-multicast-join.c +++ b/deps/libuv/test/test-udp-multicast-join.c @@ -60,7 +60,7 @@ static void close_cb(uv_handle_t* handle) { static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); @@ -103,11 +103,11 @@ static void cl_recv_cb(uv_udp_t* handle, if (nread == 0) { /* Returning unused buffer. Don't count towards cl_recv_cb_called */ - ASSERT(addr == NULL); + ASSERT_NULL(addr); return; } - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(nread == 4); ASSERT(!memcmp("PING", buf->base, nread)); diff --git a/deps/libuv/test/test-udp-multicast-join6.c b/deps/libuv/test/test-udp-multicast-join6.c index 40aa577d..e67c5ee5 100644 --- a/deps/libuv/test/test-udp-multicast-join6.c +++ b/deps/libuv/test/test-udp-multicast-join6.c @@ -72,7 +72,7 @@ static void close_cb(uv_handle_t* handle) { static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); @@ -115,11 +115,11 @@ static void cl_recv_cb(uv_udp_t* handle, if (nread == 0) { /* Returning unused buffer. Don't count towards cl_recv_cb_called */ - ASSERT(addr == NULL); + ASSERT_NULL(addr); return; } - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(nread == 4); ASSERT(!memcmp("PING", buf->base, nread)); diff --git a/deps/libuv/test/test-udp-multicast-ttl.c b/deps/libuv/test/test-udp-multicast-ttl.c index e92608be..fbddd909 100644 --- a/deps/libuv/test/test-udp-multicast-ttl.c +++ b/deps/libuv/test/test-udp-multicast-ttl.c @@ -43,7 +43,7 @@ static void close_cb(uv_handle_t* handle) { static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0 || status == UV_ENETUNREACH || status == UV_EPERM); CHECK_HANDLE(req->handle); diff --git a/deps/libuv/test/test-udp-open.c b/deps/libuv/test/test-udp-open.c index dee408ba..f5136b6d 100644 --- a/deps/libuv/test/test-udp-open.c +++ b/deps/libuv/test/test-udp-open.c @@ -91,7 +91,7 @@ static void alloc_cb(uv_handle_t* handle, static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); + ASSERT_NOT_NULL(handle); close_cb_called++; } @@ -109,13 +109,13 @@ static void recv_cb(uv_udp_t* handle, if (nread == 0) { /* Returning unused buffer. Don't count towards sv_recv_cb_called */ - ASSERT(addr == NULL); + ASSERT_NULL(addr); return; } ASSERT(flags == 0); - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(nread == 4); ASSERT(memcmp("PING", buf->base, nread) == 0); @@ -127,7 +127,7 @@ static void recv_cb(uv_udp_t* handle, static void send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); send_cb_called++; @@ -138,7 +138,7 @@ static void send_cb(uv_udp_send_t* req, int status) { TEST_IMPL(udp_open) { struct sockaddr_in addr; uv_buf_t buf = uv_buf_init("PING", 4); - uv_udp_t client; + uv_udp_t client, client2; uv_os_sock_t sock; int r; @@ -169,8 +169,6 @@ TEST_IMPL(udp_open) { #ifndef _WIN32 { - uv_udp_t client2; - r = uv_udp_init(uv_default_loop(), &client2); ASSERT(r == 0); @@ -179,7 +177,9 @@ TEST_IMPL(udp_open) { uv_close((uv_handle_t*) &client2, NULL); } -#endif /* !_WIN32 */ +#else /* _WIN32 */ + (void)client2; +#endif uv_run(uv_default_loop(), UV_RUN_DEFAULT); diff --git a/deps/libuv/test/test-udp-send-and-recv.c b/deps/libuv/test/test-udp-send-and-recv.c index 1f01188b..d6020905 100644 --- a/deps/libuv/test/test-udp-send-and-recv.c +++ b/deps/libuv/test/test-udp-send-and-recv.c @@ -73,11 +73,11 @@ static void cl_recv_cb(uv_udp_t* handle, if (nread == 0) { /* Returning unused buffer. Don't count towards cl_recv_cb_called */ - ASSERT(addr == NULL); + ASSERT_NULL(addr); return; } - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(nread == 4); ASSERT(!memcmp("PONG", buf->base, nread)); @@ -90,7 +90,7 @@ static void cl_recv_cb(uv_udp_t* handle, static void cl_send_cb(uv_udp_send_t* req, int status) { int r; - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); @@ -102,7 +102,7 @@ static void cl_send_cb(uv_udp_send_t* req, int status) { static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); @@ -128,14 +128,14 @@ static void sv_recv_cb(uv_udp_t* handle, if (nread == 0) { /* Returning unused buffer. Don't count towards sv_recv_cb_called */ - ASSERT(addr == NULL); + ASSERT_NULL(addr); return; } CHECK_HANDLE(handle); ASSERT(flags == 0); - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(nread == 4); ASSERT(!memcmp("PING", rcvbuf->base, nread)); @@ -147,7 +147,7 @@ static void sv_recv_cb(uv_udp_t* handle, ASSERT(r == 0); req = malloc(sizeof *req); - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); sndbuf = uv_buf_init("PONG", 4); r = uv_udp_send(req, handle, &sndbuf, 1, addr, sv_send_cb); diff --git a/deps/libuv/test/test-udp-send-hang-loop.c b/deps/libuv/test/test-udp-send-hang-loop.c index bf4dfebf..072070b6 100644 --- a/deps/libuv/test/test-udp-send-hang-loop.c +++ b/deps/libuv/test/test-udp-send-hang-loop.c @@ -44,7 +44,7 @@ static void send_cb(uv_udp_send_t* req, int status); static void idle_cb(uv_idle_t* handle) { int r; - ASSERT(send_req.handle == NULL); + ASSERT_NULL(send_req.handle); CHECK_OBJECT(handle, uv_idle_t, idle_handle); ASSERT(0 == uv_idle_stop(handle)); @@ -66,7 +66,7 @@ static void idle_cb(uv_idle_t* handle) { static void send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0 || status == UV_ENETUNREACH); CHECK_OBJECT(req->handle, uv_udp_t, client); CHECK_OBJECT(req, uv_udp_send_t, send_req); diff --git a/deps/libuv/test/test-udp-send-immediate.c b/deps/libuv/test/test-udp-send-immediate.c index 1011aa46..a1c95d34 100644 --- a/deps/libuv/test/test-udp-send-immediate.c +++ b/deps/libuv/test/test-udp-send-immediate.c @@ -56,7 +56,7 @@ static void close_cb(uv_handle_t* handle) { static void cl_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); CHECK_HANDLE(req->handle); @@ -75,14 +75,14 @@ static void sv_recv_cb(uv_udp_t* handle, if (nread == 0) { /* Returning unused buffer. Don't count towards sv_recv_cb_called */ - ASSERT(addr == NULL); + ASSERT_NULL(addr); return; } CHECK_HANDLE(handle); ASSERT(flags == 0); - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(nread == 4); ASSERT(memcmp("PING", rcvbuf->base, nread) == 0 || memcmp("PANG", rcvbuf->base, nread) == 0); diff --git a/deps/libuv/test/test-udp-send-unreachable.c b/deps/libuv/test/test-udp-send-unreachable.c index c6500320..c67a23b3 100644 --- a/deps/libuv/test/test-udp-send-unreachable.c +++ b/deps/libuv/test/test-udp-send-unreachable.c @@ -27,9 +27,10 @@ #include #define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &client) + ASSERT((uv_udp_t*)(handle) == &client || (uv_udp_t*)(handle) == &client2) static uv_udp_t client; +static uv_udp_t client2; static uv_timer_t timer; static int send_cb_called; @@ -37,6 +38,7 @@ static int recv_cb_called; static int close_cb_called; static int alloc_cb_called; static int timer_cb_called; +static int can_recverr; static void alloc_cb(uv_handle_t* handle, @@ -44,7 +46,7 @@ static void alloc_cb(uv_handle_t* handle, uv_buf_t* buf) { static char slab[65536]; CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); + ASSERT_LE(suggested_size, sizeof(slab)); buf->base = slab; buf->len = sizeof(slab); alloc_cb_called++; @@ -52,18 +54,25 @@ static void alloc_cb(uv_handle_t* handle, static void close_cb(uv_handle_t* handle) { - ASSERT(1 == uv_is_closing(handle)); + ASSERT_EQ(1, uv_is_closing(handle)); close_cb_called++; } static void send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); ASSERT(status == 0); + ASSERT_EQ(status, 0); CHECK_HANDLE(req->handle); send_cb_called++; } +static void send_cb_recverr(uv_udp_send_t* req, int status) { + ASSERT_PTR_NE(req, NULL); + ASSERT(status == 0 || status == UV_ECONNREFUSED); + CHECK_HANDLE(req->handle); + send_cb_called++; +} static void recv_cb(uv_udp_t* handle, ssize_t nread, @@ -77,17 +86,19 @@ static void recv_cb(uv_udp_t* handle, ASSERT(0 && "unexpected error"); } else if (nread == 0) { /* Returning unused buffer */ - ASSERT(addr == NULL); + ASSERT_NULL(addr); } else { - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); } } static void timer_cb(uv_timer_t* h) { - ASSERT(h == &timer); + ASSERT_PTR_EQ(h, &timer); timer_cb_called++; uv_close((uv_handle_t*) &client, close_cb); + if (can_recverr) + uv_close((uv_handle_t*) &client2, close_cb); uv_close((uv_handle_t*) h, close_cb); } @@ -95,27 +106,33 @@ static void timer_cb(uv_timer_t* h) { TEST_IMPL(udp_send_unreachable) { struct sockaddr_in addr; struct sockaddr_in addr2; - uv_udp_send_t req1, req2; + struct sockaddr_in addr3; + uv_udp_send_t req1, req2, req3, req4; uv_buf_t buf; int r; - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT_2, &addr2)); +#ifdef __linux__ + can_recverr = 1; +#endif + + ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT_2, &addr2)); + ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT_3, &addr3)); r = uv_timer_init( uv_default_loop(), &timer ); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_timer_start( &timer, timer_cb, 1000, 0 ); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_udp_bind(&client, (const struct sockaddr*) &addr2, 0); - ASSERT(r == 0); + ASSERT_EQ(r, 0); r = uv_udp_recv_start(&client, alloc_cb, recv_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); /* client sends "PING", then "PANG" */ buf = uv_buf_init("PING", 4); @@ -126,7 +143,7 @@ TEST_IMPL(udp_send_unreachable) { 1, (const struct sockaddr*) &addr, send_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); buf = uv_buf_init("PANG", 4); @@ -136,14 +153,48 @@ TEST_IMPL(udp_send_unreachable) { 1, (const struct sockaddr*) &addr, send_cb); - ASSERT(r == 0); + ASSERT_EQ(r, 0); + + if (can_recverr) { + r = uv_udp_init(uv_default_loop(), &client2); + ASSERT_EQ(r, 0); + + r = uv_udp_bind(&client2, + (const struct sockaddr*) &addr3, + UV_UDP_LINUX_RECVERR); + ASSERT_EQ(r, 0); + + r = uv_udp_recv_start(&client2, alloc_cb, recv_cb); + ASSERT_EQ(r, 0); + + /* client sends "PING", then "PANG" */ + buf = uv_buf_init("PING", 4); + + r = uv_udp_send(&req3, + &client2, + &buf, + 1, + (const struct sockaddr*) &addr, + send_cb_recverr); + ASSERT_EQ(r, 0); + + buf = uv_buf_init("PANG", 4); + + r = uv_udp_send(&req4, + &client2, + &buf, + 1, + (const struct sockaddr*) &addr, + send_cb_recverr); + ASSERT_EQ(r, 0); + } uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(send_cb_called == 2); - ASSERT(recv_cb_called == alloc_cb_called); - ASSERT(timer_cb_called == 1); - ASSERT(close_cb_called == 2); + ASSERT_EQ(send_cb_called, (long)(can_recverr ? 4 : 2)); + ASSERT_EQ(recv_cb_called, alloc_cb_called); + ASSERT_EQ(timer_cb_called, 1); + ASSERT_EQ(close_cb_called, (long)(can_recverr ? 3 : 2)); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/libuv/test/test-udp-try-send.c b/deps/libuv/test/test-udp-try-send.c index a31d3822..85caaaca 100644 --- a/deps/libuv/test/test-udp-try-send.c +++ b/deps/libuv/test/test-udp-try-send.c @@ -63,12 +63,12 @@ static void sv_recv_cb(uv_udp_t* handle, ASSERT(nread > 0); if (nread == 0) { - ASSERT(addr == NULL); + ASSERT_NULL(addr); return; } ASSERT(nread == 4); - ASSERT(addr != NULL); + ASSERT_NOT_NULL(addr); ASSERT(memcmp("EXIT", rcvbuf->base, nread) == 0); uv_close((uv_handle_t*) handle, close_cb); diff --git a/deps/libuv/tools/make_dist_html.py b/deps/libuv/tools/make_dist_html.py index 7a19d3e1..4833b1b8 100644 --- a/deps/libuv/tools/make_dist_html.py +++ b/deps/libuv/tools/make_dist_html.py @@ -1,6 +1,4 @@ -#!/usr/bin/python - -from __future__ import print_function +#!/usr/bin/python3 import itertools import os @@ -84,7 +82,7 @@ EXE = r''' ''' def version(tag): - return map(int, re.match('^v(\d+)\.(\d+)\.(\d+)', tag).groups()) + return list(map(int, re.match('^v(\d+)\.(\d+)\.(\d+)', tag).groups())) def major_minor(tag): return version(tag)[:2] @@ -114,7 +112,7 @@ def groups_for(groups, n=4): if __name__ == '__main__': os.chdir(os.path.dirname(__file__)) - tags = subprocess.check_output(['git', 'tag']) + tags = subprocess.check_output(['git', 'tag'], text=True) tags = [tag for tag in tags.split('\n') if tag.startswith('v')] tags.sort(key=version, reverse=True) groups = [group_for(list(g)) for _, g in itertools.groupby(tags, major_minor)]