deps: upgrade to libuv 1.42.0

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 <technicalcute@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
Luigi Pinca 2021-07-26 09:59:29 +02:00
parent fe3c5a769d
commit c61870c376
145 changed files with 2357 additions and 1176 deletions

4
deps/uv/.mailmap vendored
View File

@ -2,6 +2,7 @@ A. Hauptmann <andreashauptmann@t-online.de>
Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
Andy Fiddaman <andy@omniosce.org> <omnios@citrus-it.co.uk>
Bert Belder <bertbelder@gmail.com> <i@bertbelder.com>
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
@ -10,6 +11,8 @@ Brian White <mscdex@mscdex.net>
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr>
Christoph Iserlohn <christoph.iserlohn@innoq.com>
Darshan Sen <raisinten@gmail.com>
David Carlier <devnexen@gmail.com>
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
Frank Denis <github@pureftpd.org>
@ -53,4 +56,5 @@ gengjiawen <technicalcute@gmail.com>
jBarz <jBarz@users.noreply.github.com> <jbarboza@ca.ibm.com>
jBarz <jBarz@users.noreply.github.com> <jbarz@users.noreply.github.com>
ptlomholt <pt@lomholt.com>
tjarlama <59913901+tjarlama@users.noreply.github.com> <tjarlama@gmail.com>
zlargon <zlargon1988@gmail.com>

11
deps/uv/.readthedocs.yaml vendored Normal file
View File

@ -0,0 +1,11 @@
version: 2
sphinx:
builder: html
configuration: null
fail_on_warning: false
python:
version: 3.8
install:
- requirements: docs/requirements.txt

24
deps/uv/AUTHORS vendored
View File

@ -114,7 +114,6 @@ Dylan Cali <calid1984@gmail.com>
Austin Foxley <austinf@cetoncorp.com>
Benjamin Saunders <ben.e.saunders@gmail.com>
Geoffry Song <goffrie@gmail.com>
Rasmus Christian Pedersen <ruysch@outlook.com>
William Light <wrl@illest.net>
Oleg Efimov <o.efimov@corp.badoo.com>
Lars Gierth <larsg@systemli.org>
@ -123,7 +122,6 @@ Justin Venus <justin.venus@gmail.com>
Kristian Evensen <kristian.evensen@gmail.com>
Linus Mårtensson <linus.martensson@sonymobile.com>
Navaneeth Kedaram Nambiathan <navaneethkn@gmail.com>
Yorkie <yorkiefixer@gmail.com>
StarWing <weasley.wx@gmail.com>
thierry-FreeBSD <thierry@FreeBSD.org>
Isaiah Norton <isaiah.norton@gmail.com>
@ -459,3 +457,25 @@ schamberg97 <50446906+schamberg97@users.noreply.github.com>
Bob Weinand <bobwei9@hotmail.com>
Issam E. Maghni <issam.e.maghni@mailbox.org>
Juan Pablo Canepa <jpcanepa@gmail.com>
Shuowang (Wayne) Zhang <shuowang.zhang@ibm.com>
Ondřej Surý <ondrej@sury.org>
Juan José Arboleda <soyjuanarbol@gmail.com>
Zhao Zhili <zhilizhao@tencent.com>
Brandon Cheng <brandon.cheng@protonmail.com>
Matvii Hodovaniuk <matvii@hodovani.uk>
Hayden <me@diatr.us>
yiyuaner <yguoaz@gmail.com>
bbara <bbara93@gmail.com>
SeverinLeonhardt <Severin.Leonhardt@teamviewer.com>
Andy Fiddaman <andy@omniosce.org>
Romain Roffé <rofferom@gmail.com>
Eagle Liang <eagleliang@gmail.com>
Ricky Zhou <ives199511@gmail.com>
Simon Kissane <skissane@gmail.com>
James M Snell <jasnell@gmail.com>
Ali Mohammad Pur <Ali.mpfard@gmail.com>
Erkhes N <71805796+rexes-ND@users.noreply.github.com>
Joshua M. Clulow <josh@sysmgr.org>
Guilherme Íscaro <cabelitostos@gmail.com>
Martin Storsjö <martin@martin.st>
Claes Nästén <pekdon@gmail.com>

View File

@ -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
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
target_include_directories(uv PUBLIC $<BUILD_INTERFACE:${ZOSLIB_DIR}/include>)
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
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
target_include_directories(uv_a PUBLIC $<BUILD_INTERFACE:${ZOSLIB_DIR}/include>)
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)

View File

@ -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

155
deps/uv/ChangeLog vendored
View File

@ -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:

101
deps/uv/LINKS.md vendored Normal file
View File

@ -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)

View File

@ -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)

10
deps/uv/Makefile.am vendored
View File

@ -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

12
deps/uv/README.md vendored
View File

@ -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.

View File

@ -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])

42
deps/uv/docs/requirements.txt vendored Normal file
View File

@ -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

View File

@ -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
---

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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`.

15
deps/uv/include/uv.h vendored
View File

@ -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.
*/

View File

@ -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_ */

View File

@ -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) \

View File

@ -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 ""

3
deps/uv/src/inet.c vendored
View File

@ -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;
}

View File

@ -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
}

View File

@ -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
}

View File

@ -88,6 +88,10 @@ extern char** environ;
# define uv__accept4 accept4
#endif
#if defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__)
# include <sanitizer/linux_syscall_hooks.h>
#endif
static int uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
@ -539,7 +543,13 @@ 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;

View File

@ -33,9 +33,7 @@
#include <sys/sysctl.h>
#include <unistd.h> /* sysconf */
#if !TARGET_OS_IPHONE
#include "darwin-stub.h"
#endif
static uv_once_t once = UV_ONCE_INIT;
static uint64_t (*time_func)(void);
@ -223,10 +221,10 @@ 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);

422
deps/uv/src/unix/epoll.c vendored Normal file
View File

@ -0,0 +1,422 @@
/* Copyright libuv contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "internal.h"
#include <errno.h>
#include <sys/epoll.h>
int uv__epoll_init(uv_loop_t* loop) {
int fd;
fd = epoll_create1(O_CLOEXEC);
/* epoll_create1() can fail either because it's not implemented (old kernel)
* or because it doesn't understand the O_CLOEXEC flag.
*/
if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
fd = epoll_create(256);
if (fd != -1)
uv__cloexec(fd, 1);
}
loop->backend_fd = fd;
if (fd == -1)
return UV__ERR(errno);
return 0;
}
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct epoll_event* events;
struct epoll_event dummy;
uintptr_t i;
uintptr_t nfds;
assert(loop->watchers != NULL);
assert(fd >= 0);
events = (struct epoll_event*) loop->watchers[loop->nwatchers];
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
if (events != NULL)
/* Invalidate events with same file descriptor */
for (i = 0; i < nfds; i++)
if (events[i].data.fd == fd)
events[i].data.fd = -1;
/* Remove the file descriptor from the epoll.
* This avoids a problem where the same file description remains open
* in another process, causing repeated junk epoll events.
*
* We pass in a dummy epoll_event, to work around a bug in old kernels.
*/
if (loop->backend_fd >= 0) {
/* Work around a bug in kernels 3.10 to 3.19 where passing a struct that
* has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
*/
memset(&dummy, 0, sizeof(dummy));
epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);
}
}
int uv__io_check_fd(uv_loop_t* loop, int fd) {
struct epoll_event e;
int rc;
memset(&e, 0, sizeof(e));
e.events = POLLIN;
e.data.fd = -1;
rc = 0;
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))
if (errno != EEXIST)
rc = UV__ERR(errno);
if (rc == 0)
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))
abort();
return rc;
}
void uv__io_poll(uv_loop_t* loop, int timeout) {
/* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
* effectively infinite on 32 bits architectures. To avoid blocking
* indefinitely, we cap the timeout and poll again if necessary.
*
* Note that "30 minutes" is a simplification because it depends on
* the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200,
* that being the largest value I have seen in the wild (and only once.)
*/
static const int max_safe_timeout = 1789569;
static int no_epoll_pwait_cached;
static int no_epoll_wait_cached;
int no_epoll_pwait;
int no_epoll_wait;
struct epoll_event events[1024];
struct epoll_event* pe;
struct epoll_event e;
int real_timeout;
QUEUE* q;
uv__io_t* w;
sigset_t sigset;
uint64_t sigmask;
uint64_t base;
int have_signals;
int nevents;
int count;
int nfds;
int fd;
int op;
int i;
int user_timeout;
int reset_timeout;
if (loop->nfds == 0) {
assert(QUEUE_EMPTY(&loop->watcher_queue));
return;
}
memset(&e, 0, sizeof(e));
while (!QUEUE_EMPTY(&loop->watcher_queue)) {
q = QUEUE_HEAD(&loop->watcher_queue);
QUEUE_REMOVE(q);
QUEUE_INIT(q);
w = QUEUE_DATA(q, uv__io_t, watcher_queue);
assert(w->pevents != 0);
assert(w->fd >= 0);
assert(w->fd < (int) loop->nwatchers);
e.events = w->pevents;
e.data.fd = w->fd;
if (w->events == 0)
op = EPOLL_CTL_ADD;
else
op = EPOLL_CTL_MOD;
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
* events, skip the syscall and squelch the events after epoll_wait().
*/
if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
if (errno != EEXIST)
abort();
assert(op == EPOLL_CTL_ADD);
/* We've reactivated a file descriptor that's been watched before. */
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))
abort();
}
w->events = w->pevents;
}
sigmask = 0;
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
sigemptyset(&sigset);
sigaddset(&sigset, SIGPROF);
sigmask |= 1 << (SIGPROF - 1);
}
assert(timeout >= -1);
base = loop->time;
count = 48; /* Benchmarks suggest this gives the best throughput. */
real_timeout = timeout;
if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
reset_timeout = 1;
user_timeout = timeout;
timeout = 0;
} else {
reset_timeout = 0;
user_timeout = 0;
}
/* You could argue there is a dependency between these two but
* ultimately we don't care about their ordering with respect
* to one another. Worst case, we make a few system calls that
* could have been avoided because another thread already knows
* they fail with ENOSYS. Hardly the end of the world.
*/
no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached);
no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached);
for (;;) {
/* Only need to set the provider_entry_time if timeout != 0. The function
* will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
*/
if (timeout != 0)
uv__metrics_set_provider_entry_time(loop);
/* See the comment for max_safe_timeout for an explanation of why
* this is necessary. Executive summary: kernel bug workaround.
*/
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
timeout = max_safe_timeout;
if (sigmask != 0 && no_epoll_pwait != 0)
if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
abort();
if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
nfds = epoll_pwait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout,
&sigset);
if (nfds == -1 && errno == ENOSYS) {
uv__store_relaxed(&no_epoll_pwait_cached, 1);
no_epoll_pwait = 1;
}
} else {
nfds = epoll_wait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout);
if (nfds == -1 && errno == ENOSYS) {
uv__store_relaxed(&no_epoll_wait_cached, 1);
no_epoll_wait = 1;
}
}
if (sigmask != 0 && no_epoll_pwait != 0)
if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
abort();
/* Update loop->time unconditionally. It's tempting to skip the update when
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
* operating system didn't reschedule our process while in the syscall.
*/
SAVE_ERRNO(uv__update_time(loop));
if (nfds == 0) {
assert(timeout != -1);
if (reset_timeout != 0) {
timeout = user_timeout;
reset_timeout = 0;
}
if (timeout == -1)
continue;
if (timeout == 0)
return;
/* We may have been inside the system call for longer than |timeout|
* milliseconds so we need to update the timestamp to avoid drift.
*/
goto update_timeout;
}
if (nfds == -1) {
if (errno == ENOSYS) {
/* epoll_wait() or epoll_pwait() failed, try the other system call. */
assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
continue;
}
if (errno != EINTR)
abort();
if (reset_timeout != 0) {
timeout = user_timeout;
reset_timeout = 0;
}
if (timeout == -1)
continue;
if (timeout == 0)
return;
/* Interrupted by a signal. Update timeout and poll again. */
goto update_timeout;
}
have_signals = 0;
nevents = 0;
{
/* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */
union {
struct epoll_event* events;
uv__io_t* watchers;
} x;
x.events = events;
assert(loop->watchers != NULL);
loop->watchers[loop->nwatchers] = x.watchers;
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
}
for (i = 0; i < nfds; i++) {
pe = events + i;
fd = pe->data.fd;
/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
continue;
assert(fd >= 0);
assert((unsigned) fd < loop->nwatchers);
w = loop->watchers[fd];
if (w == NULL) {
/* File descriptor that we've stopped watching, disarm it.
*
* Ignore all errors because we may be racing with another thread
* when the file descriptor is closed.
*/
epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);
continue;
}
/* Give users only events they're interested in. Prevents spurious
* callbacks when previous callback invocation in this loop has stopped
* the current watcher. Also, filters out events that users has not
* requested us to watch.
*/
pe->events &= w->pevents | POLLERR | POLLHUP;
/* Work around an epoll quirk where it sometimes reports just the
* EPOLLERR or EPOLLHUP event. In order to force the event loop to
* move forward, we merge in the read/write events that the watcher
* is interested in; uv__read() and uv__write() will then deal with
* the error or hangup in the usual fashion.
*
* Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user
* reads the available data, calls uv_read_stop(), then sometime later
* calls uv_read_start() again. By then, libuv has forgotten about the
* hangup and the kernel won't report EPOLLIN again because there's
* nothing left to read. If anything, libuv is to blame here. The
* current hack is just a quick bandaid; to properly fix it, libuv
* needs to remember the error/hangup event. We should get that for
* free when we switch over to edge-triggered I/O.
*/
if (pe->events == POLLERR || pe->events == POLLHUP)
pe->events |=
w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
if (pe->events != 0) {
/* Run signal watchers last. This also affects child process watchers
* because those are implemented in terms of signal watchers.
*/
if (w == &loop->signal_io_watcher) {
have_signals = 1;
} else {
uv__metrics_update_idle_time(loop);
w->cb(loop, w, pe->events);
}
nevents++;
}
}
if (reset_timeout != 0) {
timeout = user_timeout;
reset_timeout = 0;
}
if (have_signals != 0) {
uv__metrics_update_idle_time(loop);
loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
}
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;
if (have_signals != 0)
return; /* Event loop should cycle now so don't poll again. */
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
/* Poll for more events but don't block this time. */
timeout = 0;
continue;
}
return;
}
if (timeout == 0)
return;
if (timeout == -1)
continue;
update_timeout:
assert(timeout > 0);
real_timeout -= (loop->time - base);
if (real_timeout <= 0)
return;
timeout = real_timeout;
}
}

View File

@ -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

62
deps/uv/src/unix/fs.c vendored
View File

@ -56,6 +56,10 @@
# define HAVE_PREADV 0
#endif
#if defined(__linux__)
# include "sys/utsname.h"
#endif
#if defined(__linux__) || defined(__sun)
# include <sys/sendfile.h>
# include <sys/sysmacros.h>
@ -901,6 +905,50 @@ out:
}
#ifdef __linux__
static unsigned uv__kernel_version(void) {
static unsigned cached_version;
struct utsname u;
unsigned version;
unsigned major;
unsigned minor;
unsigned patch;
version = uv__load_relaxed(&cached_version);
if (version != 0)
return version;
if (-1 == uname(&u))
return 0;
if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch))
return 0;
version = major * 65536 + minor * 256 + patch;
uv__store_relaxed(&cached_version, version);
return version;
}
/* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command
* in copy_file_range() when it shouldn't. There is no workaround except to
* fall back to a regular copy.
*/
static int uv__is_buggy_cephfs(int fd) {
struct statfs s;
if (-1 == fstatfs(fd, &s))
return 0;
if (s.f_type != /* CephFS */ 0xC36400)
return 0;
return uv__kernel_version() < /* 4.20.0 */ 0x041400;
}
#endif /* __linux__ */
static ssize_t uv__fs_sendfile(uv_fs_t* req) {
int in_fd;
int out_fd;
@ -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__) || \

View File

@ -595,8 +595,7 @@ out:
static int uv__fsevents_loop_init(uv_loop_t* loop) {
CFRunLoopSourceContext ctx;
uv__cf_loop_state_t* state;
pthread_attr_t attr_storage;
pthread_attr_t* attr;
pthread_attr_t attr;
int err;
if (loop->cf_state != NULL)
@ -641,25 +640,19 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
goto fail_signal_source_create;
}
/* In the unlikely event that pthread_attr_init() fails, create the thread
* with the default stack size. We'll use a little more address space but
* that in itself is not a fatal error.
*/
attr = &attr_storage;
if (pthread_attr_init(attr))
attr = NULL;
if (pthread_attr_init(&attr))
abort();
if (attr != NULL)
if (pthread_attr_setstacksize(attr, 4 * PTHREAD_STACK_MIN))
abort();
if (pthread_attr_setstacksize(&attr, uv__thread_stack_size()))
abort();
loop->cf_state = state;
/* uv_thread_t is an alias for pthread_t. */
err = UV__ERR(pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop));
err = UV__ERR(pthread_create(&loop->cf_thread, &attr, uv__cf_loop_runner, loop));
if (attr != NULL)
pthread_attr_destroy(attr);
if (pthread_attr_destroy(&attr))
abort();
if (err)
goto fail_thread_create;

View File

@ -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"

View File

@ -26,7 +26,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
@ -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) {
}
}

View File

@ -62,6 +62,17 @@
# include <AvailabilityMacros.h>
#endif
/*
* Define common detection for active Thread Sanitizer
* - clang uses __has_feature(thread_sanitizer)
* - gcc-7+ uses __SANITIZE_THREAD__
*/
#if defined(__has_feature)
# if __has_feature(thread_sanitizer)
# define __SANITIZE_THREAD__ 1
# endif
#endif
#if defined(PATH_MAX)
# define UV__PATH_MAX PATH_MAX
#else
@ -165,9 +176,11 @@ 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_ */

View File

@ -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);

View File

@ -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);

View File

@ -22,9 +22,6 @@
#ifndef UV_LINUX_SYSCALL_H_
#define UV_LINUX_SYSCALL_H_
#undef _GNU_SOURCE
#define _GNU_SOURCE
#include <stdint.h>
#include <signal.h>
#include <sys/types.h>

136
deps/uv/src/unix/os390-proctitle.c vendored Normal file
View File

@ -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 <stdlib.h>
#include <string.h>
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;
}

View File

@ -27,12 +27,6 @@
#include <termios.h>
#include <sys/msg.h>
#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();
}

View File

@ -28,6 +28,7 @@
#include <dirent.h>
#include <poll.h>
#include <pthread.h>
#include "zos-base.h"
#define EPOLL_CTL_ADD 1
#define EPOLL_CTL_DEL 2
@ -57,7 +58,6 @@ int epoll_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 **,

View File

@ -28,6 +28,8 @@
#include <builtins.h>
#include <termios.h>
#include <sys/msg.h>
#include <sys/resource.h>
#include "zos-base.h"
#if defined(__clang__)
#include "csrsic.h"
#else
@ -61,12 +63,6 @@
/* Address of the rsm control and enumeration area. */
#define CVTRCEP_OFFSET 0x490
/*
Number of frames currently available to system.
Excluded are frames backing perm storage, frames offline, and bad frames.
*/
#define RCEPOOL_OFFSET 0x004
/* Total number of frames currently on all available frame queues. */
#define RCEAFC_OFFSET 0x088
@ -144,102 +140,8 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
}
/*
Get the exe path using the thread entry information
in the address space.
*/
static int getexe(const int pid, char* buf, size_t len) {
struct {
int pid;
int thid[2];
char accesspid;
char accessthid;
char asid[2];
char loginname[8];
char flag;
char len;
} Input_data;
union {
struct {
char gthb[4];
int pid;
int thid[2];
char accesspid;
char accessthid[3];
int lenused;
int offsetProcess;
int offsetConTTY;
int offsetPath;
int offsetCommand;
int offsetFileData;
int offsetThread;
} Output_data;
char buf[2048];
} Output_buf;
struct Output_path_type {
char gthe[4];
short int len;
char path[1024];
};
int Input_length;
int Output_length;
void* Input_address;
void* Output_address;
struct Output_path_type* Output_path;
int rv;
int rc;
int rsn;
Input_length = PGTH_LEN;
Output_length = sizeof(Output_buf);
Output_address = &Output_buf;
Input_address = &Input_data;
memset(&Input_data, 0, sizeof Input_data);
Input_data.flag |= PGTHAPATH;
Input_data.pid = pid;
Input_data.accesspid = PGTH_CURRENT;
#ifdef _LP64
BPX4GTH(&Input_length,
&Input_address,
&Output_length,
&Output_address,
&rv,
&rc,
&rsn);
#else
BPX1GTH(&Input_length,
&Input_address,
&Output_length,
&Output_address,
&rv,
&rc,
&rsn);
#endif
if (rv == -1) {
errno = rc;
return -1;
}
/* Check highest byte to ensure data availability */
assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A');
/* Get the offset from the lowest 3 bytes */
Output_path = (struct Output_path_type*) ((char*) (&Output_buf) +
(Output_buf.Output_data.offsetPath & 0x00FFFFFF));
if (Output_path->len >= len) {
errno = ENOBUFS;
return -1;
}
uv__strscpy(buf, Output_path->path, len);
return 0;
static int getexe(char* buf, size_t len) {
return uv__strscpy(buf, __getargv()[0], len);
}
@ -259,8 +161,7 @@ int uv_exepath(char* buffer, size_t* size) {
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
pid = getpid();
res = getexe(pid, args, sizeof(args));
res = getexe(args, sizeof(args));
if (res < 0)
return UV_EINVAL;
@ -275,25 +176,25 @@ uint64_t uv_get_free_memory(void) {
data_area_ptr rcep = {0};
cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET);
freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4;
freeram = (uint64_t)*((uint32_t*)(rcep.deref + RCEAFC_OFFSET)) * 4096;
return freeram;
}
uint64_t uv_get_total_memory(void) {
uint64_t totalram;
data_area_ptr cvt = {0};
data_area_ptr rcep = {0};
cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET);
totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4;
return totalram;
/* Use CVTRLSTG to get the size of actual real storage online at IPL in K. */
return (uint64_t)((int)((char *__ptr32 *__ptr32 *)0)[4][214]) * 1024;
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
struct rlimit rl;
/* RLIMIT_MEMLIMIT return value is in megabytes rather than bytes. */
if (getrlimit(RLIMIT_MEMLIMIT, &rl) == 0)
return rl.rlim_cur * 1024 * 1024;
return 0; /* There is no memory limit set. */
}
@ -733,6 +634,10 @@ static int os390_message_queue_handler(uv__os390_epoll* ep) {
/* Some event that we are not interested in. */
return 0;
/* `__rfim_utok` is treated as text when it should be treated as binary while
* running in ASCII mode, resulting in an unwanted autoconversion.
*/
__a2e_l(msg.__rfim_utok, sizeof(msg.__rfim_utok));
handle = *(uv_fs_event_t**)(msg.__rfim_utok);
handle->cb(handle, uv__basename_r(handle->path), events, 0);
return 1;
@ -959,9 +864,6 @@ update_timeout:
}
}
void uv__set_process_title(const char* title) {
/* do nothing */
}
int uv__io_fork(uv_loop_t* loop) {
/*

View File

@ -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;

View File

@ -44,6 +44,10 @@ extern char **environ;
# include <grp.h>
#endif
#if defined(__MVS__)
# include "zos-base.h"
#endif
static void uv__chld(uv_signal_t* handle, int signum) {
uv_process_t* process;
@ -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

View File

@ -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;

View File

@ -164,7 +164,7 @@ static void uv__stream_osx_select(void* arg) {
else
max_fd = s->int_fd;
while (1) {
for (;;) {
/* Terminate on semaphore */
if (uv_sem_trywait(&s->close_sem) == 0)
break;
@ -195,7 +195,7 @@ static void uv__stream_osx_select(void* arg) {
/* Empty socketpair's buffer in case of interruption */
if (FD_ISSET(s->int_fd, s->sread))
while (1) {
for (;;) {
r = read(s->int_fd, buf, sizeof(buf));
if (r == sizeof(buf))
@ -799,33 +799,21 @@ static int uv__handle_fd(uv_handle_t* handle) {
}
}
static void uv__write(uv_stream_t* stream) {
static int uv__try_write(uv_stream_t* stream,
const uv_buf_t bufs[],
unsigned int nbufs,
uv_stream_t* send_handle) {
struct iovec* iov;
QUEUE* q;
uv_write_t* req;
int iovmax;
int iovcnt;
ssize_t n;
int err;
start:
assert(uv__stream_fd(stream) >= 0);
if (QUEUE_EMPTY(&stream->write_queue))
return;
q = QUEUE_HEAD(&stream->write_queue);
req = QUEUE_DATA(q, uv_write_t, queue);
assert(req->handle == stream);
/*
* Cast to iovec. We had to have our own uv_buf_t instead of iovec
* because Windows's WSABUF is not an iovec.
*/
assert(sizeof(uv_buf_t) == sizeof(struct iovec));
iov = (struct iovec*) &(req->bufs[req->write_index]);
iovcnt = req->nbufs - req->write_index;
iov = (struct iovec*) bufs;
iovcnt = nbufs;
iovmax = uv__getiovmax();
@ -837,8 +825,7 @@ start:
* Now do the actual writev. Note that we've been updating the pointers
* inside the iov each time we write. So there is no need to offset it.
*/
if (req->send_handle) {
if (send_handle != NULL) {
int fd_to_send;
struct msghdr msg;
struct cmsghdr *cmsg;
@ -847,12 +834,10 @@ start:
struct cmsghdr alias;
} scratch;
if (uv__is_closing(req->send_handle)) {
err = UV_EBADF;
goto error;
}
if (uv__is_closing(send_handle))
return UV_EBADF;
fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
fd_to_send = uv__handle_fd((uv_handle_t*) send_handle);
memset(&scratch, 0, sizeof(scratch));
@ -882,44 +867,68 @@ start:
do
n = sendmsg(uv__stream_fd(stream), &msg, 0);
while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
/* Ensure the handle isn't sent again in case this is a partial write. */
if (n >= 0)
req->send_handle = NULL;
} else {
do
n = uv__writev(uv__stream_fd(stream), iov, iovcnt);
while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
}
if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) {
err = UV__ERR(errno);
goto error;
if (n >= 0)
return n;
if (IS_TRANSIENT_WRITE_ERROR(errno, send_handle))
return UV_EAGAIN;
return UV__ERR(errno);
}
static void uv__write(uv_stream_t* stream) {
QUEUE* q;
uv_write_t* req;
ssize_t n;
assert(uv__stream_fd(stream) >= 0);
for (;;) {
if (QUEUE_EMPTY(&stream->write_queue))
return;
q = QUEUE_HEAD(&stream->write_queue);
req = QUEUE_DATA(q, uv_write_t, queue);
assert(req->handle == stream);
n = uv__try_write(stream,
&(req->bufs[req->write_index]),
req->nbufs - req->write_index,
req->send_handle);
/* Ensure the handle isn't sent again in case this is a partial write. */
if (n >= 0) {
req->send_handle = NULL;
if (uv__write_req_update(stream, req, n)) {
uv__write_req_finish(req);
return; /* TODO(bnoordhuis) Start trying to write the next request. */
}
} else if (n != UV_EAGAIN)
break;
/* If this is a blocking stream, try again. */
if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
continue;
/* We're not done. */
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
/* Notify select() thread about state change */
uv__stream_osx_interrupt_select(stream);
return;
}
if (n >= 0 && uv__write_req_update(stream, req, n)) {
uv__write_req_finish(req);
return; /* TODO(bnoordhuis) Start trying to write the next request. */
}
/* If this is a blocking stream, try again. */
if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
goto start;
/* We're not done. */
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
/* Notify select() thread about state change */
uv__stream_osx_interrupt_select(stream);
return;
error:
req->error = err;
req->error = n;
// XXX(jwn): this must call uv__stream_flush_write_queue(stream, n) here, since we won't generate any more events
uv__write_req_finish(req);
uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
if (!uv__io_active(&stream->io_watcher, POLLIN))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
}
@ -1001,9 +1010,9 @@ uv_handle_type uv__handle_type(int fd) {
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_HANDLE_READ_EOF;
stream->flags &= ~UV_HANDLE_READING;
stream->flags &= ~UV_HANDLE_READABLE;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
if (!uv__io_active(&stream->io_watcher, POLLOUT))
uv__handle_stop(stream);
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
stream->read_cb(stream, UV_EOF, buf);
}
@ -1188,12 +1197,12 @@ static void uv__read(uv_stream_t* stream) {
#endif
} else {
/* Error. User should call uv_close(). */
stream->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
stream->read_cb(stream, UV__ERR(errno), &buf);
if (stream->flags & UV_HANDLE_READING) {
stream->flags &= ~UV_HANDLE_READING;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
if (!uv__io_active(&stream->io_watcher, POLLOUT))
uv__handle_stop(stream);
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
}
}
@ -1276,6 +1285,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
req->cb = cb;
stream->shutdown_req = req;
stream->flags |= UV_HANDLE_SHUTTING;
stream->flags &= ~UV_HANDLE_WRITABLE;
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
uv__stream_osx_interrupt_select(stream);
@ -1390,14 +1400,9 @@ static void uv__stream_connect(uv_stream_t* stream) {
}
int uv_write2(uv_write_t* req,
uv_stream_t* stream,
const uv_buf_t bufs[],
unsigned int nbufs,
uv_stream_t* send_handle,
uv_write_cb cb) {
int empty_queue;
static int uv__check_before_write(uv_stream_t* stream,
unsigned int nbufs,
uv_stream_t* send_handle) {
assert(nbufs > 0);
assert((stream->type == UV_TCP ||
stream->type == UV_NAMED_PIPE ||
@ -1410,7 +1415,7 @@ int uv_write2(uv_write_t* req,
if (!(stream->flags & UV_HANDLE_WRITABLE))
return UV_EPIPE;
if (send_handle) {
if (send_handle != NULL) {
if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
return UV_EINVAL;
@ -1430,6 +1435,22 @@ int uv_write2(uv_write_t* req,
#endif
}
return 0;
}
int uv_write2(uv_write_t* req,
uv_stream_t* stream,
const uv_buf_t bufs[],
unsigned int nbufs,
uv_stream_t* send_handle,
uv_write_cb cb) {
int empty_queue;
int err;
err = uv__check_before_write(stream, nbufs, send_handle);
if (err < 0)
return err;
/* It's legal for write_queue_size > 0 even when the write_queue is empty;
* it means there are error-state requests in the write_completed_queue that
* will touch up write_queue_size later, see also uv__write_req_finish().
@ -1498,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);
err = uv__check_before_write(stream, nbufs, NULL);
if (err < 0)
return err;
r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb);
if (r != 0)
return r;
/* Remove not written bytes from write queue size */
written = uv__count_bufs(bufs, nbufs);
if (req.bufs != NULL)
req_size = uv__write_req_size(&req);
else
req_size = 0;
written -= req_size;
stream->write_queue_size -= req_size;
/* Unqueue request, regardless of immediateness */
QUEUE_REMOVE(&req.queue);
uv__req_unregister(stream->loop, &req);
if (req.bufs != req.bufsml)
uv__free(req.bufs);
req.bufs = NULL;
/* Do not poll for writable, if we wasn't before calling this */
if (!has_pollout) {
uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
uv__stream_osx_interrupt_select(stream);
}
if (written == 0 && req_size != 0)
return req.error < 0 ? req.error : UV_EAGAIN;
else
return written;
return uv__try_write(stream, bufs, nbufs, send_handle);
}
@ -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;

View File

@ -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

View File

@ -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. */

View File

@ -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 */

View File

@ -32,8 +32,6 @@
#endif
#include <sys/un.h>
#define UV__UDP_DGRAM_MAXSIZE (64 * 1024)
#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
@ -504,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)

View File

@ -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) {

View File

@ -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,

View File

@ -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

View File

@ -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;
}
}

View File

@ -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)) {

View File

@ -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;

View File

@ -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) {

View File

@ -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;

117
deps/uv/src/win/tcp.c vendored
View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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++) {

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

42
deps/uv/test/runner.c vendored
View File

@ -98,8 +98,8 @@ int run_tests(int benchmark_output) {
skip = (actual > 0 && 0 == strcmp(TASKS[0].task_name, "platform_output"));
qsort(TASKS + skip, actual - skip, sizeof(TASKS[0]), compare_task);
fprintf(stderr, "1..%d\n", total);
fflush(stderr);
fprintf(stdout, "1..%d\n", total);
fflush(stdout);
/* Run all tests. */
passed = 0;
@ -156,8 +156,8 @@ void log_tap_result(int test_count,
reason[0] = '\0';
}
fprintf(stderr, "%s %d - %s%s%s\n", result, test_count, test, directive, reason);
fflush(stderr);
fprintf(stdout, "%s %d - %s%s%s\n", result, test_count, test, directive, reason);
fflush(stdout);
}
@ -307,28 +307,28 @@ out:
/* Show error and output from processes if the test failed. */
if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) {
if (strlen(errmsg) > 0)
fprintf(stderr, "# %s\n", errmsg);
fprintf(stderr, "# ");
fflush(stderr);
fprintf(stdout, "# %s\n", errmsg);
fprintf(stdout, "# ");
fflush(stdout);
for (i = 0; i < process_count; i++) {
switch (process_output_size(&processes[i])) {
case -1:
fprintf(stderr, "Output from process `%s`: (unavailable)\n",
fprintf(stdout, "Output from process `%s`: (unavailable)\n",
process_get_name(&processes[i]));
fflush(stderr);
fflush(stdout);
break;
case 0:
fprintf(stderr, "Output from process `%s`: (no output)\n",
fprintf(stdout, "Output from process `%s`: (no output)\n",
process_get_name(&processes[i]));
fflush(stderr);
fflush(stdout);
break;
default:
fprintf(stderr, "Output from process `%s`:\n", process_get_name(&processes[i]));
fflush(stderr);
process_copy_output(&processes[i], stderr);
fprintf(stdout, "Output from process `%s`:\n", process_get_name(&processes[i]));
fflush(stdout);
process_copy_output(&processes[i], stdout);
break;
}
}
@ -337,18 +337,18 @@ out:
} else if (benchmark_output) {
switch (process_output_size(main_proc)) {
case -1:
fprintf(stderr, "%s: (unavailable)\n", test);
fflush(stderr);
fprintf(stdout, "%s: (unavailable)\n", test);
fflush(stdout);
break;
case 0:
fprintf(stderr, "%s: (no output)\n", test);
fflush(stderr);
fprintf(stdout, "%s: (no output)\n", test);
fflush(stdout);
break;
default:
for (i = 0; i < process_count; i++) {
process_copy_output(&processes[i], stderr);
process_copy_output(&processes[i], stdout);
}
break;
}
@ -378,8 +378,8 @@ int run_test_part(const char* test, const char* part) {
}
}
fprintf(stderr, "No test part with that name: %s:%s\n", test, part);
fflush(stderr);
fprintf(stdout, "No test part with that name: %s:%s\n", test, part);
fflush(stdout);
return 255;
}

1
deps/uv/test/task.h vendored
View File

@ -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"

View File

@ -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++;
}

View File

@ -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++;
}

View File

@ -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);
}

View File

@ -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++;
}

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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 */

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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++;
}

View File

@ -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);

View File

@ -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;
}

103
deps/uv/test/test-not-readable-on-eof.c vendored Normal file
View File

@ -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;
}

Some files were not shown because too many files have changed in this diff Show More