Commit 7cff2508 authored by Jason Madden's avatar Jason Madden

Update libuv to 1.42.0

fixes #1851
parent 05e0e372
......@@ -71,6 +71,8 @@ Updating libuv
rm -rf libuv
mv libuv-$LIBUV_VER libuv
rm -rf libuv/.github
rm -rf libuv/.readthedocs.yaml
rm -rf libuv/LINKS.md
rm -rf libuv/docs
rm -rf libuv/samples
rm -rf libuv/test/*.[ch] libuv/test/test.gyp # must leave the fixtures/ dir
......
......@@ -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>
......@@ -32,6 +35,7 @@ Nicholas Vavilov <vvnicholas@gmail.com>
Nick Logan <ugexe@cpan.org> <nlogan@gmail.com>
Rasmus Christian Pedersen <zerhacken@yahoo.com>
Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
Richard Lau <rlau@redhat.com> <riclau@uk.ibm.com>
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
Ryan Emery <seebees@gmail.com>
......@@ -47,8 +51,10 @@ Timothy J. Fontaine <tjfontaine@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
Yazhong Liu <yorkiefixer@gmail.com>
Yuki Okumura <mjt@cltn.org>
cjihrig <cjihrig@gmail.com>
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>
......@@ -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>
......@@ -212,7 +210,7 @@ guworks <ground.up.works@gmail.com>
RossBencina <rossb@audiomulch.com>
Roger A. Light <roger@atchoo.org>
chenttuuvv <chenttuuvv@yahoo.com>
Richard Lau <riclau@uk.ibm.com>
Richard Lau <rlau@redhat.com>
ronkorving <rkorving@wizcorp.jp>
Corbin Simpson <MostAwesomeDude@gmail.com>
Zachary Hamm <zsh@imipolexg.org>
......@@ -448,3 +446,36 @@ Aleksej Lebedev <root@zta.lk>
Nikolay Mitev <github@hmel.org>
Ulrik Strid <ulrik.strid@outlook.com>
Elad Lahav <elahav@qnx.com>
Elad Nachmias <eladn@pazam.net>
Darshan Sen <raisinten@gmail.com>
Simon Kadisch <simon.kadisch@k13-engineering.at>
Momtchil Momtchev <momtchil@momtchev.com>
Ethel Weston <66453757+ethelweston@users.noreply.github.com>
Drew DeVault <sir@cmpwn.com>
Mark Klein <klein@cscs.ch>
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>
......@@ -30,6 +30,14 @@ if(QEMU)
add_definitions(-D__QEMU__=1)
endif()
option(ASAN "Enable AddressSanitizer (ASan)" OFF)
if(ASAN AND CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang")
add_definitions(-D__ASAN__=1)
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
endif()
# Compiler check
string(CONCAT is-msvc $<OR:
$<C_COMPILER_ID:MSVC>,
......@@ -95,6 +103,9 @@ list(APPEND uv_cflags ${lint-no-conditional-assignment-msvc})
list(APPEND uv_cflags ${lint-no-unsafe-msvc})
list(APPEND uv_cflags ${lint-utf8-msvc} )
check_c_compiler_flag(-fno-strict-aliasing UV_F_STRICT_ALIASING)
list(APPEND uv_cflags $<$<BOOL:${UV_F_STRICT_ALIASING}>:-fno-strict-aliasing>)
set(uv_sources
src/fs-poll.c
src/idna.c
......@@ -108,7 +119,7 @@ set(uv_sources
src/version.c)
if(WIN32)
list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0600)
list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602)
list(APPEND uv_libraries
psapi
user32
......@@ -199,10 +210,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
src/unix/pthread-fixes.c
src/unix/random-getentropy.c
src/unix/random-getrandom.c
src/unix/random-sysctl-linux.c)
src/unix/random-sysctl-linux.c
src/unix/epoll.c)
endif()
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS390")
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux")
list(APPEND uv_sources src/unix/proctitle.c)
endif()
......@@ -243,7 +255,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
src/unix/linux-syscalls.c
src/unix/procfs-exepath.c
src/unix/random-getrandom.c
src/unix/random-sysctl-linux.c)
src/unix/random-sysctl-linux.c
src/unix/epoll.c)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
......@@ -256,9 +269,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
list(APPEND uv_defines PATH_MAX=255)
enable_language(CXX)
list(APPEND uv_defines PATH_MAX=1024)
list(APPEND uv_defines _AE_BIMODAL)
list(APPEND uv_defines _ALL_SOURCE)
list(APPEND uv_defines _ENHANCED_ASCII_EXT=0xFFFFFFFF)
list(APPEND uv_defines _ISOC99_SOURCE)
list(APPEND uv_defines _LARGE_TIME_API)
list(APPEND uv_defines _OPEN_MSGQ_EXT)
......@@ -269,14 +284,31 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
list(APPEND uv_defines _UNIX03_SOURCE)
list(APPEND uv_defines _UNIX03_THREADS)
list(APPEND uv_defines _UNIX03_WITHDRAWN)
list(APPEND uv_defines _XOPEN_SOURCE=600)
list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED)
list(APPEND uv_sources
src/unix/pthread-fixes.c
src/unix/os390.c
src/unix/os390-syscalls.c)
list(APPEND uv_cflags -Wc,DLL -Wc,exportall -Wc,xplink)
list(APPEND uv_libraries -Wl,xplink)
list(APPEND uv_test_libraries -Wl,xplink)
src/unix/os390-syscalls.c
src/unix/os390-proctitle.c)
list(APPEND uv_cflags
-q64
-qascii
-qexportall
-qgonumber
-qlongname
-qlibansi
-qfloat=IEEE
-qtune=10
-qarch=10
-qasm
-qasmlib=sys1.maclib:sys1.modgen)
find_library(ZOSLIB
NAMES zoslib
PATHS ${ZOSLIB_DIR}
PATH_SUFFIXES lib
)
list(APPEND uv_libraries ${ZOSLIB})
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "OS400")
......@@ -293,9 +325,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS400")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500)
list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500 _REENTRANT)
list(APPEND uv_libraries kstat nsl sendfile socket)
list(APPEND uv_sources src/unix/no-proctitle.c src/unix/sunos.c)
list(APPEND uv_sources
src/unix/no-proctitle.c
src/unix/sunos.c)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
......@@ -318,7 +352,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "QNX")
src/unix/bsd-ifaddrs.c
src/unix/no-proctitle.c
src/unix/no-fsevents.c)
list(APPEND uv_cflags -fno-strict-aliasing)
list(APPEND uv_libraries socket)
endif()
......@@ -340,6 +373,10 @@ target_include_directories(uv
$<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})
......@@ -351,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)
......@@ -448,6 +489,9 @@ if(LIBUV_BUILD_TESTS)
test/test-metrics.c
test/test-multiple-listen.c
test/test-mutexes.c
test/test-not-readable-nor-writable-on-read-error.c
test/test-not-readable-on-eof.c
test/test-not-writable-after-shutdown.c
test/test-osx-select.c
test/test-pass-always.c
test/test-ping-pong.c
......@@ -466,6 +510,7 @@ if(LIBUV_BUILD_TESTS)
test/test-poll-close-doesnt-corrupt-stack.c
test/test-poll-close.c
test/test-poll-closesocket.c
test/test-poll-multiple-handles.c
test/test-poll-oob.c
test/test-poll.c
test/test-process-priority.c
......@@ -479,6 +524,7 @@ if(LIBUV_BUILD_TESTS)
test/test-semaphore.c
test/test-shutdown-close.c
test/test-shutdown-eof.c
test/test-shutdown-simultaneous.c
test/test-shutdown-twice.c
test/test-signal-multiple-loops.c
test/test-signal-pending-on-close.c
......@@ -572,6 +618,11 @@ if(LIBUV_BUILD_TESTS)
add_test(NAME uv_test_a
COMMAND uv_run_tests_a
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
set_target_properties(uv_run_benchmarks_a PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(uv_run_tests PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(uv_run_tests_a PROPERTIES LINKER_LANGUAGE CXX)
endif()
endif()
if(UNIX OR MINGW)
......
......@@ -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
2020.09.26, Version 1.40.0 (Stable)
2021.07.21, Version 1.42.0 (Stable)
Changes since version 1.41.0:
* doc: fix code highlighting (Darshan Sen)
* test: move to ASSERT_NULL and ASSERT_NOT_NULL test macros (tjarlama)
* zos: build in ascii code page (Shuowang (Wayne) Zhang)
* zos: don't use nanosecond timestamp fields (Shuowang (Wayne) Zhang)
* zos: introduce zoslib (Shuowang (Wayne) Zhang)
* zos: use strnlen() from zoslib (Shuowang (Wayne) Zhang)
* zos: use nanosleep() from zoslib (Shuowang (Wayne) Zhang)
* zos: use __getargv() from zoslib to get exe path (Shuowang (Wayne) Zhang)
* zos: treat __rfim_utok as binary (Shuowang (Wayne) Zhang)
* zos: use execvpe() to set environ explictly (Shuowang (Wayne) Zhang)
* zos: use custom proctitle implementation (Shuowang (Wayne) Zhang)
* doc: add instructions for building on z/OS (Shuowang (Wayne) Zhang)
* linux,udp: enable full ICMP error reporting (Ondřej Surý)
* test: fix test-udp-send-unreachable (Ondřej Surý)
* include: fix typo in documentation (Tobias Nießen)
* chore: use for(;;) instead of while (Yash Ladha)
* test: remove string + int warning on udp-pummel (Juan José Arboleda)
* cmake: fix linker flags (Zhao Zhili)
* test: fix stack-use-after-scope (Zhao Zhili)
* unix: expose thread_stack_size() internally (Brandon Cheng)
* darwin: use RLIMIT_STACK for fsevents pthread (Brandon Cheng)
* darwin: abort on pthread_attr_init fail (Brandon Cheng)
* benchmark: remove unreachable code (Matvii Hodovaniuk)
* macos: fix memleaks in uv__get_cpu_speed (George Zhao)
* Make Thread Sanitizer aware of file descriptor close in uv__close() (Ondřej
Surý)
* darwin: fix iOS compilation and functionality (Hayden)
* linux: work around copy_file_range() cephfs bug (Ben Noordhuis)
* zos: implement uv_get_constrained_memory() (Shuowang (Wayne) Zhang)
* zos: fix uv_get_free_memory() (Shuowang (Wayne) Zhang)
* zos: use CVTRLSTG to get total memory accurately (Shuowang (Wayne) Zhang)
* ibmi: Handle interface names longer than 10 chars (Kevin Adler)
* docs: update read-the-docs version of sphinx (Jameson Nash)
* unix: refactor uv_try_write (twosee)
* linux-core: add proper divide by zero assert (yiyuaner)
* misc: remove unnecessary _GNU_SOURCE macros (Darshan Sen)
* test: log to stdout to conform TAP spec (bbara)
* win,fs: fix C4090 warning with MSVC (SeverinLeonhardt)
* build: some systems provide dlopen() in libc (Andy Fiddaman)
* include: add EOVERFLOW status code mapping (Darshan Sen)
* unix,fs: use uv__load_relaxed and uv__store_relaxed (Darshan Sen)
* win: fix string encoding issue of uv_os_gethostname (Eagle Liang)
* unix,process: add uv__write_errno helper function (Ricky Zhou)
* Re-merge "unix,stream: clear read/write states on close/eof" (Jameson Nash)
* unix,core: fix errno handling in uv__getpwuid_r (Darshan Sen)
* errors: map ESOCKTNOSUPPORT errno (Ryan Liptak)
* doc: uv_read_stop always succeeds (Simon Kissane)
* inet: fix inconsistent return value of inet_ntop6 (twosee)
* darwin: fix -Wsometimes-uninitialized warning (twosee)
* stream: introduce uv_try_write2 function (twosee)
* poll,win: UV_PRIORITIZED option should not assert (twosee)
* src: DragonFlyBSD has mmsghdr struct too (David Carlier)
* cleanup,win: Remove _WIN32 guards on threadpool (James M Snell)
* freebsd: fix an incompatible pointer type warning (Darshan Sen)
* core: Correct the conditionals for {cloexec,nonblock}_ioctl (Ali Mohammad
Pur)
* win,tcp: make uv_close work more like unix (Jameson Nash)
* doc: more accurate list of valid send_handle's (twosee)
* win,tcp: translate system errors correctly (twosee)
* unix: implement cpu_relax() on ppc64 (Ben Noordhuis)
* docs: move list of project links under PR control (Jameson Nash)
* test: wrong pointer arithmetic multiplier (Erkhes N)
* doc: switch discussion forum to github (Jameson Nash)
* idna: fix OOB read in punycode decoder (Ben Noordhuis)
* build: make sure -fvisibility=hidden is set (Santiago Gimeno)
* illumos: event ports to epoll (tjarlama)
* illumos,tty: UV_TTY_MODE_IO waits for 4 bytes (Joshua M. Clulow)
* doc: add vtjnash GPG ID (Jameson Nash)
* linux: read CPU model information on ppc (Richard Lau)
* darwin: fix uv_barrier race condition (Guilherme Íscaro)
* unix,stream: fix loop hang after uv_shutdown (Jameson Nash)
* doc,udp: note that suggested_size is 1 max-sized dgram (Ryan Liptak)
* mingw: fix building for ARM/AArch64 (Martin Storsjö)
* unix: strnlen is not available on Solaris 10 (Claes Nästén)
* sunos: restore use of event ports (Andy Fiddaman)
* sunos,cmake: use thread-safe errno (Andy Fiddaman)
2021.02.14, Version 1.41.0 (Stable), 1dff88e5161cba5c59276d2070d2e304e4dcb242
Changes since version 1.40.0:
* mailmap: update contact information for richardlau (Richard Lau)
* build: add asan checks (gengjiawen)
* unix: report bind error in uv_tcp_connect() (Ben Noordhuis)
* doc: uv_tcp_bind() never returns UV_EADDRINUSE (Ben Noordhuis)
* test: fix pump and tcp_write_batch benchmarks (Santiago Gimeno)
* doc: mark IBM i as Tier 2 support (Jesse Gorzinski)
* doc,poll: add notes (repeated cb & cancel pending cb) (Elad Nachmias)
* linux: fix -Wincompatible-pointer-types warning (Ben Noordhuis)
* linux: fix -Wsign-compare warning (Ben Noordhuis)
* android: add system call api guards (Ben Noordhuis)
* unix,win: harmonize uv_read_start() error handling (Ben Noordhuis)
* unix,win: more uv_read_start() argument validation (Ben Noordhuis)
* build: turn on -fno-strict-aliasing (Ben Noordhuis)
* stream: add uv_pipe and uv_socketpair to the API (Jameson Nash)
* unix,win: initialize timer `timeout` field (Ben Noordhuis)
* bsd-ifaddrs: improve comments (Darshan Sen)
* test: remove unnecessary uv_fs_stat() calls (Ben Noordhuis)
* fs: fix utime/futime timestamp rounding errors (Ben Noordhuis)
* test: ensure reliable floating point comparison (Jameson Nash)
* unix,fs: fix uv_fs_sendfile() (Santiago Gimeno)
* unix: fix uv_fs_stat when using statx (Simon Kadisch)
* linux,macos: fix uv_set_process_title regression (Momtchil Momtchev)
* doc: clarify UDP errors and recvmmsg (Ethel Weston)
* test-getaddrinfo: use example.invalid (Drew DeVault)
* Revert "build: fix android autotools build" (Bernardo Ramos)
* unix,fs: on DVS fs, statx returns EOPNOTSUPP (Mark Klein)
* win, fs: mkdir really return UV_EINVAL for invalid names (Nicholas Vavilov)
* tools: migrate tools/make_dist_html.py to python3 (Dominique Dumont)
* unix: fix uv_uptime() on linux (schamberg97)
* unix: check for partial copy_file_range support (Momtchil Momtchev)
* win: bump minimum supported version to windows 8 (Ben Noordhuis)
* poll,unix: ensure safety of rapid fd reuse (Bob Weinand)
* test: fix some warnings (Issam E. Maghni)
* unix: fix uv_uptime() regression (Santiago Gimeno)
* doc: fix versionadded metadata (cjihrig)
* test: fix 'incompatible pointer types' warnings (cjihrig)
* unix: check for EXDEV in uv__fs_sendfile() (Darshan Sen)
2020.09.26, Version 1.40.0 (Stable), 4e69e333252693bd82d6338d6124f0416538dbfc
Changes since version 1.39.0:
......
......@@ -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)
......
......@@ -56,7 +56,7 @@ if WINNT
uvinclude_HEADERS += include/uv/win.h include/uv/tree.h
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
-DWIN32_LEAN_AND_MEAN \
-D_WIN32_WINNT=0x0600
-D_WIN32_WINNT=0x0602
libuv_la_SOURCES += src/win/async.c \
src/win/atomicops-inl.h \
src/win/core.c \
......@@ -206,6 +206,9 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-metrics.c \
test/test-multiple-listen.c \
test/test-mutexes.c \
test/test-not-readable-nor-writable-on-read-error.c \
test/test-not-readable-on-eof.c \
test/test-not-writable-after-shutdown.c \
test/test-osx-select.c \
test/test-pass-always.c \
test/test-ping-pong.c \
......@@ -225,6 +228,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-poll-close.c \
test/test-poll-close-doesnt-corrupt-stack.c \
test/test-poll-closesocket.c \
test/test-poll-multiple-handles.c \
test/test-poll-oob.c \
test/test-process-priority.c \
test/test-process-title.c \
......@@ -237,6 +241,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-semaphore.c \
test/test-shutdown-close.c \
test/test-shutdown-eof.c \
test/test-shutdown-simultaneous.c \
test/test-shutdown-twice.c \
test/test-signal-multiple-loops.c \
test/test-signal-pending-on-close.c \
......@@ -385,13 +390,10 @@ if ANDROID
uvinclude_HEADERS += include/uv/android-ifaddrs.h
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
src/unix/linux-core.c \
src/unix/linux-inotify.c \
src/unix/linux-syscalls.c \
src/unix/procfs-exepath.c \
src/unix/pthread-fixes.c \
src/unix/random-getrandom.c \
src/unix/random-sysctl-linux.c
src/unix/random-sysctl-linux.c \
src/unix/epoll.c
endif
if CYGWIN
......@@ -472,7 +474,8 @@ libuv_la_SOURCES += src/unix/linux-core.c \
src/unix/procfs-exepath.c \
src/unix/proctitle.c \
src/unix/random-getrandom.c \
src/unix/random-sysctl-linux.c
src/unix/random-sysctl-linux.c \
src/unix/epoll.c
test_run_tests_LDFLAGS += -lutil
endif
......
......@@ -5,7 +5,7 @@
libuv is a multi-platform support library with a focus on asynchronous I/O. It
was primarily developed for use by [Node.js][], but it's also
used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/),
[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/wiki/Projects-that-use-libuv).
[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/blob/v1.x/LINKS.md).
## Feature highlights
......@@ -48,9 +48,8 @@ The documentation is licensed under the CC BY 4.0 license. Check the [LICENSE-do
## Community
* [Support](https://github.com/libuv/help)
* [Support](https://github.com/libuv/libuv/discussions)
* [Mailing list](http://groups.google.com/group/libuv)
* [IRC chatroom (#libuv@irc.freenode.org)](http://webchat.freenode.net?channels=libuv&uio=d4)
## Documentation
......@@ -286,6 +285,16 @@ listed in `test/benchmark-list.h`.
Check the [SUPPORTED_PLATFORMS file](SUPPORTED_PLATFORMS.md).
### `-fno-strict-aliasing`
It is recommended to turn on the `-fno-strict-aliasing` compiler flag in
projects that use libuv. The use of ad hoc "inheritance" in the libuv API
may not be safe in the presence of compiler optimizations that depend on
strict aliasing.
MSVC does not have an equivalent flag but it also does not appear to need it
at the time of writing (December 2019.)
### AIX Notes
AIX compilation using IBM XL C/C++ requires version 12.1 or greater.
......@@ -298,6 +307,13 @@ describes the package in more detail.
### z/OS Notes
z/OS compilation requires [ZOSLIB](https://github.com/ibmruntimes/zoslib) to be installed. When building with [CMake][], use the flag `-DZOSLIB_DIR` to specify the path to [ZOSLIB](https://github.com/ibmruntimes/zoslib):
```bash
$ (cd build && cmake .. -DBUILD_TESTING=ON -DZOSLIB_DIR=/path/to/zoslib)
$ cmake --build build
```
z/OS creates System V semaphores and message queues. These persist on the system
after the process terminates unless the event loop is closed.
......
......@@ -4,14 +4,14 @@
|---|---|---|---|
| GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | |
| macOS | Tier 1 | macOS >= 10.7 | |
| Windows | Tier 1 | >= Windows 7 | MSVC 2008 and later are supported |
| Windows | Tier 1 | >= Windows 8 | VS 2015 and later are supported |
| FreeBSD | Tier 1 | >= 10 | |
| AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix |
| IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos |
| Linux with musl | Tier 2 | musl >= 1.0 | |
| SmartOS | Tier 2 | >= 14.4 | Maintainers: @libuv/smartos |
| Android | Tier 3 | NDK >= r15b | |
| IBM i | Tier 3 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
| MinGW | Tier 3 | MinGW32 and MinGW-w64 | |
| SunOS | Tier 3 | Solaris 121 and later | |
| Other | Tier 3 | N/A | |
......
......@@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
AC_INIT([libuv], [1.40.0], [https://github.com/libuv/libuv/issues])
AC_INIT([libuv], [1.42.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
......@@ -24,7 +24,11 @@ AC_ENABLE_SHARED
AC_ENABLE_STATIC
AC_PROG_CC
AM_PROG_CC_C_O
CC_FLAG_VISIBILITY #[-fvisibility=hidden]
CC_ATTRIBUTE_VISIBILITY([default], [
CC_FLAG_VISIBILITY([CFLAGS="${CFLAGS} -fvisibility=hidden"])
])
CC_CHECK_CFLAGS_APPEND([-fno-strict-aliasing])
CC_CHECK_CFLAGS_APPEND([-g])
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
CC_CHECK_CFLAGS_APPEND([-Wall])
......@@ -42,7 +46,7 @@ AX_PTHREAD([
LIBS="$LIBS $PTHREAD_LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
])
AC_CHECK_LIB([dl], [dlopen])
AC_SEARCH_LIBS([dlopen], [dl])
AC_SEARCH_LIBS([kstat_lookup], [kstat])
AC_SEARCH_LIBS([gethostbyname], [nsl])
AC_SEARCH_LIBS([perfstat_cpu], [perfstat])
......
......@@ -126,6 +126,7 @@ extern "C" {
XX(ENOTEMPTY, "directory not empty") \
XX(ENOTSOCK, "socket operation on non-socket") \
XX(ENOTSUP, "operation not supported on socket") \
XX(EOVERFLOW, "value too large for defined data type") \
XX(EPERM, "operation not permitted") \
XX(EPIPE, "broken pipe") \
XX(EPROTO, "protocol error") \
......@@ -148,6 +149,7 @@ extern "C" {
XX(ENOTTY, "inappropriate ioctl for device") \
XX(EFTYPE, "inappropriate file type or format") \
XX(EILSEQ, "illegal byte sequence") \
XX(ESOCKTNOSUPPORT, "socket type not supported") \
#define UV_HANDLE_TYPE_MAP(XX) \
XX(ASYNC, async) \
......@@ -475,6 +477,12 @@ UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd);
UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);
UV_EXTERN int uv_pipe(uv_file fds[2], int read_flags, int write_flags);
UV_EXTERN int uv_socketpair(int type,
int protocol,
uv_os_sock_t socket_vector[2],
int flags0,
int flags1);
#define UV_STREAM_FIELDS \
/* number of bytes queued for writing */ \
......@@ -520,6 +528,10 @@ UV_EXTERN int uv_write2(uv_write_t* req,
UV_EXTERN int uv_try_write(uv_stream_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs);
UV_EXTERN int uv_try_write2(uv_stream_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
uv_stream_t* send_handle);
/* uv_write_t is a subclass of uv_req_t. */
struct uv_write_s {
......@@ -620,7 +632,14 @@ enum uv_udp_flags {
* in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL.
*/
UV_UDP_MMSG_FREE = 16,
/*
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
* Linux. This stops the Linux kernel from suppressing some ICMP error
* messages and enables full ICMP error reporting for faster failover.
* This flag is no-op on platforms other than Linux.
*/
UV_UDP_LINUX_RECVERR = 32,
/*
* Indicates that recvmmsg should be used, if available.
*/
......@@ -933,10 +952,13 @@ typedef enum {
UV_WRITABLE_PIPE = 0x20,
/*
* Open the child pipe handle in overlapped mode on Windows.
* On Unix it is silently ignored.
* When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the
* handle in non-blocking mode in the child. This may cause loss of data,
* if the child is not designed to handle to encounter this mode,
* but can also be significantly more efficient.
*/
UV_OVERLAPPED_PIPE = 0x40
UV_NONBLOCK_PIPE = 0x40,
UV_OVERLAPPED_PIPE = 0x40 /* old name, for compatibility */
} uv_stdio_flags;
typedef struct uv_stdio_container_s {
......
......@@ -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_ */
......@@ -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) \
......
......@@ -31,7 +31,7 @@
*/
#define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 40
#define UV_VERSION_MINOR 42
#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
......
......@@ -19,6 +19,7 @@
#include "uv.h"
#include "idna.h"
#include <assert.h>
#include <string.h>
static unsigned uv__utf8_decode1_slow(const char** p,
......@@ -32,7 +33,7 @@ static unsigned uv__utf8_decode1_slow(const char** p,
if (a > 0xF7)
return -1;
switch (*p - pe) {
switch (pe - *p) {
default:
if (a > 0xEF) {
min = 0x10000;
......@@ -62,6 +63,8 @@ static unsigned uv__utf8_decode1_slow(const char** p,
a = 0;
break;
}
/* Fall through. */
case 0:
return -1; /* Invalid continuation byte. */
}
......@@ -88,6 +91,8 @@ static unsigned uv__utf8_decode1_slow(const char** p,
unsigned uv__utf8_decode1(const char** p, const char* pe) {
unsigned a;
assert(*p < pe);
a = (unsigned char) *(*p)++;
if (a < 128)
......@@ -96,9 +101,6 @@ unsigned uv__utf8_decode1(const char** p, const char* pe) {
return uv__utf8_decode1_slow(p, pe, a);
}
#define foreach_codepoint(c, p, pe) \
for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;)
static int uv__idna_toascii_label(const char* s, const char* se,
char** d, char* de) {
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
......@@ -121,15 +123,22 @@ static int uv__idna_toascii_label(const char* s, const char* se,
ss = s;
todo = 0;
foreach_codepoint(c, &s, se) {
/* Note: after this loop we've visited all UTF-8 characters and know
* they're legal so we no longer need to check for decode errors.
*/
while (s < se) {
c = uv__utf8_decode1(&s, se);
if (c == -1u)
return UV_EINVAL;
if (c < 128)
h++;
else if (c == (unsigned) -1)
return UV_EINVAL;
else
todo++;
}
/* Only write "xn--" when there are non-ASCII characters. */
if (todo > 0) {
if (*d < de) *(*d)++ = 'x';
if (*d < de) *(*d)++ = 'n';
......@@ -137,9 +146,13 @@ static int uv__idna_toascii_label(const char* s, const char* se,
if (*d < de) *(*d)++ = '-';
}
/* Write ASCII characters. */
x = 0;
s = ss;
foreach_codepoint(c, &s, se) {
while (s < se) {
c = uv__utf8_decode1(&s, se);
assert(c != -1u);
if (c > 127)
continue;
......@@ -166,10 +179,15 @@ static int uv__idna_toascii_label(const char* s, const char* se,
while (todo > 0) {
m = -1;
s = ss;
foreach_codepoint(c, &s, se)
while (s < se) {
c = uv__utf8_decode1(&s, se);
assert(c != -1u);
if (c >= n)
if (c < m)
m = c;
}
x = m - n;
y = h + 1;
......@@ -181,7 +199,10 @@ static int uv__idna_toascii_label(const char* s, const char* se,
n = m;
s = ss;
foreach_codepoint(c, &s, se) {
while (s < se) {
c = uv__utf8_decode1(&s, se);
assert(c != -1u);
if (c < n)
if (++delta == 0)
return UV_E2BIG; /* Overflow. */
......@@ -245,8 +266,6 @@ static int uv__idna_toascii_label(const char* s, const char* se,
return 0;
}
#undef foreach_codepoint
long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
const char* si;
const char* st;
......@@ -256,10 +275,14 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
ds = d;
for (si = s; si < se; /* empty */) {
si = s;
while (si < se) {
st = si;
c = uv__utf8_decode1(&si, se);
if (c == -1u)
return UV_EINVAL;
if (c != '.')
if (c != 0x3002) /* 。 */
if (c != 0xFF0E) /* . */
......
......@@ -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;
}
......
......@@ -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
}
......
......@@ -58,6 +58,7 @@ static int timer_less_than(const struct heap_node* ha,
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
handle->timer_cb = NULL;
handle->timeout = 0;
handle->repeat = 0;
return 0;
}
......
......@@ -214,7 +214,7 @@ static int uv__async_start(uv_loop_t* loop) {
pipefd[0] = err;
pipefd[1] = -1;
#else
err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE);
if (err < 0)
return err;
#endif
......
......@@ -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
}
......
......@@ -42,8 +42,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
return 1;
#if !defined(__CYGWIN__) && !defined(__MSYS__)
/*
* If `exclude_type` is `UV__EXCLUDE_IFPHYS`, just see whether `sa_family`
* equals to `AF_LINK` or not. Otherwise, the result depends on the operation
* If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family`
* equals `AF_LINK`. Otherwise, the result depends on the operating
* system with `AF_LINK` or `PF_INET`.
*/
if (exclude_type == UV__EXCLUDE_IFPHYS)
......@@ -53,7 +53,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
defined(__HAIKU__)
/*
* On BSD getifaddrs returns information related to the raw underlying
* devices. We're not interested in this information.
* devices. We're not interested in this information.
*/
if (ent->ifa_addr->sa_family == AF_LINK)
return 1;
......
......@@ -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;
......@@ -925,13 +934,12 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
if (w->pevents == 0) {
QUEUE_REMOVE(&w->watcher_queue);
QUEUE_INIT(&w->watcher_queue);
w->events = 0;
if (loop->watchers[w->fd] != NULL) {
assert(loop->watchers[w->fd] == w);
if (w == loop->watchers[w->fd]) {
assert(loop->nfds > 0);
loop->watchers[w->fd] = NULL;
loop->nfds--;
w->events = 0;
}
}
else if (QUEUE_EMPTY(&w->watcher_queue))
......@@ -1175,7 +1183,9 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
if (buf == NULL)
return UV_ENOMEM;
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
do
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
while (r == EINTR);
if (r != ERANGE)
break;
......@@ -1185,7 +1195,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
if (r != 0) {
uv__free(buf);
return -r;
return UV__ERR(r);
}
if (result == NULL) {
......@@ -1571,7 +1581,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
buf[*buflen] = '\0';
return 0;
}
}
/* Case iii). Search PATH environment variable */
cloned_path = NULL;
......
......@@ -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);
......
This diff is collapsed.
......@@ -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
......
......@@ -56,8 +56,13 @@
# 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>
#endif
#if defined(__APPLE__)
......@@ -212,14 +217,30 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
struct timespec ts;
ts.tv_sec = time;
ts.tv_nsec = (uint64_t)(time * 1000000) % 1000000 * 1000;
ts.tv_nsec = (time - ts.tv_sec) * 1e9;
/* TODO(bnoordhuis) Remove this. utimesat() has nanosecond resolution but we
* stick to microsecond resolution for the sake of consistency with other
* platforms. I'm the original author of this compatibility hack but I'm
* less convinced it's useful nowadays.
*/
ts.tv_nsec -= ts.tv_nsec % 1000;
if (ts.tv_nsec < 0) {
ts.tv_nsec += 1e9;
ts.tv_sec -= 1;
}
return ts;
}
UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
struct timeval tv;
tv.tv_sec = time;
tv.tv_usec = (uint64_t)(time * 1000000) % 1000000;
tv.tv_usec = (time - tv.tv_sec) * 1e6;
if (tv.tv_usec < 0) {
tv.tv_usec += 1e6;
tv.tv_sec -= 1;
}
return tv;
}
......@@ -227,9 +248,6 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
#if defined(__linux__) \
|| defined(_AIX71) \
|| defined(__HAIKU__)
/* utimesat() has nanosecond resolution but we stick to microseconds
* for the sake of consistency with other platforms.
*/
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
......@@ -887,6 +905,50 @@ out:
}
#ifdef __linux__
static unsigned uv__kernel_version(void) {
static unsigned cached_version;
struct utsname u;
unsigned version;
unsigned major;
unsigned minor;
unsigned patch;
version = uv__load_relaxed(&cached_version);
if (version != 0)
return version;
if (-1 == uname(&u))
return 0;
if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch))
return 0;
version = major * 65536 + minor * 256 + patch;
uv__store_relaxed(&cached_version, version);
return version;
}
/* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command
* in copy_file_range() when it shouldn't. There is no workaround except to
* fall back to a regular copy.
*/
static int uv__is_buggy_cephfs(int fd) {
struct statfs s;
if (-1 == fstatfs(fd, &s))
return 0;
if (s.f_type != /* CephFS */ 0xC36400)
return 0;
return uv__kernel_version() < /* 4.20.0 */ 0x041400;
}
#endif /* __linux__ */
static ssize_t uv__fs_sendfile(uv_fs_t* req) {
int in_fd;
int out_fd;
......@@ -903,14 +965,25 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
#ifdef __linux__
{
static int copy_file_range_support = 1;
static int no_copy_file_range_support;
if (copy_file_range_support) {
r = uv__fs_copy_file_range(in_fd, NULL, out_fd, &off, req->bufsml[0].len, 0);
if (uv__load_relaxed(&no_copy_file_range_support) == 0) {
r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0);
if (r == -1 && errno == ENOSYS) {
/* ENOSYS - it will never work */
errno = 0;
uv__store_relaxed(&no_copy_file_range_support, 1);
} else if (r == -1 && errno == EACCES && uv__is_buggy_cephfs(in_fd)) {
/* EACCES - pre-4.20 kernels have a bug where CephFS uses the RADOS
copy-from command when it shouldn't */
errno = 0;
uv__store_relaxed(&no_copy_file_range_support, 1);
} else if (r == -1 && (errno == ENOTSUP || errno == EXDEV)) {
/* ENOTSUP - it could work on another file system type */
/* EXDEV - it will not work when in_fd and out_fd are not on the same
mounted filesystem (pre Linux 5.3) */
errno = 0;
copy_file_range_support = 0;
} else {
goto ok;
}
......@@ -1010,9 +1083,6 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|| defined(_AIX71) \
|| defined(__sun) \
|| defined(__HAIKU__)
/* utimesat() has nanosecond resolution but we stick to microseconds
* for the sake of consistency with other platforms.
*/
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
......@@ -1220,7 +1290,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
if (fstatfs(dstfd, &s) == -1)
goto out;
if (s.f_type != /* CIFS */ 0xFF534D42u)
if ((unsigned) s.f_type != /* CIFS */ 0xFF534D42u)
goto out;
}
......@@ -1340,7 +1410,8 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
dst->st_birthtim.tv_nsec = src->st_ctimensec;
dst->st_flags = 0;
dst->st_gen = 0;
#elif !defined(_AIX) && ( \
#elif !defined(_AIX) && \
!defined(__MVS__) && ( \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
......@@ -1420,8 +1491,9 @@ static int uv__fs_statx(int fd,
case -1:
/* EPERM happens when a seccomp filter rejects the system call.
* Has been observed with libseccomp < 2.3.3 and docker < 18.04.
* EOPNOTSUPP is used on DVS exported filesystems
*/
if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
if (errno != EINVAL && errno != EPERM && errno != ENOSYS && errno != EOPNOTSUPP)
return -1;
/* Fall through. */
default:
......@@ -1434,12 +1506,12 @@ static int uv__fs_statx(int fd,
return UV_ENOSYS;
}
buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
buf->st_dev = makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor);
buf->st_mode = statxbuf.stx_mode;
buf->st_nlink = statxbuf.stx_nlink;
buf->st_uid = statxbuf.stx_uid;
buf->st_gid = statxbuf.stx_gid;
buf->st_rdev = statxbuf.stx_rdev_major;
buf->st_rdev = makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor);
buf->st_ino = statxbuf.stx_ino;
buf->st_size = statxbuf.stx_size;
buf->st_blksize = statxbuf.stx_blksize;
......
......@@ -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;
......
......@@ -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"
......
......@@ -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) {
}
\ No newline at end of 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);
......@@ -282,12 +297,6 @@ int uv___stream_fd(const uv_stream_t* handle);
#define uv__stream_fd(handle) ((handle)->io_watcher.fd)
#endif /* defined(__APPLE__) */
#ifdef O_NONBLOCK
# define UV__F_NONBLOCK O_NONBLOCK
#else
# define UV__F_NONBLOCK 1
#endif
int uv__make_pipe(int fds[2], int flags);
#if defined(__APPLE__)
......@@ -327,7 +336,8 @@ int uv__getsockpeername(const uv_handle_t* handle,
#if defined(__linux__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__)
defined(__FreeBSD_kernel__) || \
defined(__DragonFly__)
#define HAVE_MMSG 1
struct uv__mmsghdr {
struct msghdr msg_hdr;
......@@ -340,5 +350,11 @@ int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen);
#define HAVE_MMSG 0
#endif
#if defined(__sun)
#if !defined(_POSIX_VERSION) || _POSIX_VERSION < 200809L
size_t strnlen(const char* s, size_t maxlen);
#endif
#endif
#endif /* UV_UNIX_INTERNAL_H_ */
This diff is collapsed.
......@@ -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);
......
......@@ -194,37 +194,37 @@ int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
#if defined(__NR_preadv)
return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
#else
#if !defined(__NR_preadv) || defined(__ANDROID_API__) && __ANDROID_API__ < 24
return errno = ENOSYS, -1;
#else
return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
#endif
}
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
#if defined(__NR_pwritev)
return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
#else
#if !defined(__NR_pwritev) || defined(__ANDROID_API__) && __ANDROID_API__ < 24
return errno = ENOSYS, -1;
#else
return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
#endif
}
int uv__dup3(int oldfd, int newfd, int flags) {
#if defined(__NR_dup3)
return syscall(__NR_dup3, oldfd, newfd, flags);
#else
#if !defined(__NR_dup3) || defined(__ANDROID_API__) && __ANDROID_API__ < 21
return errno = ENOSYS, -1;
#else
return syscall(__NR_dup3, oldfd, newfd, flags);
#endif
}
ssize_t
uv__fs_copy_file_range(int fd_in,
ssize_t* off_in,
off_t* off_in,
int fd_out,
ssize_t* off_out,
off_t* off_out,
size_t len,
unsigned int flags)
{
......@@ -247,21 +247,18 @@ int uv__statx(int dirfd,
int flags,
unsigned int mask,
struct uv__statx* statxbuf) {
/* __NR_statx make Android box killed by SIGSYS.
* That looks like a seccomp2 sandbox filter rejecting the system call.
*/
#if defined(__NR_statx) && !defined(__ANDROID__)
return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
#else
#if !defined(__NR_statx) || defined(__ANDROID_API__) && __ANDROID_API__ < 30
return errno = ENOSYS, -1;
#else
return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
#endif
}
ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) {
#if defined(__NR_getrandom)
return syscall(__NR_getrandom, buf, buflen, flags);
#else
#if !defined(__NR_getrandom) || defined(__ANDROID_API__) && __ANDROID_API__ < 28
return errno = ENOSYS, -1;
#else
return syscall(__NR_getrandom, buf, buflen, flags);
#endif
}
......@@ -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>
......@@ -66,9 +63,9 @@ ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset)
int uv__dup3(int oldfd, int newfd, int flags);
ssize_t
uv__fs_copy_file_range(int fd_in,
ssize_t* off_in,
off_t* off_in,
int fd_out,
ssize_t* off_out,
off_t* off_out,
size_t len,
unsigned int flags);
int uv__statx(int dirfd,
......
/* 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;
}
......@@ -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();
}
......
......@@ -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 **,
......
......@@ -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) {
/*
......
......@@ -379,3 +379,57 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
return r != -1 ? 0 : UV__ERR(errno);
}
int uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) {
uv_os_fd_t temp[2];
int err;
#if defined(__FreeBSD__) || defined(__linux__)
int flags = O_CLOEXEC;
if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE))
flags |= UV_FS_O_NONBLOCK;
if (pipe2(temp, flags))
return UV__ERR(errno);
if (flags & UV_FS_O_NONBLOCK) {
fds[0] = temp[0];
fds[1] = temp[1];
return 0;
}
#else
if (pipe(temp))
return UV__ERR(errno);
if ((err = uv__cloexec(temp[0], 1)))
goto fail;
if ((err = uv__cloexec(temp[1], 1)))
goto fail;
#endif
if (read_flags & UV_NONBLOCK_PIPE)
if ((err = uv__nonblock(temp[0], 1)))
goto fail;
if (write_flags & UV_NONBLOCK_PIPE)
if ((err = uv__nonblock(temp[1], 1)))
goto fail;
fds[0] = temp[0];
fds[1] = temp[1];
return 0;
fail:
uv__close(temp[0]);
uv__close(temp[1]);
return err;
}
int uv__make_pipe(int fds[2], int flags) {
return uv_pipe(fds,
flags & UV_NONBLOCK_PIPE,
flags & UV_NONBLOCK_PIPE);
}
......@@ -79,9 +79,10 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
* Workaround for e.g. kqueue fds not supporting ioctls.
*/
err = uv__nonblock(fd, 1);
#if UV__NONBLOCK_IS_IOCTL
if (err == UV_ENOTTY)
if (uv__nonblock == uv__nonblock_ioctl)
err = uv__nonblock_fcntl(fd, 1);
err = uv__nonblock_fcntl(fd, 1);
#endif
if (err)
return err;
......@@ -116,12 +117,21 @@ int uv_poll_stop(uv_poll_t* handle) {
int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
uv__io_t** watchers;
uv__io_t* w;
int events;
assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT |
UV_PRIORITIZED)) == 0);
assert(!uv__is_closing(handle));
watchers = handle->loop->watchers;
w = &handle->io_watcher;
if (uv__fd_exists(handle->loop, w->fd))
if (watchers[w->fd] != w)
return UV_EEXIST;
uv__poll_stop(handle);
if (pevents == 0)
......
......@@ -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;
......@@ -111,68 +115,6 @@ static void uv__chld(uv_signal_t* handle, int signum) {
assert(QUEUE_EMPTY(&pending));
}
static int uv__make_socketpair(int fds[2]) {
#if defined(__FreeBSD__) || defined(__linux__)
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds))
return UV__ERR(errno);
return 0;
#else
int err;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
return UV__ERR(errno);
err = uv__cloexec(fds[0], 1);
if (err == 0)
err = uv__cloexec(fds[1], 1);
if (err != 0) {
uv__close(fds[0]);
uv__close(fds[1]);
return UV__ERR(errno);
}
return 0;
#endif
}
int uv__make_pipe(int fds[2], int flags) {
#if defined(__FreeBSD__) || defined(__linux__)
if (pipe2(fds, flags | O_CLOEXEC))
return UV__ERR(errno);
return 0;
#else
if (pipe(fds))
return UV__ERR(errno);
if (uv__cloexec(fds[0], 1))
goto fail;
if (uv__cloexec(fds[1], 1))
goto fail;
if (flags & UV__F_NONBLOCK) {
if (uv__nonblock(fds[0], 1))
goto fail;
if (uv__nonblock(fds[1], 1))
goto fail;
}
return 0;
fail:
uv__close(fds[0]);
uv__close(fds[1]);
return UV__ERR(errno);
#endif
}
/*
* Used for initializing stdio streams like options.stdin_stream. Returns
* zero on success. See also the cleanup section in uv_spawn().
......@@ -192,7 +134,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
if (container->data.stream->type != UV_NAMED_PIPE)
return UV_EINVAL;
else
return uv__make_socketpair(fds);
return uv_socketpair(SOCK_STREAM, 0, fds, 0, 0);
case UV_INHERIT_FD:
case UV_INHERIT_STREAM:
......@@ -259,6 +201,12 @@ static void uv__write_int(int fd, int val) {
}
static void uv__write_errno(int error_fd) {
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH))
/* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be
* avoided. Since this isn't called on those targets, the function
......@@ -287,10 +235,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
if (use_fd < 0 || use_fd >= fd)
continue;
pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
if (pipes[fd][1] == -1) {
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if (pipes[fd][1] == -1)
uv__write_errno(error_fd);
}
for (fd = 0; fd < stdio_count; fd++) {
......@@ -307,10 +253,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
close_fd = use_fd;
if (use_fd < 0) {
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if (use_fd < 0)
uv__write_errno(error_fd);
}
}
......@@ -319,10 +263,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
else
fd = dup2(use_fd, fd);
if (fd == -1) {
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if (fd == -1)
uv__write_errno(error_fd);
if (fd <= 2)
uv__nonblock_fcntl(fd, 0);
......@@ -338,10 +280,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
uv__close(use_fd);
}
if (options->cwd != NULL && chdir(options->cwd)) {
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if (options->cwd != NULL && chdir(options->cwd))
uv__write_errno(error_fd);
if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
/* When dropping privileges from root, the `setgroups` call will
......@@ -354,15 +294,11 @@ static void uv__process_child_init(const uv_process_options_t* options,
SAVE_ERRNO(setgroups(0, NULL));
}
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid))
uv__write_errno(error_fd);
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid))
uv__write_errno(error_fd);
if (options->env != NULL) {
environ = options->env;
......@@ -385,22 +321,23 @@ static void uv__process_child_init(const uv_process_options_t* options,
if (SIG_ERR != signal(n, SIG_DFL))
continue;
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
uv__write_errno(error_fd);
}
/* Reset signal mask. */
sigemptyset(&set);
err = pthread_sigmask(SIG_SETMASK, &set, NULL);
if (err != 0) {
uv__write_int(error_fd, UV__ERR(err));
_exit(127);
}
if (err != 0)
uv__write_errno(error_fd);
#ifdef __MVS__
execvpe(options->file, options->args, environ);
#else
execvp(options->file, options->args);
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
#endif
uv__write_errno(error_fd);
}
#endif
......
......@@ -84,10 +84,7 @@ char** uv_setup_args(int argc, char** argv) {
}
new_argv[i] = NULL;
/* argv is not adjacent on z/os, we use just argv[0] on that platform. */
#ifndef __MVS__
pt.cap = argv[i - 1] + size - argv[0];
#endif
args_mem = new_argv;
process_title = pt;
......@@ -119,6 +116,7 @@ int uv_set_process_title(const char* title) {
memcpy(pt->str, title, len);
memset(pt->str + len, '\0', pt->cap - len);
pt->len = len;
uv__set_process_title(pt->str);
uv_mutex_unlock(&process_title_mutex);
......
......@@ -265,7 +265,7 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) {
if (loop->signal_pipefd[0] != -1)
return 0;
err = uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK);
err = uv__make_pipe(loop->signal_pipefd, UV_NONBLOCK_PIPE);
if (err)
return err;
......
This diff is collapsed.
......@@ -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
......@@ -214,14 +214,15 @@ int uv__tcp_connect(uv_connect_t* req,
if (handle->connect_req != NULL)
return UV_EALREADY; /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
if (handle->delayed_error != 0)
goto out;
err = maybe_new_socket(handle,
addr->sa_family,
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
if (err)
return err;
handle->delayed_error = 0;
do {
errno = 0;
r = connect(uv__stream_fd(handle), addr, addrlen);
......@@ -249,6 +250,8 @@ int uv__tcp_connect(uv_connect_t* req,
return UV__ERR(errno);
}
out:
uv__req_init(handle->loop, req, UV_CONNECT);
req->cb = cb;
req->handle = (uv_stream_t*) handle;
......@@ -459,3 +462,49 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
void uv__tcp_close(uv_tcp_t* handle) {
uv__stream_close((uv_stream_t*)handle);
}
int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {
uv_os_sock_t temp[2];
int err;
#if defined(__FreeBSD__) || defined(__linux__)
int flags;
flags = type | SOCK_CLOEXEC;
if ((flags0 & UV_NONBLOCK_PIPE) && (flags1 & UV_NONBLOCK_PIPE))
flags |= SOCK_NONBLOCK;
if (socketpair(AF_UNIX, flags, protocol, temp))
return UV__ERR(errno);
if (flags & UV_FS_O_NONBLOCK) {
fds[0] = temp[0];
fds[1] = temp[1];
return 0;
}
#else
if (socketpair(AF_UNIX, type, protocol, temp))
return UV__ERR(errno);
if ((err = uv__cloexec(temp[0], 1)))
goto fail;
if ((err = uv__cloexec(temp[1], 1)))
goto fail;
#endif
if (flags0 & UV_NONBLOCK_PIPE)
if ((err = uv__nonblock(temp[0], 1)))
goto fail;
if (flags1 & UV_NONBLOCK_PIPE)
if ((err = uv__nonblock(temp[1], 1)))
goto fail;
fds[0] = temp[0];
fds[1] = temp[1];
return 0;
fail:
uv__close(temp[0]);
uv__close(temp[1]);
return err;
}
......@@ -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. */
......
......@@ -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 */
......
......@@ -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)
......
......@@ -832,6 +832,25 @@ void uv_loop_delete(uv_loop_t* loop) {
}
int uv_read_start(uv_stream_t* stream,
uv_alloc_cb alloc_cb,
uv_read_cb read_cb) {
if (stream == NULL || alloc_cb == NULL || read_cb == NULL)
return UV_EINVAL;
if (stream->flags & UV_HANDLE_CLOSING)
return UV_EINVAL;
if (stream->flags & UV_HANDLE_READING)
return UV_EALREADY;
if (!(stream->flags & UV_HANDLE_READABLE))
return UV_ENOTCONN;
return uv__read_start(stream, alloc_cb, read_cb);
}
void uv_os_free_environ(uv_env_item_t* envitems, int count) {
int i;
......@@ -853,7 +872,11 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
}
#ifdef __GNUC__ /* Also covers __clang__ and __INTEL_COMPILER. */
/* Also covers __clang__ and __INTEL_COMPILER. Disabled on Windows because
* threads have already been forcibly terminated by the operating system
* by the time destructors run, ergo, it's not safe to try to clean them up.
*/
#if defined(__GNUC__) && !defined(_WIN32)
__attribute__((destructor))
#endif
void uv_library_shutdown(void) {
......
......@@ -68,6 +68,8 @@ extern int snprintf(char*, size_t, const char*, ...);
#define uv__store_relaxed(p, v) do *p = v; while (0)
#endif
#define UV__UDP_DGRAM_MAXSIZE (64 * 1024)
/* Handle flags. Some flags are specific to Windows or UNIX. */
enum {
/* Used by all handles. */
......@@ -106,8 +108,7 @@ enum {
UV_HANDLE_TCP_KEEPALIVE = 0x02000000,
UV_HANDLE_TCP_SINGLE_ACCEPT = 0x04000000,
UV_HANDLE_TCP_ACCEPT_STATE_CHANGING = 0x08000000,
UV_HANDLE_TCP_SOCKET_CLOSED = 0x10000000,
UV_HANDLE_SHARED_TCP_SOCKET = 0x20000000,
UV_HANDLE_SHARED_TCP_SOCKET = 0x10000000,
/* Only used by uv_udp_t handles. */
UV_HANDLE_UDP_PROCESSING = 0x01000000,
......@@ -136,6 +137,10 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
void uv__loop_close(uv_loop_t* loop);
int uv__read_start(uv_stream_t* stream,
uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
int uv__tcp_bind(uv_tcp_t* tcp,
const struct sockaddr* addr,
unsigned int addrlen,
......
......@@ -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
......
......@@ -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;
}
}
......@@ -92,30 +92,24 @@
return; \
}
#define MILLIONu (1000U * 1000U)
#define BILLIONu (1000U * 1000U * 1000U)
#define MILLION ((int64_t) 1000 * 1000)
#define BILLION ((int64_t) 1000 * 1000 * 1000)
#define FILETIME_TO_UINT(filetime) \
(*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)
#define FILETIME_TO_TIME_T(filetime) \
(FILETIME_TO_UINT(filetime) / (10u * MILLIONu))
#define FILETIME_TO_TIME_NS(filetime, secs) \
((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)
#define FILETIME_TO_TIMESPEC(ts, filetime) \
do { \
(ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime); \
(ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec); \
} while(0)
static void uv__filetime_to_timespec(uv_timespec_t *ts, int64_t filetime) {
filetime -= 116444736 * BILLION;
ts->tv_sec = (long) (filetime / (10 * MILLION));
ts->tv_nsec = (long) ((filetime - ts->tv_sec * 10 * MILLION) * 100U);
if (ts->tv_nsec < 0) {
ts->tv_sec -= 1;
ts->tv_nsec += 1e9;
}
}
#define TIME_T_TO_FILETIME(time, filetime_ptr) \
do { \
uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) + \
(uint64_t) 116444736 * BILLIONu; \
(filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \
(filetime_ptr)->dwHighDateTime = bigtime >> 32; \
int64_t bigtime = ((time) * 10 * MILLION + 116444736 * BILLION); \
(filetime_ptr)->dwLowDateTime = (uint64_t) bigtime & 0xFFFFFFFF; \
(filetime_ptr)->dwHighDateTime = (uint64_t) bigtime >> 32; \
} while(0)
#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')
......@@ -1224,7 +1218,8 @@ void fs__mkdir(uv_fs_t* req) {
SET_REQ_RESULT(req, 0);
} else {
SET_REQ_WIN32_ERROR(req, GetLastError());
if (req->sys_errno_ == ERROR_INVALID_NAME)
if (req->sys_errno_ == ERROR_INVALID_NAME ||
req->sys_errno_ == ERROR_DIRECTORY)
req->result = UV_EINVAL;
}
}
......@@ -1243,7 +1238,7 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) {
uint64_t v;
char* path;
path = req->path;
path = (char*)req->path;
len = wcslen(req->file.pathw);
ep = req->file.pathw + len;
if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {
......@@ -1791,10 +1786,14 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) |
((_S_IREAD | _S_IWRITE) >> 6);
FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime);
FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime);
FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime);
FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime);
uv__filetime_to_timespec(&statbuf->st_atim,
file_info.BasicInformation.LastAccessTime.QuadPart);
uv__filetime_to_timespec(&statbuf->st_ctim,
file_info.BasicInformation.ChangeTime.QuadPart);
uv__filetime_to_timespec(&statbuf->st_mtim,
file_info.BasicInformation.LastWriteTime.QuadPart);
uv__filetime_to_timespec(&statbuf->st_birthtim,
file_info.BasicInformation.CreationTime.QuadPart);
statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart;
......
......@@ -115,8 +115,8 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
/*
* Pipes
*/
int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
char* name, size_t nameSize);
int uv__create_stdio_pipe_pair(uv_loop_t* loop,
uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags);
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
......
......@@ -202,17 +202,17 @@ static void close_pipe(uv_pipe_t* pipe) {
}
int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
char* name, size_t nameSize) {
static int uv__pipe_server(
HANDLE* pipeHandle_ptr, DWORD access,
char* name, size_t nameSize, char* random) {
HANDLE pipeHandle;
int err;
char* ptr = (char*)handle;
for (;;) {
uv_unique_pipe_name(ptr, name, nameSize);
uv_unique_pipe_name(random, name, nameSize);
pipeHandle = CreateNamedPipeA(name,
access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
access | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0,
NULL);
......@@ -226,26 +226,225 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
goto error;
}
/* Pipe name collision. Increment the pointer and try again. */
ptr++;
/* Pipe name collision. Increment the random number and try again. */
random++;
}
if (CreateIoCompletionPort(pipeHandle,
*pipeHandle_ptr = pipeHandle;
return 0;
error:
if (pipeHandle != INVALID_HANDLE_VALUE)
CloseHandle(pipeHandle);
return err;
}
static int uv__create_pipe_pair(
HANDLE* server_pipe_ptr, HANDLE* client_pipe_ptr,
unsigned int server_flags, unsigned int client_flags,
int inherit_client, char* random) {
/* allowed flags are: UV_READABLE_PIPE | UV_WRITABLE_PIPE | UV_NONBLOCK_PIPE */
char pipe_name[64];
SECURITY_ATTRIBUTES sa;
DWORD server_access;
DWORD client_access;
HANDLE server_pipe;
HANDLE client_pipe;
int err;
server_pipe = INVALID_HANDLE_VALUE;
client_pipe = INVALID_HANDLE_VALUE;
server_access = 0;
if (server_flags & UV_READABLE_PIPE)
server_access |= PIPE_ACCESS_INBOUND;
if (server_flags & UV_WRITABLE_PIPE)
server_access |= PIPE_ACCESS_OUTBOUND;
if (server_flags & UV_NONBLOCK_PIPE)
server_access |= FILE_FLAG_OVERLAPPED;
server_access |= WRITE_DAC;
client_access = 0;
if (client_flags & UV_READABLE_PIPE)
client_access |= GENERIC_READ;
else
client_access |= FILE_READ_ATTRIBUTES;
if (client_flags & UV_WRITABLE_PIPE)
client_access |= GENERIC_WRITE;
else
client_access |= FILE_WRITE_ATTRIBUTES;
client_access |= WRITE_DAC;
/* Create server pipe handle. */
err = uv__pipe_server(&server_pipe,
server_access,
pipe_name,
sizeof(pipe_name),
random);
if (err)
goto error;
/* Create client pipe handle. */
sa.nLength = sizeof sa;
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = inherit_client;
client_pipe = CreateFileA(pipe_name,
client_access,
0,
&sa,
OPEN_EXISTING,
(client_flags & UV_NONBLOCK_PIPE) ? FILE_FLAG_OVERLAPPED : 0,
NULL);
if (client_pipe == INVALID_HANDLE_VALUE) {
err = GetLastError();
goto error;
}
#ifndef NDEBUG
/* Validate that the pipe was opened in the right mode. */
{
DWORD mode;
BOOL r;
r = GetNamedPipeHandleState(client_pipe, &mode, NULL, NULL, NULL, NULL, 0);
if (r == TRUE) {
assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
} else {
fprintf(stderr, "libuv assertion failure: GetNamedPipeHandleState failed\n");
}
}
#endif
/* Do a blocking ConnectNamedPipe. This should not block because we have
* both ends of the pipe created. */
if (!ConnectNamedPipe(server_pipe, NULL)) {
if (GetLastError() != ERROR_PIPE_CONNECTED) {
err = GetLastError();
goto error;
}
}
*client_pipe_ptr = client_pipe;
*server_pipe_ptr = server_pipe;
return 0;
error:
if (server_pipe != INVALID_HANDLE_VALUE)
CloseHandle(server_pipe);
if (client_pipe != INVALID_HANDLE_VALUE)
CloseHandle(client_pipe);
return err;
}
int uv_pipe(uv_file fds[2], int read_flags, int write_flags) {
uv_file temp[2];
int err;
HANDLE readh;
HANDLE writeh;
/* Make the server side the inbound (read) end, */
/* so that both ends will have FILE_READ_ATTRIBUTES permission. */
/* TODO: better source of local randomness than &fds? */
read_flags |= UV_READABLE_PIPE;
write_flags |= UV_WRITABLE_PIPE;
err = uv__create_pipe_pair(&readh, &writeh, read_flags, write_flags, 0, (char*) &fds[0]);
if (err != 0)
return err;
temp[0] = _open_osfhandle((intptr_t) readh, 0);
if (temp[0] == -1) {
if (errno == UV_EMFILE)
err = UV_EMFILE;
else
err = UV_UNKNOWN;
CloseHandle(readh);
CloseHandle(writeh);
return err;
}
temp[1] = _open_osfhandle((intptr_t) writeh, 0);
if (temp[1] == -1) {
if (errno == UV_EMFILE)
err = UV_EMFILE;
else
err = UV_UNKNOWN;
_close(temp[0]);
CloseHandle(writeh);
return err;
}
fds[0] = temp[0];
fds[1] = temp[1];
return 0;
}
int uv__create_stdio_pipe_pair(uv_loop_t* loop,
uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {
/* The parent_pipe is always the server_pipe and kept by libuv.
* The child_pipe is always the client_pipe and is passed to the child.
* The flags are specified with respect to their usage in the child. */
HANDLE server_pipe;
HANDLE client_pipe;
unsigned int server_flags;
unsigned int client_flags;
int err;
server_pipe = INVALID_HANDLE_VALUE;
client_pipe = INVALID_HANDLE_VALUE;
server_flags = 0;
client_flags = 0;
if (flags & UV_READABLE_PIPE) {
/* The server needs inbound (read) access too, otherwise CreateNamedPipe()
* won't give us the FILE_READ_ATTRIBUTES permission. We need that to probe
* the state of the write buffer when we're trying to shutdown the pipe. */
server_flags |= UV_READABLE_PIPE | UV_WRITABLE_PIPE;
client_flags |= UV_READABLE_PIPE;
}
if (flags & UV_WRITABLE_PIPE) {
server_flags |= UV_READABLE_PIPE;
client_flags |= UV_WRITABLE_PIPE;
}
server_flags |= UV_NONBLOCK_PIPE;
if (flags & UV_NONBLOCK_PIPE || parent_pipe->ipc) {
client_flags |= UV_NONBLOCK_PIPE;
}
err = uv__create_pipe_pair(&server_pipe, &client_pipe,
server_flags, client_flags, 1, (char*) server_pipe);
if (err)
goto error;
if (CreateIoCompletionPort(server_pipe,
loop->iocp,
(ULONG_PTR)handle,
(ULONG_PTR) parent_pipe,
0) == NULL) {
err = GetLastError();
goto error;
}
uv_pipe_connection_init(handle);
handle->handle = pipeHandle;
uv_pipe_connection_init(parent_pipe);
parent_pipe->handle = server_pipe;
*child_pipe_ptr = client_pipe;
/* The server end is now readable and/or writable. */
if (flags & UV_READABLE_PIPE)
parent_pipe->flags |= UV_HANDLE_WRITABLE;
if (flags & UV_WRITABLE_PIPE)
parent_pipe->flags |= UV_HANDLE_READABLE;
return 0;
error:
if (pipeHandle != INVALID_HANDLE_VALUE)
CloseHandle(pipeHandle);
if (server_pipe != INVALID_HANDLE_VALUE)
CloseHandle(server_pipe);
if (client_pipe != INVALID_HANDLE_VALUE)
CloseHandle(client_pipe);
return err;
}
......@@ -712,9 +911,8 @@ error:
handle->name = NULL;
}
if (pipeHandle != INVALID_HANDLE_VALUE) {
if (pipeHandle != INVALID_HANDLE_VALUE)
CloseHandle(pipeHandle);
}
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, err);
......
......@@ -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;
......
......@@ -95,102 +95,6 @@ void uv_disable_stdio_inheritance(void) {
}
static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {
char pipe_name[64];
SECURITY_ATTRIBUTES sa;
DWORD server_access = 0;
DWORD client_access = 0;
HANDLE child_pipe = INVALID_HANDLE_VALUE;
int err;
int overlap;
if (flags & UV_READABLE_PIPE) {
/* The server needs inbound access too, otherwise CreateNamedPipe() won't
* give us the FILE_READ_ATTRIBUTES permission. We need that to probe the
* state of the write buffer when we're trying to shutdown the pipe. */
server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
}
if (flags & UV_WRITABLE_PIPE) {
server_access |= PIPE_ACCESS_INBOUND;
client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
}
/* Create server pipe handle. */
err = uv_stdio_pipe_server(loop,
server_pipe,
server_access,
pipe_name,
sizeof(pipe_name));
if (err)
goto error;
/* Create child pipe handle. */
sa.nLength = sizeof sa;
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);
child_pipe = CreateFileA(pipe_name,
client_access,
0,
&sa,
OPEN_EXISTING,
overlap ? FILE_FLAG_OVERLAPPED : 0,
NULL);
if (child_pipe == INVALID_HANDLE_VALUE) {
err = GetLastError();
goto error;
}
#ifndef NDEBUG
/* Validate that the pipe was opened in the right mode. */
{
DWORD mode;
BOOL r = GetNamedPipeHandleState(child_pipe,
&mode,
NULL,
NULL,
NULL,
NULL,
0);
assert(r == TRUE);
assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
}
#endif
/* Do a blocking ConnectNamedPipe. This should not block because we have both
* ends of the pipe created. */
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
if (GetLastError() != ERROR_PIPE_CONNECTED) {
err = GetLastError();
goto error;
}
}
/* The server end is now readable and/or writable. */
if (flags & UV_READABLE_PIPE)
server_pipe->flags |= UV_HANDLE_WRITABLE;
if (flags & UV_WRITABLE_PIPE)
server_pipe->flags |= UV_HANDLE_READABLE;
*child_pipe_ptr = child_pipe;
return 0;
error:
if (server_pipe->handle != INVALID_HANDLE_VALUE) {
uv_pipe_cleanup(loop, server_pipe);
}
if (child_pipe != INVALID_HANDLE_VALUE) {
CloseHandle(child_pipe);
}
return err;
}
static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
HANDLE current_process;
......
......@@ -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) {
......
......@@ -65,18 +65,11 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
}
int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb) {
int uv__read_start(uv_stream_t* handle,
uv_alloc_cb alloc_cb,
uv_read_cb read_cb) {
int err;
if (handle->flags & UV_HANDLE_READING) {
return UV_EALREADY;
}
if (!(handle->flags & UV_HANDLE_READABLE)) {
return UV_ENOTCONN;
}
err = ERROR_INVALID_PARAMETER;
switch (handle->type) {
case UV_TCP:
......@@ -195,6 +188,16 @@ int uv_try_write(uv_stream_t* stream,
}
int uv_try_write2(uv_stream_t* stream,
const uv_buf_t bufs[],
unsigned int nbufs,
uv_stream_t* send_handle) {
if (send_handle != NULL)
return UV_EAGAIN;
return uv_try_write(stream, bufs, nbufs);
}
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
uv_loop_t* loop = handle->loop;
......
This diff is collapsed.
......@@ -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;
......
......@@ -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;
}
......
Upgrade bundled libuv to 1.42.0 from 1.40.0.
......@@ -151,6 +151,7 @@ else:
_libuv_source('unix/thread.c'),
_libuv_source('unix/tty.c'),
_libuv_source('unix/udp.c'),
_libuv_source('unix/epoll.c'),
]
......@@ -263,6 +264,7 @@ elif sys.platform.startswith('netbsd'): # pragma: no cover
elif sys.platform.startswith('sunos'): # pragma: no cover
_define_macro('__EXTENSIONS__', 1)
_define_macro('_XOPEN_SOURCE', 500)
_define_macro('_REENTRANT', 1)
_add_library('kstat')
_add_library('nsl')
_add_library('sendfile')
......@@ -290,7 +292,7 @@ elif WIN:
_define_macro('_CRT_SECURE_NO_DEPRECATE', 1)
_define_macro('_CRT_NONSTDC_NO_DEPRECATE', 1)
_define_macro('_CRT_SECURE_NO_WARNINGS', 1)
_define_macro('_WIN32_WINNT', '0x0600')
_define_macro('_WIN32_WINNT', '0x0602')
_define_macro('WIN32_LEAN_AND_MEAN', 1)
_add_library('advapi32')
_add_library('iphlpapi')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment