From 42359ab582d89edb25907b7bf636c65436acf08e Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Mon, 26 Jul 2021 09:59:29 +0200 Subject: [PATCH] deps: upgrade to libuv 1.42.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notable changes: - win,tcp: make `uv_close()` work more like unix. - cleanup,win: Remove `_WIN32` guards on threadpool. - more errno mappings and fixes. - higher performance try-writes. - fix string encoding issue of `uv_os_gethostname()` (note: MINGW-W64 upstream is broken on i686 due to https://sourceforge.net/p/mingw-w64/bugs/899/). - zOS support. - Workarounds for a `copy_file_range()` kernel bug. - Better support for TSan. - darwin: use `RLIMIT_STACK` for fsevents pthread. - fix a bug that would cause libuv to hang if the user called `uv_shutdown()`. - darwin: fix `uv_barrier()` race condition. PR-URL: https://github.com/nodejs/node/pull/39525 Fixes: https://github.com/nodejs/node/issues/39502 Reviewed-By: Jiawen Geng Reviewed-By: Tobias Nießen Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- deps/uv/.mailmap | 4 + deps/uv/.readthedocs.yaml | 11 + deps/uv/AUTHORS | 24 +- deps/uv/CMakeLists.txt | 63 ++- deps/uv/CONTRIBUTING.md | 10 +- deps/uv/ChangeLog | 155 +++++++ deps/uv/LINKS.md | 101 +++++ deps/uv/MAINTAINERS.md | 1 + deps/uv/Makefile.am | 10 +- deps/uv/README.md | 12 +- deps/uv/configure.ac | 9 +- deps/uv/docs/requirements.txt | 42 ++ deps/uv/docs/src/errors.rst | 8 + deps/uv/docs/src/index.rst | 2 +- deps/uv/docs/src/misc.rst | 2 +- deps/uv/docs/src/stream.rst | 20 +- deps/uv/docs/src/udp.rst | 16 +- deps/uv/include/uv.h | 15 +- deps/uv/include/uv/errno.h | 12 + deps/uv/include/uv/tree.h | 2 +- deps/uv/include/uv/version.h | 2 +- deps/uv/src/inet.c | 3 +- deps/uv/src/threadpool.c | 2 - deps/uv/src/unix/atomic-ops.h | 6 +- deps/uv/src/unix/core.c | 23 +- deps/uv/src/unix/darwin.c | 12 +- deps/uv/src/unix/epoll.c | 422 ++++++++++++++++++ deps/uv/src/unix/freebsd.c | 15 +- deps/uv/src/unix/fs.c | 62 ++- deps/uv/src/unix/fsevents.c | 23 +- deps/uv/src/unix/getaddrinfo.c | 3 - deps/uv/src/unix/ibmi.c | 48 +- deps/uv/src/unix/internal.h | 24 +- deps/uv/src/unix/linux-core.c | 409 +---------------- deps/uv/src/unix/linux-inotify.c | 2 +- deps/uv/src/unix/linux-syscalls.h | 3 - deps/uv/src/unix/os390-proctitle.c | 136 ++++++ deps/uv/src/unix/os390-syscalls.c | 57 +-- deps/uv/src/unix/os390-syscalls.h | 2 +- deps/uv/src/unix/os390.c | 136 +----- deps/uv/src/unix/poll.c | 5 +- deps/uv/src/unix/process.c | 63 ++- deps/uv/src/unix/proctitle.c | 3 - deps/uv/src/unix/stream.c | 207 ++++----- deps/uv/src/unix/sunos.c | 11 + deps/uv/src/unix/thread.c | 12 +- deps/uv/src/unix/tty.c | 18 + deps/uv/src/unix/udp.c | 32 +- deps/uv/src/uv-common.c | 6 +- deps/uv/src/uv-common.h | 5 +- deps/uv/src/win/atomicops-inl.h | 8 +- deps/uv/src/win/error.c | 2 +- deps/uv/src/win/fs.c | 2 +- deps/uv/src/win/poll.c | 3 +- deps/uv/src/win/process.c | 2 +- deps/uv/src/win/stream.c | 10 + deps/uv/src/win/tcp.c | 117 +++-- deps/uv/src/win/udp.c | 4 +- deps/uv/src/win/util.c | 17 +- deps/uv/test/benchmark-async-pummel.c | 2 +- deps/uv/test/benchmark-async.c | 2 +- deps/uv/test/benchmark-million-async.c | 2 +- deps/uv/test/benchmark-million-timers.c | 2 +- deps/uv/test/benchmark-multi-accept.c | 8 +- deps/uv/test/benchmark-pound.c | 8 +- deps/uv/test/benchmark-tcp-write-batch.c | 4 +- deps/uv/test/benchmark-udp-pummel.c | 14 +- deps/uv/test/blackhole-server.c | 2 +- deps/uv/test/dns-server.c | 2 +- deps/uv/test/echo-server.c | 59 ++- deps/uv/test/run-benchmarks.c | 12 +- deps/uv/test/run-tests.c | 14 +- deps/uv/test/runner-unix.c | 4 +- deps/uv/test/runner.c | 42 +- deps/uv/test/task.h | 1 + deps/uv/test/test-active.c | 2 +- deps/uv/test/test-async.c | 2 +- deps/uv/test/test-callback-stack.c | 2 +- deps/uv/test/test-close-order.c | 2 +- deps/uv/test/test-default-loop-close.c | 4 +- deps/uv/test/test-delayed-accept.c | 18 +- deps/uv/test/test-dlerror.c | 16 +- deps/uv/test/test-error.c | 8 +- deps/uv/test/test-fs-event.c | 8 +- deps/uv/test/test-fs-poll.c | 4 +- deps/uv/test/test-fs-readdir.c | 16 +- deps/uv/test/test-fs.c | 55 +-- deps/uv/test/test-get-currentexe.c | 2 +- deps/uv/test/test-get-passwd.c | 14 +- deps/uv/test/test-getaddrinfo.c | 4 +- deps/uv/test/test-getnameinfo.c | 6 +- deps/uv/test/test-getsockname.c | 2 +- deps/uv/test/test-getters-setters.c | 14 +- .../test-ipc-heavy-traffic-deadlock-bug.c | 2 +- deps/uv/test/test-ipc.c | 2 +- deps/uv/test/test-list.h | 15 + deps/uv/test/test-loop-handles.c | 4 +- deps/uv/test/test-multiple-listen.c | 6 +- ...-not-readable-nor-writable-on-read-error.c | 104 +++++ deps/uv/test/test-not-readable-on-eof.c | 103 +++++ .../test/test-not-writable-after-shutdown.c | 69 +++ deps/uv/test/test-pipe-bind-error.c | 2 +- deps/uv/test/test-pipe-connect-error.c | 2 +- deps/uv/test/test-pipe-connect-prepare.c | 2 +- deps/uv/test/test-pipe-getsockname.c | 2 +- deps/uv/test/test-pipe-server-close.c | 2 +- deps/uv/test/test-pipe-set-non-blocking.c | 4 +- deps/uv/test/test-poll.c | 4 +- deps/uv/test/test-ref.c | 2 +- deps/uv/test/test-shutdown-simultaneous.c | 135 ++++++ deps/uv/test/test-signal-multiple-loops.c | 2 +- deps/uv/test/test-signal-pending-on-close.c | 4 +- deps/uv/test/test-spawn.c | 12 +- deps/uv/test/test-tcp-alloc-cb-fail.c | 2 +- deps/uv/test/test-tcp-bind-error.c | 2 +- deps/uv/test/test-tcp-bind6-error.c | 2 +- deps/uv/test/test-tcp-close.c | 2 +- deps/uv/test/test-tcp-connect-error.c | 4 +- deps/uv/test/test-tcp-connect6-error.c | 4 +- deps/uv/test/test-tcp-create-socket-early.c | 2 +- deps/uv/test/test-tcp-open.c | 17 +- deps/uv/test/test-tcp-write-fail.c | 4 +- .../test-tcp-write-to-half-open-connection.c | 2 +- deps/uv/test/test-tcp-writealot.c | 8 +- deps/uv/test/test-thread.c | 6 +- deps/uv/test/test-threadpool-cancel.c | 6 +- deps/uv/test/test-timer-again.c | 2 +- deps/uv/test/test-timer.c | 8 +- deps/uv/test/test-tty-duplicate-key.c | 2 +- .../test-tty-escape-sequence-processing.c | 4 +- deps/uv/test/test-udp-alloc-cb-fail.c | 10 +- deps/uv/test/test-udp-connect.c | 4 +- deps/uv/test/test-udp-mmsg.c | 6 +- deps/uv/test/test-udp-multicast-interface.c | 2 +- deps/uv/test/test-udp-multicast-interface6.c | 2 +- deps/uv/test/test-udp-multicast-join.c | 6 +- deps/uv/test/test-udp-multicast-join6.c | 6 +- deps/uv/test/test-udp-multicast-ttl.c | 2 +- deps/uv/test/test-udp-open.c | 16 +- deps/uv/test/test-udp-send-and-recv.c | 14 +- deps/uv/test/test-udp-send-hang-loop.c | 4 +- deps/uv/test/test-udp-send-immediate.c | 6 +- deps/uv/test/test-udp-send-unreachable.c | 93 +++- deps/uv/test/test-udp-try-send.c | 4 +- deps/uv/uv.gyp | 2 + 145 files changed, 2353 insertions(+), 1172 deletions(-) create mode 100644 deps/uv/.readthedocs.yaml create mode 100644 deps/uv/LINKS.md create mode 100644 deps/uv/docs/requirements.txt create mode 100644 deps/uv/src/unix/epoll.c create mode 100644 deps/uv/src/unix/os390-proctitle.c create mode 100644 deps/uv/test/test-not-readable-nor-writable-on-read-error.c create mode 100644 deps/uv/test/test-not-readable-on-eof.c create mode 100644 deps/uv/test/test-not-writable-after-shutdown.c create mode 100644 deps/uv/test/test-shutdown-simultaneous.c diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 045b7702d958de..7be85aba980e40 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.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 @@ -53,4 +56,5 @@ gengjiawen jBarz jBarz ptlomholt +tjarlama <59913901+tjarlama@users.noreply.github.com> zlargon diff --git a/deps/uv/.readthedocs.yaml b/deps/uv/.readthedocs.yaml new file mode 100644 index 00000000000000..e53b9f3e84be0a --- /dev/null +++ b/deps/uv/.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/uv/AUTHORS b/deps/uv/AUTHORS index 9f327af9f8303f..741bcc708cb5e0 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/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 @@ -459,3 +457,25 @@ 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/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index c8e881d18f503e..148d0e68992c83 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -34,7 +34,8 @@ 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_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_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 @@ -209,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() @@ -253,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") @@ -266,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) @@ -279,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") @@ -303,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") @@ -349,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}) @@ -360,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) @@ -457,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 @@ -489,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 @@ -582,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/uv/CONTRIBUTING.md b/deps/uv/CONTRIBUTING.md index b0abe3b40eaa25..d37c51d6363856 100644 --- a/deps/uv/CONTRIBUTING.md +++ b/deps/uv/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/uv/ChangeLog b/deps/uv/ChangeLog index d0eaf9fe34a20f..4f2a4bc91dd0d0 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,158 @@ +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: diff --git a/deps/uv/LINKS.md b/deps/uv/LINKS.md new file mode 100644 index 00000000000000..b8204e56e160d2 --- /dev/null +++ b/deps/uv/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/uv/MAINTAINERS.md b/deps/uv/MAINTAINERS.md index 268251e615a13d..fb7e5ef34172c5 100644 --- a/deps/uv/MAINTAINERS.md +++ b/deps/uv/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/uv/Makefile.am b/deps/uv/Makefile.am index e8bab4963dda78..5830003c1e0736 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -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 \ @@ -238,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 \ @@ -388,7 +392,8 @@ libuv_la_CFLAGS += -D_GNU_SOURCE libuv_la_SOURCES += src/unix/android-ifaddrs.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 @@ -469,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/uv/README.md b/deps/uv/README.md index f6c73709cc5b82..a9a8a9d1179e2f 100644 --- a/deps/uv/README.md +++ b/deps/uv/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 @@ -308,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/uv/configure.ac b/deps/uv/configure.ac index 4bdc7fd3f532b8..1fbb5c8c822f41 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.41.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,10 @@ 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]) @@ -43,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/uv/docs/requirements.txt b/deps/uv/docs/requirements.txt new file mode 100644 index 00000000000000..8386e0178fabac --- /dev/null +++ b/deps/uv/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/uv/docs/src/errors.rst b/deps/uv/docs/src/errors.rst index c2daa8584eb9c3..c7240f3546f77e 100644 --- a/deps/uv/docs/src/errors.rst +++ b/deps/uv/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/uv/docs/src/index.rst b/deps/uv/docs/src/index.rst index f696dc16279bf4..4b5d4d2c51195a 100644 --- a/deps/uv/docs/src/index.rst +++ b/deps/uv/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/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index b2725c399e431d..9a8595e577c3ea 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/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/uv/docs/src/stream.rst b/deps/uv/docs/src/stream.rst index 429ebdab28f5f1..0b42c4b3f8ca82 100644 --- a/deps/uv/docs/src/stream.rst +++ b/deps/uv/docs/src/stream.rst @@ -151,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: @@ -188,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) @@ -202,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/uv/docs/src/udp.rst b/deps/uv/docs/src/udp.rst index 827fbaad6c0476..009767d55dc74e 100644 --- a/deps/uv/docs/src/udp.rst +++ b/deps/uv/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. */ @@ -178,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. @@ -395,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/uv/include/uv.h b/deps/uv/include/uv.h index 1e1fc94bfcc3dc..77503bde9f28e4 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/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) \ @@ -526,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 { @@ -626,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. */ diff --git a/deps/uv/include/uv/errno.h b/deps/uv/include/uv/errno.h index aadce9c14c9a6c..71906b3f5e65e6 100644 --- a/deps/uv/include/uv/errno.h +++ b/deps/uv/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/uv/include/uv/tree.h b/deps/uv/include/uv/tree.h index f936416e3d8313..2b28835fdedef2 100644 --- a/deps/uv/include/uv/tree.h +++ b/deps/uv/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/uv/include/uv/version.h b/deps/uv/include/uv/version.h index e94f1e02e15354..d5ba36c3ba9a1a 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,7 +31,7 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 41 +#define UV_VERSION_MINOR 42 #define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/inet.c b/deps/uv/src/inet.c index 698ab232e53714..ddabf22fa52a0d 100644 --- a/deps/uv/src/inet.c +++ b/deps/uv/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/uv/src/threadpool.c b/deps/uv/src/threadpool.c index 0998938f3e0d16..869ae95f58c7b8 100644 --- a/deps/uv/src/threadpool.c +++ b/deps/uv/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/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h index 347d19365f7542..c48d058435a6b3 100644 --- a/deps/uv/src/unix/atomic-ops.h +++ b/deps/uv/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/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 63f268f795f100..71e9c525c4a77b 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/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; @@ -1174,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; @@ -1184,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) { @@ -1570,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/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index d0ecd452d87c68..a7be0dd2f3ca14 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/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/uv/src/unix/epoll.c b/deps/uv/src/unix/epoll.c new file mode 100644 index 00000000000000..97348e254b4556 --- /dev/null +++ b/deps/uv/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/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index fe795a0e75ea1a..170b897e2023d2 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/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/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index fd7ae08755f519..eb17fb4a23eb82 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -56,6 +56,10 @@ # define HAVE_PREADV 0 #endif +#if defined(__linux__) +# include "sys/utsname.h" +#endif + #if defined(__linux__) || defined(__sun) # include # include @@ -901,6 +905,50 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) { } +#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; @@ -917,15 +965,20 @@ 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) { + if (uv__load_relaxed(&no_copy_file_range_support) == 0) { r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0); if (r == -1 && errno == ENOSYS) { /* ENOSYS - it will never work */ errno = 0; - copy_file_range_support = 0; + uv__store_relaxed(&no_copy_file_range_support, 1); + } else if (r == -1 && errno == EACCES && uv__is_buggy_cephfs(in_fd)) { + /* EACCES - pre-4.20 kernels have a bug where CephFS uses the RADOS + copy-from command when it shouldn't */ + errno = 0; + uv__store_relaxed(&no_copy_file_range_support, 1); } else if (r == -1 && (errno == ENOTSUP || errno == EXDEV)) { /* ENOTSUP - it could work on another file system type */ /* EXDEV - it will not work when in_fd and out_fd are not on the same @@ -1357,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__) || \ diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index a51f29b3f6db55..bf4f1f6a5180ab 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -595,8 +595,7 @@ static int uv__fsevents_global_init(void) { 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/uv/src/unix/getaddrinfo.c b/deps/uv/src/unix/getaddrinfo.c index d7ca7d1a446838..77337ace9454e0 100644 --- a/deps/uv/src/unix/getaddrinfo.c +++ b/deps/uv/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/uv/src/unix/ibmi.c b/deps/uv/src/unix/ibmi.c index 96efc02bad6071..8c6ae636329e5b 100644 --- a/deps/uv/src/unix/ibmi.c +++ b/deps/uv/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/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 3bdf7283bd4fd8..12d4da93686e99 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/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); @@ -321,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; @@ -334,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/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index c356e96d2dec5b..2716e2be65dfe4 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/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; @@ -740,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; @@ -769,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) @@ -817,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 @@ -855,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); diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c index 42b601adbf898a..c1bd260e16e5e9 100644 --- a/deps/uv/src/unix/linux-inotify.c +++ b/deps/uv/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/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h index c85231f6bf4436..b4d9082d46f99b 100644 --- a/deps/uv/src/unix/linux-syscalls.h +++ b/deps/uv/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 diff --git a/deps/uv/src/unix/os390-proctitle.c b/deps/uv/src/unix/os390-proctitle.c new file mode 100644 index 00000000000000..ccda97c9ac5822 --- /dev/null +++ b/deps/uv/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/uv/src/unix/os390-syscalls.c b/deps/uv/src/unix/os390-syscalls.c index 491e950c503d40..c19155339c3124 100644 --- a/deps/uv/src/unix/os390-syscalls.c +++ b/deps/uv/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/uv/src/unix/os390-syscalls.h b/deps/uv/src/unix/os390-syscalls.h index 86416bbc551e19..7d59b75e470945 100644 --- a/deps/uv/src/unix/os390-syscalls.h +++ b/deps/uv/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/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c index 3bb44266d93cc1..bf0448b519080e 100644 --- a/deps/uv/src/unix/os390.c +++ b/deps/uv/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 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } } -void uv__set_process_title(const char* title) { - /* do nothing */ -} int uv__io_fork(uv_loop_t* loop) { /* diff --git a/deps/uv/src/unix/poll.c b/deps/uv/src/unix/poll.c index 7a1bc7b9dd58d8..7a12e2d1488a9d 100644 --- a/deps/uv/src/unix/poll.c +++ b/deps/uv/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; diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index 8f94c53b249978..f4aebb0490e198 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/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; @@ -197,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 @@ -225,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++) { @@ -245,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); } } @@ -257,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); @@ -276,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 @@ -292,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; @@ -323,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/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c index 9e39545e44a0ff..9d1f00ddf66e29 100644 --- a/deps/uv/src/unix/proctitle.c +++ b/deps/uv/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; diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 106785e4574ea0..bc64fe8f44b26d 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/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 @@ static void uv__write(uv_stream_t* stream) { * 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 @@ static void uv__write(uv_stream_t* stream) { 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 @@ static void uv__write(uv_stream_t* stream) { do n = sendmsg(uv__stream_fd(stream), &msg, 0); while (n == -1 && RETRY_ON_WRITE_ERROR(errno)); - - /* Ensure the handle isn't sent again in case this is a partial write. */ - if (n >= 0) - req->send_handle = NULL; } else { do n = uv__writev(uv__stream_fd(stream), iov, iovcnt); while (n == -1 && RETRY_ON_WRITE_ERROR(errno)); } - if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) { - err = UV__ERR(errno); - goto error; - } + if (n >= 0) + return n; - if (n >= 0 && uv__write_req_update(stream, req, n)) { - uv__write_req_finish(req); - return; /* TODO(bnoordhuis) Start trying to write the next request. */ - } + if (IS_TRANSIENT_WRITE_ERROR(errno, send_handle)) + return UV_EAGAIN; - /* If this is a blocking stream, try again. */ - if (stream->flags & UV_HANDLE_BLOCKING_WRITES) - goto start; + return UV__ERR(errno); +} - /* We're not done. */ - uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); +static void uv__write(uv_stream_t* stream) { + QUEUE* q; + uv_write_t* req; + ssize_t n; - /* Notify select() thread about state change */ - uv__stream_osx_interrupt_select(stream); + assert(uv__stream_fd(stream) >= 0); + + 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; - return; + /* 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,57 +1519,28 @@ 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); - - r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb); - if (r != 0) - return r; - - /* Remove not written bytes from write queue size */ - written = uv__count_bufs(bufs, nbufs); - if (req.bufs != NULL) - req_size = uv__write_req_size(&req); - else - req_size = 0; - written -= req_size; - stream->write_queue_size -= req_size; - - /* Unqueue request, regardless of immediateness */ - QUEUE_REMOVE(&req.queue); - uv__req_unregister(stream->loop, &req); - if (req.bufs != req.bufsml) - uv__free(req.bufs); - req.bufs = NULL; - - /* Do not poll for writable, if we wasn't before calling this */ - if (!has_pollout) { - uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); - uv__stream_osx_interrupt_select(stream); - } + err = uv__check_before_write(stream, nbufs, NULL); + if (err < 0) + return err; - if (written == 0 && req_size != 0) - return req.error < 0 ? req.error : UV_EAGAIN; - else - return written; + return uv__try_write(stream, bufs, nbufs, send_handle); } @@ -1587,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/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index d511c18b85e8ee..2bf297e5d966b7 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/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/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 1a85d1d4fcd4df..c46450cc661270 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/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/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index 6f60abaadb02ef..9442cf16360e50 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/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/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 7d699a16753c6b..49051c07c15491 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/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/uv/src/uv-common.c b/deps/uv/src/uv-common.c index dd559a11d11b6a..e81ed79b0c551d 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -872,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/uv/src/uv-common.h b/deps/uv/src/uv-common.h index a92912fdb1a72e..8a190bf8fa8c5a 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/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, diff --git a/deps/uv/src/win/atomicops-inl.h b/deps/uv/src/win/atomicops-inl.h index 52713cf305feb5..2f984c6db0b428 100644 --- a/deps/uv/src/win/atomicops-inl.h +++ b/deps/uv/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/uv/src/win/error.c b/deps/uv/src/win/error.c index 3ec984c83eb077..3a269da87a948b 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/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/uv/src/win/fs.c b/deps/uv/src/win/fs.c index a083b5e82c8c42..674070400be419 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -1238,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)) { diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c index 87858590c8525a..9d37759606692e 100644 --- a/deps/uv/src/win/poll.c +++ b/deps/uv/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/uv/src/win/process.c b/deps/uv/src/win/process.c index 73543c6ed987ce..4038fbfd290d1a 100644 --- a/deps/uv/src/win/process.c +++ b/deps/uv/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/uv/src/win/stream.c b/deps/uv/src/win/stream.c index ebb5fe5cb79d04..abf477f64421d5 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -188,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/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index 517700e66d81b9..cf2dbd85fdbb05 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/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; @@ -1024,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), @@ -1105,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), @@ -1158,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); @@ -1336,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) { @@ -1355,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) { @@ -1402,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 : @@ -1424,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) { @@ -1496,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); diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 68ca728aa5c9cc..3043f2da88e74a 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/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/uv/src/win/util.c b/deps/uv/src/win/util.c index aad8f1a15e9cb6..88602c7ee8623f 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/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/uv/test/benchmark-async-pummel.c b/deps/uv/test/benchmark-async-pummel.c index 119ae5eee5a28c..49660a6f5755c0 100644 --- a/deps/uv/test/benchmark-async-pummel.c +++ b/deps/uv/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/uv/test/benchmark-async.c b/deps/uv/test/benchmark-async.c index e44165f2b81485..5167ecbd758d7a 100644 --- a/deps/uv/test/benchmark-async.c +++ b/deps/uv/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/uv/test/benchmark-million-async.c b/deps/uv/test/benchmark-million-async.c index 5395ed54bab5c0..937a12f81e64be 100644 --- a/deps/uv/test/benchmark-million-async.c +++ b/deps/uv/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/uv/test/benchmark-million-timers.c b/deps/uv/test/benchmark-million-timers.c index 60a308bef13d40..ef25c2052d6f66 100644 --- a/deps/uv/test/benchmark-million-timers.c +++ b/deps/uv/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/uv/test/benchmark-multi-accept.c b/deps/uv/test/benchmark-multi-accept.c index 5a186233f580d9..86b7da5acd158a 100644 --- a/deps/uv/test/benchmark-multi-accept.c +++ b/deps/uv/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/uv/test/benchmark-pound.c b/deps/uv/test/benchmark-pound.c index 79f36345037cd4..830bc554b34348 100644 --- a/deps/uv/test/benchmark-pound.c +++ b/deps/uv/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/uv/test/benchmark-tcp-write-batch.c b/deps/uv/test/benchmark-tcp-write-batch.c index 96921b70db57ef..16aa72f6bf73c8 100644 --- a/deps/uv/test/benchmark-tcp-write-batch.c +++ b/deps/uv/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/uv/test/benchmark-udp-pummel.c b/deps/uv/test/benchmark-udp-pummel.c index 68a2373d781fc3..1a2205702603e0 100644 --- a/deps/uv/test/benchmark-udp-pummel.c +++ b/deps/uv/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/uv/test/blackhole-server.c b/deps/uv/test/blackhole-server.c index 9b21d1e0e07279..0a8758e1a1733b 100644 --- a/deps/uv/test/blackhole-server.c +++ b/deps/uv/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); diff --git a/deps/uv/test/dns-server.c b/deps/uv/test/dns-server.c index 80052c703983b0..f8ca87f227e8e2 100644 --- a/deps/uv/test/dns-server.c +++ b/deps/uv/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/uv/test/echo-server.c b/deps/uv/test/echo-server.c index 69d0abc980bc32..058c9925475c94 100644 --- a/deps/uv/test/echo-server.c +++ b/deps/uv/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; @@ -220,7 +243,7 @@ static void on_recv(uv_udp_t* handle, ASSERT(addr->sa_family == AF_INET); req = send_alloc(); - ASSERT(req != NULL); + ASSERT_NOT_NULL(req); sndbuf = uv_buf_init(rcvbuf->base, nread); ASSERT(0 <= uv_udp_send(req, handle, &sndbuf, 1, addr, on_send)); } diff --git a/deps/uv/test/run-benchmarks.c b/deps/uv/test/run-benchmarks.c index 980c9be8c12aa6..2b343da4c91731 100644 --- a/deps/uv/test/run-benchmarks.c +++ b/deps/uv/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/uv/test/run-tests.c b/deps/uv/test/run-tests.c index fc8a79a9eb9019..5e53aaa80b17ce 100644 --- a/deps/uv/test/run-tests.c +++ b/deps/uv/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); @@ -153,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) { @@ -198,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); diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index b7ca1f857ec1e4..a13648bc883878 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/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/uv/test/runner.c b/deps/uv/test/runner.c index bb50b43b304ab6..789108275cda11 100644 --- a/deps/uv/test/runner.c +++ b/deps/uv/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 @@ int run_test(const char* test, /* 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 @@ int run_test(const char* test, } 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/uv/test/task.h b/deps/uv/test/task.h index 4e7e2f07f570d3..a02c8931b50f2f 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/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" diff --git a/deps/uv/test/test-active.c b/deps/uv/test/test-active.c index b17bd1760188b4..384389561a79e8 100644 --- a/deps/uv/test/test-active.c +++ b/deps/uv/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/uv/test/test-async.c b/deps/uv/test/test-async.c index 6f5351bf1586b0..619be620e3e916 100644 --- a/deps/uv/test/test-async.c +++ b/deps/uv/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/uv/test/test-callback-stack.c b/deps/uv/test/test-callback-stack.c index 1871e7e98196d1..a5195c7b7f3dd1 100644 --- a/deps/uv/test/test-callback-stack.c +++ b/deps/uv/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/uv/test/test-close-order.c b/deps/uv/test/test-close-order.c index 2b24f6d6579163..c2fd6c3d0dec16 100644 --- a/deps/uv/test/test-close-order.c +++ b/deps/uv/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/uv/test/test-default-loop-close.c b/deps/uv/test/test-default-loop-close.c index fd11cfa8c1285a..51e1e7dc23bffa 100644 --- a/deps/uv/test/test-default-loop-close.c +++ b/deps/uv/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/uv/test/test-delayed-accept.c b/deps/uv/test/test-delayed-accept.c index 513e69bd5b7d23..88b31e26903f09 100644 --- a/deps/uv/test/test-delayed-accept.c +++ b/deps/uv/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/uv/test/test-dlerror.c b/deps/uv/test/test-dlerror.c index 42ad68828626b1..a436ec016bfec8 100644 --- a/deps/uv/test/test-dlerror.c +++ b/deps/uv/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/uv/test/test-error.c b/deps/uv/test/test-error.c index 35d108a4a1f768..f0fb864607f36c 100644 --- a/deps/uv/test/test-error.c +++ b/deps/uv/test/test-error.c @@ -50,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/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 0992d5989e421b..ec163868f49925 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/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); @@ -758,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(); @@ -1072,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/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c index 9dfd5fdd6aa282..76fe6fc3957192 100644 --- a/deps/uv/test/test-fs-poll.c +++ b/deps/uv/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/uv/test/test-fs-readdir.c b/deps/uv/test/test-fs-readdir.c index cccaa7438baabc..41e1d373ca89a1 100644 --- a/deps/uv/test/test-fs-readdir.c +++ b/deps/uv/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,7 +223,7 @@ 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; @@ -247,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); @@ -329,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; @@ -403,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/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 0292a96b4802ca..034c971d3620e8 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/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++; } @@ -1453,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); @@ -2011,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); @@ -2032,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() @@ -2046,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); @@ -2843,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); @@ -2880,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); @@ -2932,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); @@ -3332,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, @@ -3361,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), @@ -3444,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, @@ -3480,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), @@ -3676,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)); @@ -3773,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); diff --git a/deps/uv/test/test-get-currentexe.c b/deps/uv/test/test-get-currentexe.c index 8eba7b73b7b036..dc239cc89d1435 100644 --- a/deps/uv/test/test-get-currentexe.c +++ b/deps/uv/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/uv/test/test-get-passwd.c b/deps/uv/test/test-get-passwd.c index abe8be36a332b5..865c07d651507a 100644 --- a/deps/uv/test/test-get-passwd.c +++ b/deps/uv/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/uv/test/test-getaddrinfo.c b/deps/uv/test/test-getaddrinfo.c index b1fc312349f960..d0b6a505016dd8 100644 --- a/deps/uv/test/test-getaddrinfo.c +++ b/deps/uv/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++; } @@ -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/uv/test/test-getnameinfo.c b/deps/uv/test/test-getnameinfo.c index eb3264515ce509..2bfedd3a39b233 100644 --- a/deps/uv/test/test-getnameinfo.c +++ b/deps/uv/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/uv/test/test-getsockname.c b/deps/uv/test/test-getsockname.c index 565c17fe50b552..7c77fcb0a9b605 100644 --- a/deps/uv/test/test-getsockname.c +++ b/deps/uv/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/uv/test/test-getters-setters.c b/deps/uv/test/test-getters-setters.c index 42c9dcaf0cb2c7..2a37122df3f6aa 100644 --- a/deps/uv/test/test-getters-setters.c +++ b/deps/uv/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/uv/test/test-ipc-heavy-traffic-deadlock-bug.c b/deps/uv/test/test-ipc-heavy-traffic-deadlock-bug.c index 753fb7b7c209e7..89b977d2c34080 100644 --- a/deps/uv/test/test-ipc-heavy-traffic-deadlock-bug.c +++ b/deps/uv/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/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c index ba3ba737481532..68a0e1bb8144ca 100644 --- a/deps/uv/test/test-ipc.c +++ b/deps/uv/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); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 74588407cfbd8d..59b95da9ebe346 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -206,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) @@ -504,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) @@ -780,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) @@ -1129,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/uv/test/test-loop-handles.c b/deps/uv/test/test-loop-handles.c index 131098801ae126..05cb8466ca626e 100644 --- a/deps/uv/test/test-loop-handles.c +++ b/deps/uv/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/uv/test/test-multiple-listen.c b/deps/uv/test/test-multiple-listen.c index 4ae5fa67b3a342..0b2851411a862b 100644 --- a/deps/uv/test/test-multiple-listen.c +++ b/deps/uv/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/uv/test/test-not-readable-nor-writable-on-read-error.c b/deps/uv/test/test-not-readable-nor-writable-on-read-error.c new file mode 100644 index 00000000000000..ae951e39893b36 --- /dev/null +++ b/deps/uv/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/uv/test/test-not-readable-on-eof.c b/deps/uv/test/test-not-readable-on-eof.c new file mode 100644 index 00000000000000..2bb5f4eecccf76 --- /dev/null +++ b/deps/uv/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/uv/test/test-not-writable-after-shutdown.c b/deps/uv/test/test-not-writable-after-shutdown.c new file mode 100644 index 00000000000000..9cd93703cea292 --- /dev/null +++ b/deps/uv/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/uv/test/test-pipe-bind-error.c b/deps/uv/test/test-pipe-bind-error.c index 9cf93165e41301..ce35052f537fdc 100644 --- a/deps/uv/test/test-pipe-bind-error.c +++ b/deps/uv/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/uv/test/test-pipe-connect-error.c b/deps/uv/test/test-pipe-connect-error.c index 8bba328a344f17..30c270d9fce8f4 100644 --- a/deps/uv/test/test-pipe-connect-error.c +++ b/deps/uv/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++; } diff --git a/deps/uv/test/test-pipe-connect-prepare.c b/deps/uv/test/test-pipe-connect-prepare.c index a86e7284a799fd..08b57cbf51094c 100644 --- a/deps/uv/test/test-pipe-connect-prepare.c +++ b/deps/uv/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/uv/test/test-pipe-getsockname.c b/deps/uv/test/test-pipe-getsockname.c index 5f377dcbb60696..79db8eba7177e0 100644 --- a/deps/uv/test/test-pipe-getsockname.c +++ b/deps/uv/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); diff --git a/deps/uv/test/test-pipe-server-close.c b/deps/uv/test/test-pipe-server-close.c index ea9977dd843e2a..25305b397b2e05 100644 --- a/deps/uv/test/test-pipe-server-close.c +++ b/deps/uv/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/uv/test/test-pipe-set-non-blocking.c b/deps/uv/test/test-pipe-set-non-blocking.c index c45148f2bd028d..8246afaf827003 100644 --- a/deps/uv/test/test-pipe-set-non-blocking.c +++ b/deps/uv/test/test-pipe-set-non-blocking.c @@ -105,10 +105,10 @@ TEST_IMPL(pipe_set_non_blocking) { #ifdef _WIN32 ASSERT(n == UV_EAGAIN); /* E_NOTIMPL */ ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &pipe_handle, &buf, 1, write_cb)); - ASSERT(write_req.handle != NULL); + 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(write_req.handle == NULL); /* check for signaled completion of write_cb */ + ASSERT_NULL(write_req.handle); /* check for signaled completion of write_cb */ n = buf.len; #endif ASSERT(n == sizeof(data)); diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c index edd75d38266768..3bc422d2795543 100644 --- a/deps/uv/test/test-poll.c +++ b/deps/uv/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/uv/test/test-ref.c b/deps/uv/test/test-ref.c index 05728c83365bfe..d24ea4a01e8aba 100644 --- a/deps/uv/test/test-ref.c +++ b/deps/uv/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/uv/test/test-shutdown-simultaneous.c b/deps/uv/test/test-shutdown-simultaneous.c new file mode 100644 index 00000000000000..7de3bd42252e62 --- /dev/null +++ b/deps/uv/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/uv/test/test-signal-multiple-loops.c b/deps/uv/test/test-signal-multiple-loops.c index 09d9cacb3af6b4..7d61ff61e0d9e9 100644 --- a/deps/uv/test/test-signal-multiple-loops.c +++ b/deps/uv/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/uv/test/test-signal-pending-on-close.c b/deps/uv/test/test-signal-pending-on-close.c index 23b9ec8d16f1d4..428a97ef5ae30d 100644 --- a/deps/uv/test/test-signal-pending-on-close.c +++ b/deps/uv/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/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index 886ddaf63b509d..9f2eb24b2d6daf 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -1176,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]); @@ -1185,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" "); @@ -1351,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); @@ -1385,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); @@ -1423,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)); } @@ -1474,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)); } diff --git a/deps/uv/test/test-tcp-alloc-cb-fail.c b/deps/uv/test/test-tcp-alloc-cb-fail.c index 61ca667acbcab3..b6f4ca38850bac 100644 --- a/deps/uv/test/test-tcp-alloc-cb-fail.c +++ b/deps/uv/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/uv/test/test-tcp-bind-error.c b/deps/uv/test/test-tcp-bind-error.c index 7732267f44f54e..fdd1fe07450d73 100644 --- a/deps/uv/test/test-tcp-bind-error.c +++ b/deps/uv/test/test-tcp-bind-error.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/uv/test/test-tcp-bind6-error.c b/deps/uv/test/test-tcp-bind6-error.c index b762bcb3d1b8d0..86181b708e3fd2 100644 --- a/deps/uv/test/test-tcp-bind6-error.c +++ b/deps/uv/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/uv/test/test-tcp-close.c b/deps/uv/test/test-tcp-close.c index e65885aa5563a7..5a7bd6893bf479 100644 --- a/deps/uv/test/test-tcp-close.c +++ b/deps/uv/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/uv/test/test-tcp-connect-error.c b/deps/uv/test/test-tcp-connect-error.c index eab1eeb25457bb..dda30a58064f8f 100644 --- a/deps/uv/test/test-tcp-connect-error.c +++ b/deps/uv/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/uv/test/test-tcp-connect6-error.c b/deps/uv/test/test-tcp-connect6-error.c index 91ac0a3a101f86..2f6e9cbce14336 100644 --- a/deps/uv/test/test-tcp-connect6-error.c +++ b/deps/uv/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/uv/test/test-tcp-create-socket-early.c b/deps/uv/test/test-tcp-create-socket-early.c index b87e7324184be1..f2bc60d7c7c0ec 100644 --- a/deps/uv/test/test-tcp-create-socket-early.c +++ b/deps/uv/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/uv/test/test-tcp-open.c b/deps/uv/test/test-tcp-open.c index 0d92886d61f225..7e49139cd81a86 100644 --- a/deps/uv/test/test-tcp-open.c +++ b/deps/uv/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/uv/test/test-tcp-write-fail.c b/deps/uv/test/test-tcp-write-fail.c index 5256a9f4a790aa..58ee00faedb410 100644 --- a/deps/uv/test/test-tcp-write-fail.c +++ b/deps/uv/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/uv/test/test-tcp-write-to-half-open-connection.c b/deps/uv/test/test-tcp-write-to-half-open-connection.c index 2fa2ae72253fb6..ae4251317d80e6 100644 --- a/deps/uv/test/test-tcp-write-to-half-open-connection.c +++ b/deps/uv/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/uv/test/test-tcp-writealot.c b/deps/uv/test/test-tcp-writealot.c index 7206fdc2f60eb5..40dce96e8d8c34 100644 --- a/deps/uv/test/test-tcp-writealot.c +++ b/deps/uv/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/uv/test/test-thread.c b/deps/uv/test/test-thread.c index 432c243999fb15..8de5a6f03a3029 100644 --- a/deps/uv/test/test-thread.c +++ b/deps/uv/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/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c index be252c6f723451..1e867c51cf9c3f 100644 --- a/deps/uv/test/test-threadpool-cancel.c +++ b/deps/uv/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/uv/test/test-timer-again.c b/deps/uv/test/test-timer-again.c index e87d2edf18f121..834b59d718c8aa 100644 --- a/deps/uv/test/test-timer-again.c +++ b/deps/uv/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/uv/test/test-timer.c b/deps/uv/test/test-timer.c index ee8331c2045ff3..d0921a967304f1 100644 --- a/deps/uv/test/test-timer.c +++ b/deps/uv/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/uv/test/test-tty-duplicate-key.c b/deps/uv/test/test-tty-duplicate-key.c index 1ec2f3695d99a4..efd79e14786d69 100644 --- a/deps/uv/test/test-tty-duplicate-key.c +++ b/deps/uv/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/uv/test/test-tty-escape-sequence-processing.c b/deps/uv/test/test-tty-escape-sequence-processing.c index c4461e91e06cf9..ef34e5927c52af 100644 --- a/deps/uv/test/test-tty-escape-sequence-processing.c +++ b/deps/uv/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/uv/test/test-udp-alloc-cb-fail.c b/deps/uv/test/test-udp-alloc-cb-fail.c index 0cee09c942ef2c..6b0980163a5f9e 100644 --- a/deps/uv/test/test-udp-alloc-cb-fail.c +++ b/deps/uv/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/uv/test/test-udp-connect.c b/deps/uv/test/test-udp-connect.c index 52856f700d210e..89ca1a84fcd294 100644 --- a/deps/uv/test/test-udp-connect.c +++ b/deps/uv/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); diff --git a/deps/uv/test/test-udp-mmsg.c b/deps/uv/test/test-udp-mmsg.c index 08628a5046fedc..fb24115107231e 100644 --- a/deps/uv/test/test-udp-mmsg.c +++ b/deps/uv/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/uv/test/test-udp-multicast-interface.c b/deps/uv/test/test-udp-multicast-interface.c index 9d36098d0d0ac2..bd9a61c98aa6e2 100644 --- a/deps/uv/test/test-udp-multicast-interface.c +++ b/deps/uv/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/uv/test/test-udp-multicast-interface6.c b/deps/uv/test/test-udp-multicast-interface6.c index 23a68a00f85625..be11514c805900 100644 --- a/deps/uv/test/test-udp-multicast-interface6.c +++ b/deps/uv/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/uv/test/test-udp-multicast-join.c b/deps/uv/test/test-udp-multicast-join.c index cb3ff871eb9111..9e603a8455f736 100644 --- a/deps/uv/test/test-udp-multicast-join.c +++ b/deps/uv/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/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c index 40aa577d0a1b12..e67c5ee59bb1fb 100644 --- a/deps/uv/test/test-udp-multicast-join6.c +++ b/deps/uv/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/uv/test/test-udp-multicast-ttl.c b/deps/uv/test/test-udp-multicast-ttl.c index e92608be4809bf..fbddd90914ca86 100644 --- a/deps/uv/test/test-udp-multicast-ttl.c +++ b/deps/uv/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/uv/test/test-udp-open.c b/deps/uv/test/test-udp-open.c index dee408baa5c09e..f5136b6d4f281f 100644 --- a/deps/uv/test/test-udp-open.c +++ b/deps/uv/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/uv/test/test-udp-send-and-recv.c b/deps/uv/test/test-udp-send-and-recv.c index 1f01188b274a49..d60209059b9887 100644 --- a/deps/uv/test/test-udp-send-and-recv.c +++ b/deps/uv/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/uv/test/test-udp-send-hang-loop.c b/deps/uv/test/test-udp-send-hang-loop.c index bf4dfebfb35098..072070b60e5e65 100644 --- a/deps/uv/test/test-udp-send-hang-loop.c +++ b/deps/uv/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/uv/test/test-udp-send-immediate.c b/deps/uv/test/test-udp-send-immediate.c index 1011aa467e0541..a1c95d34384ce2 100644 --- a/deps/uv/test/test-udp-send-immediate.c +++ b/deps/uv/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/uv/test/test-udp-send-unreachable.c b/deps/uv/test/test-udp-send-unreachable.c index c6500320d783b4..c67a23b38529fe 100644 --- a/deps/uv/test/test-udp-send-unreachable.c +++ b/deps/uv/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/uv/test/test-udp-try-send.c b/deps/uv/test/test-udp-try-send.c index a31d3822955632..85caaaca41d5a5 100644 --- a/deps/uv/test/test-udp-try-send.c +++ b/deps/uv/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/uv/uv.gyp b/deps/uv/uv.gyp index 7fc7e0601b9f6a..f03b4b4c0f3a20 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -238,6 +238,7 @@ [ 'OS=="linux"', { 'defines': [ '_GNU_SOURCE' ], 'sources': [ + 'src/unix/epoll.c', 'src/unix/linux-core.c', 'src/unix/linux-inotify.c', 'src/unix/linux-syscalls.c', @@ -274,6 +275,7 @@ 'defines': [ '__EXTENSIONS__', '_XOPEN_SOURCE=500', + '_REENTRANT', ], 'link_settings': { 'libraries': [