libuv 1.43.0

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3735 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2022-01-05 02:04:05 +00:00
parent c02a3d3659
commit e2c25ab414
60 changed files with 1048 additions and 608 deletions

View File

@ -1,9 +1,9 @@
# Number of days of inactivity before an issue becomes stale # Number of days of inactivity before an issue becomes stale
daysUntilStale: 21 daysUntilStale: 28
# Number of days of inactivity before a stale issue is closed # Number of days of inactivity before a stale issue is closed
# Set to false to disable. If disabled, issues still need to be closed # Set to false to disable. If disabled, issues still need to be closed
# manually, but will remain marked as stale. # manually, but will remain marked as stale.
daysUntilClose: 120 daysUntilClose: false
# Issues with these labels will never be considered stale # Issues with these labels will never be considered stale
exemptLabels: exemptLabels:
- v2 - v2
@ -18,7 +18,6 @@ staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable # Comment to post when marking an issue as stale. Set to `false` to disable
markComment: > markComment: >
This issue has been automatically marked as stale because it has not had This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you recent activity. Thank you for your contributions.
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable # Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false closeComment: false

View File

@ -3,6 +3,36 @@ name: CI
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build-windows:
runs-on: windows-${{ matrix.config.server }}
name: build-${{ matrix.config.toolchain}}-${{ matrix.config.arch}}
strategy:
fail-fast: false
matrix:
config:
- {toolchain: Visual Studio 15 2017, arch: Win32, server: 2016}
- {toolchain: Visual Studio 15 2017, arch: x64, server: 2016}
- {toolchain: Visual Studio 16 2019, arch: Win32, server: 2019}
- {toolchain: Visual Studio 16 2019, arch: x64, server: 2019}
- {toolchain: Visual Studio 17 2022, arch: Win32, server: 2022}
- {toolchain: Visual Studio 17 2022, arch: x64, server: 2022}
steps:
- uses: actions/checkout@v2
- name: Envinfo
run: npx envinfo
- name: Build
shell: cmd
run: |
mkdir -p build
cd build
cmake .. -DBUILD_TESTING=ON -G "${{ matrix.config.toolchain }}" -A ${{ matrix.config.arch }}
cmake --build .
- name: Test
shell: cmd
run: |
cd build
ctest -C Debug --output-on-failure
build-android: build-android:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: reactnativecommunity/react-native-android:2020-5-20 container: reactnativecommunity/react-native-android:2020-5-20
@ -17,6 +47,25 @@ jobs:
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/20.0.5594570/build/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-21 .. $ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/20.0.5594570/build/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-21 ..
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake --build . $ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake --build .
build-macos:
runs-on: macos-10.15
steps:
- uses: actions/checkout@v2
- name: Envinfo
run: npx envinfo
- name: Setup
run: |
brew install ninja
- name: Build
run: |
mkdir build
cd build && cmake .. -DBUILD_TESTING=ON -G Ninja
cmake --build .
ls -lh
- name: Test
run: |
cd build && ctest -V
build-cross-qemu: build-cross-qemu:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: build-cross-qemu-${{ matrix.config.target }} name: build-cross-qemu-${{ matrix.config.target }}

View File

@ -3,15 +3,24 @@ name: Sanitizer checks
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
asan: sanitizers:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Setup
run: |
sudo apt-get install ninja-build
- name: Envinfo - name: Envinfo
run: npx envinfo run: npx envinfo
- name: TSAN
run: |
mkdir build-tsan
(cd build-tsan && cmake .. -G Ninja -DBUILD_TESTING=ON -DTSAN=ON -DCMAKE_BUILD_TYPE=Release)
cmake --build build-tsan
./build-tsan/uv_run_tests_a || true # currently permit failures
- name: ASAN - name: ASAN
run: | run: |
mkdir build mkdir build-asan
cd build && cmake .. -DBUILD_TESTING=ON -DASAN=ON -DCMAKE_BUILD_TYPE=Debug (cd build-asan && cmake .. -G Ninja -DBUILD_TESTING=ON -DASAN=ON -DCMAKE_BUILD_TYPE=Debug)
cmake --build . && ./uv_run_tests_a cmake --build build-asan
./build-asan/uv_run_tests_a

4
deps/libuv/.mailmap vendored
View File

@ -1,4 +1,5 @@
A. Hauptmann <andreashauptmann@t-online.de> A. Hauptmann <andreashauptmann@t-online.de>
AJ Heller <aj@drfloob.com> <hork@google.com>
Aaron Bieber <qbit@deftly.net> <deftly@gmail.com> Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com> Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com> Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
@ -12,6 +13,7 @@ Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr> Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr>
Christoph Iserlohn <christoph.iserlohn@innoq.com> Christoph Iserlohn <christoph.iserlohn@innoq.com>
Darshan Sen <raisinten@gmail.com> Darshan Sen <raisinten@gmail.com>
Darshan Sen <raisinten@gmail.com> <darshan.sen@postman.com>
David Carlier <devnexen@gmail.com> David Carlier <devnexen@gmail.com>
Devchandra Meetei Leishangthem <dlmeetei@gmail.com> Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com> Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
@ -21,6 +23,7 @@ Isaac Z. Schlueter <i@izs.me>
Jason Williams <necmon@yahoo.com> Jason Williams <necmon@yahoo.com>
Jesse Gorzinski <jgorzinski@gmail.com> Jesse Gorzinski <jgorzinski@gmail.com>
Jesse Gorzinski <jgorzinski@gmail.com> <jgorzins@us.ibm.com> Jesse Gorzinski <jgorzinski@gmail.com> <jgorzins@us.ibm.com>
Juan José Arboleda <soyjuanarbol@gmail.com>
Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com> Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com>
Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu> Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu> Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
@ -46,6 +49,7 @@ Santiago Gimeno <santiago.gimeno@quantion.es> <santiago.gimeno@gmail.com>
Saúl Ibarra Corretgé <saghul@gmail.com> Saúl Ibarra Corretgé <saghul@gmail.com>
Saúl Ibarra Corretgé <saghul@gmail.com> <s@saghul.net> Saúl Ibarra Corretgé <saghul@gmail.com> <s@saghul.net>
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org> Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
Shuowang (Wayne) Zhang <shuowang.zhang@ibm.com>
TK-one <tk5641@naver.com> TK-one <tk5641@naver.com>
Timothy J. Fontaine <tjfontaine@gmail.com> Timothy J. Fontaine <tjfontaine@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com> Yasuhiro Matsumoto <mattn.jp@gmail.com>

17
deps/libuv/AUTHORS vendored
View File

@ -479,3 +479,20 @@ Joshua M. Clulow <josh@sysmgr.org>
Guilherme Íscaro <cabelitostos@gmail.com> Guilherme Íscaro <cabelitostos@gmail.com>
Martin Storsjö <martin@martin.st> Martin Storsjö <martin@martin.st>
Claes Nästén <pekdon@gmail.com> Claes Nästén <pekdon@gmail.com>
Mohamed Edrah <43171151+MSE99@users.noreply.github.com>
Supragya Raj <supragyaraj@gmail.com>
Ikko Ashimine <eltociear@gmail.com>
Sylvain Corlay <sylvain.corlay@gmail.com>
earnal <etienne.arnal@gmail.com>
YAKSH BARIYA <yakshbari4@gmail.com>
Ofek Lev <ofekmeister@gmail.com>
~locpyl-tidnyd <81016946+locpyl-tidnyd@users.noreply.github.com>
Evan Miller <emmiller@gmail.com>
Petr Menšík <pemensik@redhat.com>
Nicolas Noble <nicolasnoble@users.noreply.github.com>
AJ Heller <aj@drfloob.com>
Stacey Marshall <stacey.marshall@gmail.com>
Jesper Storm Bache <jsbache@users.noreply.github.com>
Campbell He <duskmoon314@users.noreply.github.com>
Andrey Hohutkin <andrey.hohutkin@gmail.com>
deal <halx99@live.com>

View File

@ -31,13 +31,26 @@ if(QEMU)
endif() endif()
option(ASAN "Enable AddressSanitizer (ASan)" OFF) option(ASAN "Enable AddressSanitizer (ASan)" OFF)
if(ASAN AND CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang") option(TSAN "Enable ThreadSanitizer (TSan)" OFF)
if((ASAN OR TSAN) AND NOT (CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang"))
message(SEND_ERROR "Sanitizer support requires clang or gcc. Try again with -DCMAKE_C_COMPILER.")
endif()
if(ASAN)
add_definitions(-D__ASAN__=1) add_definitions(-D__ASAN__=1)
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -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_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
endif() endif()
if(TSAN)
add_definitions(-D__TSAN__=1)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
endif()
# Compiler check # Compiler check
string(CONCAT is-msvc $<OR: string(CONCAT is-msvc $<OR:
$<C_COMPILER_ID:MSVC>, $<C_COMPILER_ID:MSVC>,
@ -418,7 +431,6 @@ if(LIBUV_BUILD_TESTS)
test/benchmark-thread.c test/benchmark-thread.c
test/benchmark-udp-pummel.c test/benchmark-udp-pummel.c
test/blackhole-server.c test/blackhole-server.c
test/dns-server.c
test/echo-server.c test/echo-server.c
test/run-benchmarks.c test/run-benchmarks.c
test/runner.c) test/runner.c)
@ -477,6 +489,7 @@ if(LIBUV_BUILD_TESTS)
test/test-idna.c test/test-idna.c
test/test-ip4-addr.c test/test-ip4-addr.c
test/test-ip6-addr.c test/test-ip6-addr.c
test/test-ip-name.c
test/test-ipc-heavy-traffic-deadlock-bug.c test/test-ipc-heavy-traffic-deadlock-bug.c
test/test-ipc-send-recv.c test/test-ipc-send-recv.c
test/test-ipc.c test/test-ipc.c
@ -490,7 +503,6 @@ if(LIBUV_BUILD_TESTS)
test/test-multiple-listen.c test/test-multiple-listen.c
test/test-mutexes.c test/test-mutexes.c
test/test-not-readable-nor-writable-on-read-error.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-not-writable-after-shutdown.c
test/test-osx-select.c test/test-osx-select.c
test/test-pass-always.c test/test-pass-always.c
@ -518,6 +530,7 @@ if(LIBUV_BUILD_TESTS)
test/test-process-title.c test/test-process-title.c
test/test-queue-foreach-delete.c test/test-queue-foreach-delete.c
test/test-random.c test/test-random.c
test/test-readable-on-eof.c
test/test-ref.c test/test-ref.c
test/test-run-nowait.c test/test-run-nowait.c
test/test-run-once.c test/test-run-once.c
@ -574,6 +587,7 @@ if(LIBUV_BUILD_TESTS)
test/test-udp-alloc-cb-fail.c test/test-udp-alloc-cb-fail.c
test/test-udp-bind.c test/test-udp-bind.c
test/test-udp-connect.c test/test-udp-connect.c
test/test-udp-connect6.c
test/test-udp-create-socket-early.c test/test-udp-create-socket-early.c
test/test-udp-dgram-too-big.c test/test-udp-dgram-too-big.c
test/test-udp-ipv6.c test/test-udp-ipv6.c
@ -625,46 +639,43 @@ if(LIBUV_BUILD_TESTS)
endif() endif()
endif() endif()
if(UNIX OR MINGW) # Now for some gibbering horrors from beyond the stars...
# Now for some gibbering horrors from beyond the stars... foreach(lib IN LISTS uv_libraries)
foreach(lib IN LISTS uv_libraries) list(APPEND LIBS "-l${lib}")
list(APPEND LIBS "-l${lib}") endforeach()
endforeach() string(REPLACE ";" " " LIBS "${LIBS}")
string(REPLACE ";" " " LIBS "${LIBS}") # Consider setting project version via project() call?
# Consider setting project version via project() call? file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
file(STRINGS configure.ac configure_ac REGEX ^AC_INIT) string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}")
string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}") set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}") # The version in the filename is mirroring the behaviour of autotools.
# The version in the filename is mirroring the behaviour of autotools. set_target_properties(uv PROPERTIES
set_target_properties(uv PROPERTIES VERSION ${UV_VERSION_MAJOR}.0.0
VERSION ${UV_VERSION_MAJOR}.0.0 SOVERSION ${UV_VERSION_MAJOR})
SOVERSION ${UV_VERSION_MAJOR}) set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) set(prefix ${CMAKE_INSTALL_PREFIX})
set(prefix ${CMAKE_INSTALL_PREFIX}) configure_file(libuv.pc.in libuv.pc @ONLY)
configure_file(libuv.pc.in libuv.pc @ONLY) configure_file(libuv-static.pc.in libuv-static.pc @ONLY)
configure_file(libuv-static.pc.in libuv-static.pc @ONLY)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
install(FILES ${PROJECT_BINARY_DIR}/libuv.pc ${PROJECT_BINARY_DIR}/libuv-static.pc install(FILES ${PROJECT_BINARY_DIR}/libuv.pc ${PROJECT_BINARY_DIR}/libuv-static.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(TARGETS uv EXPORT libuvConfig
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
endif() LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(EXPORT libuvConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libuv)
if(MSVC) if(MSVC)
install(DIRECTORY include/ DESTINATION include) set(CMAKE_DEBUG_POSTFIX d)
install(FILES LICENSE DESTINATION .)
install(TARGETS uv uv_a
RUNTIME DESTINATION lib/$<CONFIG>
ARCHIVE DESTINATION lib/$<CONFIG>)
endif() endif()
message(STATUS "summary of build options: message(STATUS "summary of build options:
Install prefix: ${CMAKE_INSTALL_PREFIX} Install prefix: ${CMAKE_INSTALL_PREFIX}
Target system: ${CMAKE_SYSTEM_NAME} Target system: ${CMAKE_SYSTEM_NAME}
Compiler: Compiler:
C compiler: ${CMAKE_C_COMPILER} C compiler: ${CMAKE_C_COMPILER} (${CMAKE_C_COMPILER_ID})
CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS} CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
") ")

91
deps/libuv/ChangeLog vendored
View File

@ -1,4 +1,93 @@
2021.07.21, Version 1.42.0 (Stable) 2022.01.05, Version 1.43.0 (Stable)
Changes since version 1.42.0:
* run test named ip6_sin6_len (Jameson Nash)
* docs: fix wrong information about scheduling (Mohamed Edrah)
* unix: protect fork in uv_spawn from signals (Jameson Nash)
* drop only successfully sent packets post sendmmsg (Supragya Raj)
* test: fix typo in test-tty-escape-sequence-processing.c (Ikko Ashimine)
* cmake: use standard installation layout always (Sylvain Corlay)
* win,spawn: allow UNC path with forward slash (earnal)
* win,fsevent: fix uv_fs_event_stop() assert (Ben Noordhuis)
* unix: remove redundant include in unix.h (
* doc: mark SmartOS as Tier 3 support (
* doc: fix broken links for netbsd's sysctl manpage (
* misc: adjust stalebot deadline (
* test: remove `dns-server.c` as it is not used anywhere (
* build: fix non-cmake android builds (
* doc: replace pyuv with uvloop (
* asan: fix some tests (
* build: add experimental TSAN configuration (
* pipe: remove useless assertion (
* bsd: destroy mutex in uv__process_title_cleanup() (
* build: add windows build to CI (
* win,fs: fix error code in uv_fs_read() and uv_fs_write() ( Sen)
* build: add macos-latest to ci matrix (
* udp: fix &/&& typo in macro condition (
* build: install cmake package module (Petr Menšík)
* win: fix build for mingw32 (
* build: fix build failures with MinGW new headers (erw7)
* build: fix win build with cmake versions before v3.14 (
* unix: support aarch64 in uv_cpu_info() (
* linux: work around CIFS EPERM bug (
* sunos: Oracle Developer Studio support (
* Revert "sunos: Oracle Developer Studio support (
* sunos: Oracle Developer Studio support (
* stream: permit read after seeing EOF (
* thread: initialize uv_thread_self for all threads (
* kqueue: ignore write-end closed notifications (
* macos: fix the cfdata length in uv__get_cpu_speed ( Bache)
* unix,win: add uv_ip_name to get name from sockaddr (
* win,test: fix a few typos (AJ Heller)
* zos: use destructor for uv__threadpool_cleanup() ( Zhang)
* linux: use MemAvailable instead of MemFree (
* freebsd: call dlerror() only if necessary (
* bsd,windows,zos: fix udp disconnect EINVAL (
2021.07.21, Version 1.42.0 (Stable), 6ce14710da7079eb248868171f6343bc409ea3a4
Changes since version 1.41.0: Changes since version 1.41.0:

View File

@ -141,7 +141,6 @@ endif
test_run_tests_LDFLAGS = test_run_tests_LDFLAGS =
test_run_tests_SOURCES = test/blackhole-server.c \ test_run_tests_SOURCES = test/blackhole-server.c \
test/dns-server.c \
test/echo-server.c \ test/echo-server.c \
test/run-tests.c \ test/run-tests.c \
test/runner.c \ test/runner.c \
@ -193,6 +192,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-idna.c \ test/test-idna.c \
test/test-ip4-addr.c \ test/test-ip4-addr.c \
test/test-ip6-addr.c \ test/test-ip6-addr.c \
test/test-ip-name.c \
test/test-ipc-heavy-traffic-deadlock-bug.c \ test/test-ipc-heavy-traffic-deadlock-bug.c \
test/test-ipc-send-recv.c \ test/test-ipc-send-recv.c \
test/test-ipc.c \ test/test-ipc.c \
@ -207,7 +207,6 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-multiple-listen.c \ test/test-multiple-listen.c \
test/test-mutexes.c \ test/test-mutexes.c \
test/test-not-readable-nor-writable-on-read-error.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-not-writable-after-shutdown.c \
test/test-osx-select.c \ test/test-osx-select.c \
test/test-pass-always.c \ test/test-pass-always.c \
@ -235,6 +234,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-process-title-threadsafe.c \ test/test-process-title-threadsafe.c \
test/test-queue-foreach-delete.c \ test/test-queue-foreach-delete.c \
test/test-random.c \ test/test-random.c \
test/test-readable-on-eof.c \
test/test-ref.c \ test/test-ref.c \
test/test-run-nowait.c \ test/test-run-nowait.c \
test/test-run-once.c \ test/test-run-once.c \
@ -291,6 +291,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-udp-alloc-cb-fail.c \ test/test-udp-alloc-cb-fail.c \
test/test-udp-bind.c \ test/test-udp-bind.c \
test/test-udp-connect.c \ test/test-udp-connect.c \
test/test-udp-connect6.c \
test/test-udp-create-socket-early.c \ test/test-udp-create-socket-early.c \
test/test-udp-dgram-too-big.c \ test/test-udp-dgram-too-big.c \
test/test-udp-ipv6.c \ test/test-udp-ipv6.c \
@ -390,10 +391,7 @@ if ANDROID
uvinclude_HEADERS += include/uv/android-ifaddrs.h uvinclude_HEADERS += include/uv/android-ifaddrs.h
libuv_la_CFLAGS += -D_GNU_SOURCE libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/android-ifaddrs.c \ libuv_la_SOURCES += src/unix/android-ifaddrs.c \
src/unix/pthread-fixes.c \ src/unix/pthread-fixes.c
src/unix/random-getrandom.c \
src/unix/random-sysctl-linux.c \
src/unix/epoll.c
endif endif
if CYGWIN if CYGWIN

View File

@ -5,7 +5,7 @@
libuv is a multi-platform support library with a focus on asynchronous I/O. It 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 was primarily developed for use by [Node.js][], but it's also
used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/), used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/),
[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/blob/v1.x/LINKS.md). [uvloop](https://github.com/MagicStack/uvloop), and [others](https://github.com/libuv/libuv/blob/v1.x/LINKS.md).
## Feature highlights ## Feature highlights

View File

@ -10,7 +10,7 @@
| IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi | | IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos | | z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos |
| Linux with musl | Tier 2 | musl >= 1.0 | | | Linux with musl | Tier 2 | musl >= 1.0 | |
| SmartOS | Tier 2 | >= 14.4 | Maintainers: @libuv/smartos | | SmartOS | Tier 3 | >= 14.4 | |
| Android | Tier 3 | NDK >= r15b | | | Android | Tier 3 | NDK >= r15b | |
| MinGW | Tier 3 | MinGW32 and MinGW-w64 | | | MinGW | Tier 3 | MinGW32 and MinGW-w64 | |
| SunOS | Tier 3 | Solaris 121 and later | | | SunOS | Tier 3 | Solaris 121 and later | |

View File

@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57) AC_PREREQ(2.57)
AC_INIT([libuv], [1.42.0], [https://github.com/libuv/libuv/issues]) AC_INIT([libuv], [1.43.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4]) m4_include([m4/as_case.m4])

View File

@ -42,7 +42,7 @@ as other activities and other I/O operations are kept waiting.
One of the standard solutions is to use threads. Each blocking I/O operation is One of the standard solutions is to use threads. Each blocking I/O operation is
started in a separate thread (or in a thread pool). When the blocking function started in a separate thread (or in a thread pool). When the blocking function
gets invoked in the thread, the processor can schedule another thread to run, gets invoked in the thread, the operating system can schedule another thread to run,
which actually needs the CPU. which actually needs the CPU.
The approach followed by libuv uses another style, which is the **asynchronous, The approach followed by libuv uses another style, which is the **asynchronous,

View File

@ -7,7 +7,7 @@ Overview
libuv is a multi-platform support library with a focus on asynchronous I/O. It 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`_, was primarily developed for use by `Node.js`_, but it's also used by `Luvit`_,
`Julia`_, `pyuv`_, and `others`_. `Julia`_, `uvloop`_, and `others`_.
.. note:: .. note::
In case you find errors in this documentation you can help by sending In case you find errors in this documentation you can help by sending
@ -16,7 +16,7 @@ was primarily developed for use by `Node.js`_, but it's also used by `Luvit`_,
.. _Node.js: https://nodejs.org .. _Node.js: https://nodejs.org
.. _Luvit: https://luvit.io .. _Luvit: https://luvit.io
.. _Julia: https://julialang.org .. _Julia: https://julialang.org
.. _pyuv: https://github.com/saghul/pyuv .. _uvloop: https://github.com/MagicStack/uvloop
.. _others: https://github.com/libuv/libuv/blob/v1.x/LINKS.md .. _others: https://github.com/libuv/libuv/blob/v1.x/LINKS.md

View File

@ -377,6 +377,10 @@ API
Convert a binary structure containing an IPv6 address to a string. Convert a binary structure containing an IPv6 address to a string.
.. c:function:: int uv_ip_name(const struct sockaddr *src, char *dst, size_t size)
Convert a binary structure containing an IPv4 address or an IPv6 address to a string.
.. c:function:: int uv_inet_ntop(int af, const void* src, char* dst, size_t size) .. c:function:: int uv_inet_ntop(int af, const void* src, char* dst, size_t size)
.. c:function:: int uv_inet_pton(int af, const char* src, void* dst) .. c:function:: int uv_inet_pton(int af, const char* src, void* dst)
@ -732,7 +736,7 @@ API
:man:`sysctl(2)`. :man:`sysctl(2)`.
- FreeBSD: `getrandom(2) <https://www.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2>_`, - FreeBSD: `getrandom(2) <https://www.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2>_`,
or `/dev/urandom` after reading from `/dev/random` once. or `/dev/urandom` after reading from `/dev/random` once.
- NetBSD: `KERN_ARND` `sysctl(3) <https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+3+NetBSD-current>_` - NetBSD: `KERN_ARND` `sysctl(7) <https://man.netbsd.org/sysctl.7>_`
- macOS, OpenBSD: `getentropy(2) <https://man.openbsd.org/getentropy.2>_` - macOS, OpenBSD: `getentropy(2) <https://man.openbsd.org/getentropy.2>_`
if available, or `/dev/urandom` after reading from `/dev/random` once. if available, or `/dev/urandom` after reading from `/dev/random` once.
- AIX: `/dev/random`. - AIX: `/dev/random`.

View File

@ -45,6 +45,8 @@ extern "C" {
# endif # endif
#elif __GNUC__ >= 4 #elif __GNUC__ >= 4
# define UV_EXTERN __attribute__((visibility("default"))) # define UV_EXTERN __attribute__((visibility("default")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) /* Sun Studio >= 8 */
# define UV_EXTERN __global
#else #else
# define UV_EXTERN /* nothing */ # define UV_EXTERN /* nothing */
#endif #endif
@ -1658,6 +1660,7 @@ UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);
UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size);
UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size); UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size);
UV_EXTERN int uv_ip_name(const struct sockaddr* src, char* dst, size_t size);
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size); UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst); UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);

View File

@ -65,12 +65,10 @@
# include "uv/bsd.h" # include "uv/bsd.h"
#elif defined(__CYGWIN__) || \ #elif defined(__CYGWIN__) || \
defined(__MSYS__) || \ defined(__MSYS__) || \
defined(__HAIKU__) || \
defined(__QNX__) || \
defined(__GNU__) defined(__GNU__)
# include "uv/posix.h" # include "uv/posix.h"
#elif defined(__HAIKU__)
# include "uv/posix.h"
#elif defined(__QNX__)
# include "uv/posix.h"
#endif #endif
#ifndef NI_MAXHOST #ifndef NI_MAXHOST

View File

@ -31,7 +31,7 @@
*/ */
#define UV_VERSION_MAJOR 1 #define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 42 #define UV_VERSION_MINOR 43
#define UV_VERSION_PATCH 0 #define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX "" #define UV_VERSION_SUFFIX ""

View File

@ -45,7 +45,14 @@ typedef struct pollfd {
#endif #endif
#include <mswsock.h> #include <mswsock.h>
// Disable the typedef in mstcpip.h of MinGW.
#define _TCP_INITIAL_RTO_PARAMETERS _TCP_INITIAL_RTO_PARAMETERS__AVOID
#define TCP_INITIAL_RTO_PARAMETERS TCP_INITIAL_RTO_PARAMETERS__AVOID
#define PTCP_INITIAL_RTO_PARAMETERS PTCP_INITIAL_RTO_PARAMETERS__AVOID
#include <ws2tcpip.h> #include <ws2tcpip.h>
#undef _TCP_INITIAL_RTO_PARAMETERS
#undef TCP_INITIAL_RTO_PARAMETERS
#undef PTCP_INITIAL_RTO_PARAMETERS
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>

View File

@ -160,13 +160,20 @@ static void post(QUEUE* q, enum uv__work_kind kind) {
} }
#ifdef __MVS__
/* TODO(itodorov) - zos: revisit when Woz compiler is available. */
__attribute__((destructor))
#endif
void uv__threadpool_cleanup(void) { void uv__threadpool_cleanup(void) {
unsigned int i; unsigned int i;
if (nthreads == 0) if (nthreads == 0)
return; return;
#ifndef __MVS__
/* TODO(gabylb) - zos: revisit when Woz compiler is available. */
post(&exit_message, UV__WORK_CPU); post(&exit_message, UV__WORK_CPU);
#endif
for (i = 0; i < nthreads; i++) for (i = 0; i < nthreads; i++)
if (uv_thread_join(threads + i)) if (uv_thread_join(threads + i))

View File

@ -38,9 +38,7 @@ static void init_process_title_mutex_once(void) {
void uv__process_title_cleanup(void) { void uv__process_title_cleanup(void) {
/* TODO(bnoordhuis) uv_mutex_destroy(&process_title_mutex) uv_mutex_destroy(&process_title_mutex);
* and reset process_title_mutex_once?
*/
} }

View File

@ -280,14 +280,18 @@ static int uv__get_cpu_speed(uint64_t* speed) {
NULL, NULL,
0); 0);
if (freq_ref) { if (freq_ref) {
uint32_t freq; const UInt8* freq_ref_ptr = pCFDataGetBytePtr(freq_ref);
CFIndex len = pCFDataGetLength(freq_ref); CFIndex len = pCFDataGetLength(freq_ref);
CFRange range; if (len == 8)
range.location = 0; memcpy(speed, freq_ref_ptr, 8);
range.length = len; else if (len == 4) {
uint32_t v;
memcpy(&v, freq_ref_ptr, 4);
*speed = v;
} else {
*speed = 0;
}
pCFDataGetBytes(freq_ref, range, (UInt8*)&freq);
*speed = freq;
pCFRelease(freq_ref); pCFRelease(freq_ref);
pCFRelease(data); pCFRelease(data);
break; break;

View File

@ -53,7 +53,7 @@ void uv_dlclose(uv_lib_t* lib) {
int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) { int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
dlerror(); /* Reset error status. */ dlerror(); /* Reset error status. */
*ptr = dlsym(lib->handle, name); *ptr = dlsym(lib->handle, name);
return uv__dlerror(lib); return *ptr ? 0 : uv__dlerror(lib);
} }

View File

@ -946,6 +946,71 @@ static int uv__is_buggy_cephfs(int fd) {
return uv__kernel_version() < /* 4.20.0 */ 0x041400; return uv__kernel_version() < /* 4.20.0 */ 0x041400;
} }
static int uv__is_cifs_or_smb(int fd) {
struct statfs s;
if (-1 == fstatfs(fd, &s))
return 0;
switch ((unsigned) s.f_type) {
case 0x0000517Bu: /* SMB */
case 0xFE534D42u: /* SMB2 */
case 0xFF534D42u: /* CIFS */
return 1;
}
return 0;
}
static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off,
int out_fd, size_t len) {
static int no_copy_file_range_support;
ssize_t r;
if (uv__load_relaxed(&no_copy_file_range_support)) {
errno = ENOSYS;
return -1;
}
r = uv__fs_copy_file_range(in_fd, off, out_fd, NULL, len, 0);
if (r != -1)
return r;
switch (errno) {
case EACCES:
/* Pre-4.20 kernels have a bug where CephFS uses the RADOS
* copy-from command when it shouldn't.
*/
if (uv__is_buggy_cephfs(in_fd))
errno = ENOSYS; /* Use fallback. */
break;
case ENOSYS:
uv__store_relaxed(&no_copy_file_range_support, 1);
break;
case EPERM:
/* It's been reported that CIFS spuriously fails.
* Consider it a transient error.
*/
if (uv__is_cifs_or_smb(out_fd))
errno = ENOSYS; /* Use fallback. */
break;
case ENOTSUP:
case 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 = ENOSYS; /* Use fallback. */
break;
}
return -1;
}
#endif /* __linux__ */ #endif /* __linux__ */
@ -960,40 +1025,21 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
{ {
off_t off; off_t off;
ssize_t r; ssize_t r;
size_t len;
int try_sendfile;
off = req->off; off = req->off;
len = req->bufsml[0].len;
try_sendfile = 1;
#ifdef __linux__ #ifdef __linux__
{ r = uv__fs_try_copy_file_range(in_fd, &off, out_fd, len);
static int no_copy_file_range_support; try_sendfile = (r == -1 && errno == ENOSYS);
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;
} else {
goto ok;
}
}
}
#endif #endif
r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len); if (try_sendfile)
r = sendfile(out_fd, in_fd, &off, len);
ok:
/* sendfile() on SunOS returns EINVAL if the target fd is not a socket but /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
* it still writes out data. Fortunately, we can detect it by checking if * it still writes out data. Fortunately, we can detect it by checking if
* the offset has been updated. * the offset has been updated.
@ -1277,22 +1323,15 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
if (fchmod(dstfd, src_statsbuf.st_mode) == -1) { if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
err = UV__ERR(errno); err = UV__ERR(errno);
#ifdef __linux__ #ifdef __linux__
/* fchmod() on CIFS shares always fails with EPERM unless the share is
* mounted with "noperm". As fchmod() is a meaningless operation on such
* shares anyway, detect that condition and squelch the error.
*/
if (err != UV_EPERM) if (err != UV_EPERM)
goto out; goto out;
{ if (!uv__is_cifs_or_smb(dstfd))
struct statfs s; goto out;
/* fchmod() on CIFS shares always fails with EPERM unless the share is
* mounted with "noperm". As fchmod() is a meaningless operation on such
* shares anyway, detect that condition and squelch the error.
*/
if (fstatfs(dstfd, &s) == -1)
goto out;
if ((unsigned) s.f_type != /* CIFS */ 0xFF534D42u)
goto out;
}
err = 0; err = 0;
#else /* !__linux__ */ #else /* !__linux__ */

View File

@ -326,6 +326,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (errno != ENOENT) if (errno != ENOENT)
abort(); abort();
} }
if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP))
revents |= UV__POLLRDHUP;
} }
if (ev->filter == EV_OOBAND) { if (ev->filter == EV_OOBAND) {
@ -359,9 +361,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (ev->flags & EV_ERROR) if (ev->flags & EV_ERROR)
revents |= POLLERR; revents |= POLLERR;
if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP))
revents |= UV__POLLRDHUP;
if (revents == 0) if (revents == 0)
continue; continue;

View File

@ -365,24 +365,30 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
const char* inferred_model; const char* inferred_model;
unsigned int model_idx; unsigned int model_idx;
unsigned int speed_idx; unsigned int speed_idx;
unsigned int part_idx;
char buf[1024]; char buf[1024];
char* model; char* model;
FILE* fp; FILE* fp;
int model_id;
/* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */ /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */
(void) &model_marker; (void) &model_marker;
(void) &speed_marker; (void) &speed_marker;
(void) &speed_idx; (void) &speed_idx;
(void) &part_idx;
(void) &model; (void) &model;
(void) &buf; (void) &buf;
(void) &fp; (void) &fp;
(void) &model_id;
model_idx = 0; model_idx = 0;
speed_idx = 0; speed_idx = 0;
part_idx = 0;
#if defined(__arm__) || \ #if defined(__arm__) || \
defined(__i386__) || \ defined(__i386__) || \
defined(__mips__) || \ defined(__mips__) || \
defined(__aarch64__) || \
defined(__PPC__) || \ defined(__PPC__) || \
defined(__x86_64__) defined(__x86_64__)
fp = uv__open_file("/proc/cpuinfo"); fp = uv__open_file("/proc/cpuinfo");
@ -402,11 +408,96 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
continue; continue;
} }
} }
#if defined(__arm__) || defined(__mips__) #if defined(__arm__) || defined(__mips__) || defined(__aarch64__)
if (model_idx < numcpus) { if (model_idx < numcpus) {
#if defined(__arm__) #if defined(__arm__)
/* Fallback for pre-3.8 kernels. */ /* Fallback for pre-3.8 kernels. */
static const char model_marker[] = "Processor\t: "; static const char model_marker[] = "Processor\t: ";
#elif defined(__aarch64__)
static const char part_marker[] = "CPU part\t: ";
/* Adapted from: https://github.com/karelzak/util-linux */
struct vendor_part {
const int id;
const char* name;
};
static const struct vendor_part arm_chips[] = {
{ 0x811, "ARM810" },
{ 0x920, "ARM920" },
{ 0x922, "ARM922" },
{ 0x926, "ARM926" },
{ 0x940, "ARM940" },
{ 0x946, "ARM946" },
{ 0x966, "ARM966" },
{ 0xa20, "ARM1020" },
{ 0xa22, "ARM1022" },
{ 0xa26, "ARM1026" },
{ 0xb02, "ARM11 MPCore" },
{ 0xb36, "ARM1136" },
{ 0xb56, "ARM1156" },
{ 0xb76, "ARM1176" },
{ 0xc05, "Cortex-A5" },
{ 0xc07, "Cortex-A7" },
{ 0xc08, "Cortex-A8" },
{ 0xc09, "Cortex-A9" },
{ 0xc0d, "Cortex-A17" }, /* Originally A12 */
{ 0xc0f, "Cortex-A15" },
{ 0xc0e, "Cortex-A17" },
{ 0xc14, "Cortex-R4" },
{ 0xc15, "Cortex-R5" },
{ 0xc17, "Cortex-R7" },
{ 0xc18, "Cortex-R8" },
{ 0xc20, "Cortex-M0" },
{ 0xc21, "Cortex-M1" },
{ 0xc23, "Cortex-M3" },
{ 0xc24, "Cortex-M4" },
{ 0xc27, "Cortex-M7" },
{ 0xc60, "Cortex-M0+" },
{ 0xd01, "Cortex-A32" },
{ 0xd03, "Cortex-A53" },
{ 0xd04, "Cortex-A35" },
{ 0xd05, "Cortex-A55" },
{ 0xd06, "Cortex-A65" },
{ 0xd07, "Cortex-A57" },
{ 0xd08, "Cortex-A72" },
{ 0xd09, "Cortex-A73" },
{ 0xd0a, "Cortex-A75" },
{ 0xd0b, "Cortex-A76" },
{ 0xd0c, "Neoverse-N1" },
{ 0xd0d, "Cortex-A77" },
{ 0xd0e, "Cortex-A76AE" },
{ 0xd13, "Cortex-R52" },
{ 0xd20, "Cortex-M23" },
{ 0xd21, "Cortex-M33" },
{ 0xd41, "Cortex-A78" },
{ 0xd42, "Cortex-A78AE" },
{ 0xd4a, "Neoverse-E1" },
{ 0xd4b, "Cortex-A78C" },
};
if (strncmp(buf, part_marker, sizeof(part_marker) - 1) == 0) {
model = buf + sizeof(part_marker) - 1;
errno = 0;
model_id = strtol(model, NULL, 16);
if ((errno != 0) || model_id < 0) {
fclose(fp);
return UV_EINVAL;
}
for (part_idx = 0; part_idx < ARRAY_SIZE(arm_chips); part_idx++) {
if (model_id == arm_chips[part_idx].id) {
model = uv__strdup(arm_chips[part_idx].name);
if (model == NULL) {
fclose(fp);
return UV_ENOMEM;
}
ci[model_idx++].model = model;
break;
}
}
}
#else /* defined(__mips__) */ #else /* defined(__mips__) */
static const char model_marker[] = "cpu model\t\t: "; static const char model_marker[] = "cpu model\t\t: ";
#endif #endif
@ -421,18 +512,18 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
continue; continue;
} }
} }
#else /* !__arm__ && !__mips__ */ #else /* !__arm__ && !__mips__ && !__aarch64__ */
if (speed_idx < numcpus) { if (speed_idx < numcpus) {
if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) { if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) {
ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1); ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1);
continue; continue;
} }
} }
#endif /* __arm__ || __mips__ */ #endif /* __arm__ || __mips__ || __aarch64__ */
} }
fclose(fp); fclose(fp);
#endif /* __arm__ || __i386__ || __mips__ || __PPC__ || __x86_64__ */ #endif /* __arm__ || __i386__ || __mips__ || __PPC__ || __x86_64__ || __aarch__ */
/* Now we want to make sure that all the models contain *something* because /* Now we want to make sure that all the models contain *something* because
* it's not safe to leave them as null. Copy the last entry unless there * it's not safe to leave them as null. Copy the last entry unless there
@ -697,7 +788,7 @@ uint64_t uv_get_free_memory(void) {
struct sysinfo info; struct sysinfo info;
uint64_t rc; uint64_t rc;
rc = uv__read_proc_meminfo("MemFree:"); rc = uv__read_proc_meminfo("MemAvailable:");
if (rc != 0) if (rc != 0)
return rc; return rc;

View File

@ -136,6 +136,11 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
} }
void uv__os390_cleanup(void) {
msgctl(uv_backend_fd(uv_default_loop()), IPC_RMID, NULL);
}
static void init_message_queue(uv__os390_epoll* lst) { static void init_message_queue(uv__os390_epoll* lst) {
struct { struct {
long int header; long int header;

View File

@ -70,5 +70,6 @@ int sem_destroy(UV_PLATFORM_SEM_T* semid);
int sem_post(UV_PLATFORM_SEM_T* semid); int sem_post(UV_PLATFORM_SEM_T* semid);
int sem_trywait(UV_PLATFORM_SEM_T* semid); int sem_trywait(UV_PLATFORM_SEM_T* semid);
int sem_wait(UV_PLATFORM_SEM_T* semid); int sem_wait(UV_PLATFORM_SEM_T* semid);
void uv__os390_cleanup(void);
#endif /* UV_OS390_SYSCALL_H_ */ #endif /* UV_OS390_SYSCALL_H_ */

View File

@ -26,6 +26,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -216,13 +217,32 @@ static void uv__process_child_init(const uv_process_options_t* options,
int stdio_count, int stdio_count,
int (*pipes)[2], int (*pipes)[2],
int error_fd) { int error_fd) {
sigset_t set; sigset_t signewset;
int close_fd; int close_fd;
int use_fd; int use_fd;
int err;
int fd; int fd;
int n; int n;
/* Reset signal disposition first. Use a hard-coded limit because NSIG is not
* fixed on Linux: it's either 32, 34 or 64, depending on whether RT signals
* are enabled. We are not allowed to touch RT signal handlers, glibc uses
* them internally.
*/
for (n = 1; n < 32; n += 1) {
if (n == SIGKILL || n == SIGSTOP)
continue; /* Can't be changed. */
#if defined(__HAIKU__)
if (n == SIGKILLTHR)
continue; /* Can't be changed. */
#endif
if (SIG_ERR != signal(n, SIG_DFL))
continue;
uv__write_errno(error_fd);
}
if (options->flags & UV_PROCESS_DETACHED) if (options->flags & UV_PROCESS_DETACHED)
setsid(); setsid();
@ -304,32 +324,10 @@ static void uv__process_child_init(const uv_process_options_t* options,
environ = options->env; environ = options->env;
} }
/* Reset signal disposition. Use a hard-coded limit because NSIG /* Reset signal mask just before exec. */
* is not fixed on Linux: it's either 32, 34 or 64, depending on sigemptyset(&signewset);
* whether RT signals are enabled. We are not allowed to touch if (sigprocmask(SIG_SETMASK, &signewset, NULL) != 0)
* RT signal handlers, glibc uses them internally. abort();
*/
for (n = 1; n < 32; n += 1) {
if (n == SIGKILL || n == SIGSTOP)
continue; /* Can't be changed. */
#if defined(__HAIKU__)
if (n == SIGKILLTHR)
continue; /* Can't be changed. */
#endif
if (SIG_ERR != signal(n, SIG_DFL))
continue;
uv__write_errno(error_fd);
}
/* Reset signal mask. */
sigemptyset(&set);
err = pthread_sigmask(SIG_SETMASK, &set, NULL);
if (err != 0)
uv__write_errno(error_fd);
#ifdef __MVS__ #ifdef __MVS__
execvpe(options->file, options->args, environ); execvpe(options->file, options->args, environ);
@ -338,6 +336,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
#endif #endif
uv__write_errno(error_fd); uv__write_errno(error_fd);
abort();
} }
#endif #endif
@ -349,6 +348,8 @@ int uv_spawn(uv_loop_t* loop,
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */ /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
return UV_ENOSYS; return UV_ENOSYS;
#else #else
sigset_t signewset;
sigset_t sigoldset;
int signal_pipe[2] = { -1, -1 }; int signal_pipe[2] = { -1, -1 };
int pipes_storage[8][2]; int pipes_storage[8][2];
int (*pipes)[2]; int (*pipes)[2];
@ -423,25 +424,41 @@ int uv_spawn(uv_loop_t* loop,
/* Acquire write lock to prevent opening new fds in worker threads */ /* Acquire write lock to prevent opening new fds in worker threads */
uv_rwlock_wrlock(&loop->cloexec_lock); uv_rwlock_wrlock(&loop->cloexec_lock);
pid = fork();
if (pid == -1) { /* Start the child with most signals blocked, to avoid any issues before we
err = UV__ERR(errno); * can reset them, but allow program failures to exit (and not hang). */
uv_rwlock_wrunlock(&loop->cloexec_lock); sigfillset(&signewset);
uv__close(signal_pipe[0]); sigdelset(&signewset, SIGKILL);
uv__close(signal_pipe[1]); sigdelset(&signewset, SIGSTOP);
goto error; sigdelset(&signewset, SIGTRAP);
} sigdelset(&signewset, SIGSEGV);
sigdelset(&signewset, SIGBUS);
if (pid == 0) { sigdelset(&signewset, SIGILL);
uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]); sigdelset(&signewset, SIGSYS);
sigdelset(&signewset, SIGABRT);
if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0)
abort();
pid = fork();
if (pid == -1)
err = UV__ERR(errno);
if (pid == 0)
uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]);
if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0)
abort(); abort();
}
/* Release lock in parent process */ /* Release lock in parent process */
uv_rwlock_wrunlock(&loop->cloexec_lock); uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[1]); uv__close(signal_pipe[1]);
if (pid == -1) {
uv__close(signal_pipe[0]);
goto error;
}
process->status = 0; process->status = 0;
exec_errorno = 0; exec_errorno = 0;
do do

View File

@ -1010,7 +1010,6 @@ uv_handle_type uv__handle_type(int fd) {
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_HANDLE_READ_EOF; stream->flags |= UV_HANDLE_READ_EOF;
stream->flags &= ~UV_HANDLE_READING; stream->flags &= ~UV_HANDLE_READING;
stream->flags &= ~UV_HANDLE_READABLE;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
uv__handle_stop(stream); uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream); uv__stream_osx_interrupt_select(stream);
@ -1550,15 +1549,12 @@ int uv__read_start(uv_stream_t* stream,
assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
stream->type == UV_TTY); stream->type == UV_TTY);
/* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just /* The UV_HANDLE_READING flag is irrelevant of the state of the stream - it
* expresses the desired state of the user. * just expresses the desired state of the user. */
*/
stream->flags |= UV_HANDLE_READING; stream->flags |= UV_HANDLE_READING;
stream->flags &= ~UV_HANDLE_READ_EOF;
/* TODO: try to do the read inline? */ /* TODO: try to do the read inline? */
/* TODO: keep track of tcp state. If we've gotten a EOF then we should
* not start the IO watcher.
*/
assert(uv__stream_fd(stream) >= 0); assert(uv__stream_fd(stream) >= 0);
assert(alloc_cb); assert(alloc_cb);

View File

@ -375,8 +375,11 @@ write_queue_drain:
return; return;
} }
/* Safety: npkts known to be >0 below. Hence cast from ssize_t
* to size_t safe.
*/
for (i = 0, q = QUEUE_HEAD(&handle->write_queue); for (i = 0, q = QUEUE_HEAD(&handle->write_queue);
i < pkts && q != &handle->write_queue; i < (size_t)npkts && q != &handle->write_queue;
++i, q = QUEUE_HEAD(&handle->write_queue)) { ++i, q = QUEUE_HEAD(&handle->write_queue)) {
assert(q != NULL); assert(q != NULL);
req = QUEUE_DATA(q, uv_udp_send_t, queue); req = QUEUE_DATA(q, uv_udp_send_t, queue);
@ -651,28 +654,71 @@ int uv__udp_connect(uv_udp_t* handle,
return 0; return 0;
} }
/* From https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html
* Any of uv supported UNIXs kernel should be standardized, but the kernel
* implementation logic not same, let's use pseudocode to explain the udp
* disconnect behaviors:
*
* Predefined stubs for pseudocode:
* 1. sodisconnect: The function to perform the real udp disconnect
* 2. pru_connect: The function to perform the real udp connect
* 3. so: The kernel object match with socket fd
* 4. addr: The sockaddr parameter from user space
*
* BSDs:
* if(sodisconnect(so) == 0) { // udp disconnect succeed
* if (addr->sa_len != so->addr->sa_len) return EINVAL;
* if (addr->sa_family != so->addr->sa_family) return EAFNOSUPPORT;
* pru_connect(so);
* }
* else return EISCONN;
*
* z/OS (same with Windows):
* if(addr->sa_len < so->addr->sa_len) return EINVAL;
* if (addr->sa_family == AF_UNSPEC) sodisconnect(so);
*
* AIX:
* if(addr->sa_len != sizeof(struct sockaddr)) return EINVAL; // ignore ip proto version
* if (addr->sa_family == AF_UNSPEC) sodisconnect(so);
*
* Linux,Others:
* if(addr->sa_len < sizeof(struct sockaddr)) return EINVAL;
* if (addr->sa_family == AF_UNSPEC) sodisconnect(so);
*/
int uv__udp_disconnect(uv_udp_t* handle) { int uv__udp_disconnect(uv_udp_t* handle) {
int r; int r;
#if defined(__MVS__)
struct sockaddr_storage addr;
#else
struct sockaddr addr; struct sockaddr addr;
#endif
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
#if defined(__MVS__)
addr.ss_family = AF_UNSPEC;
#else
addr.sa_family = AF_UNSPEC; addr.sa_family = AF_UNSPEC;
#endif
do { do {
errno = 0; errno = 0;
r = connect(handle->io_watcher.fd, &addr, sizeof(addr)); r = connect(handle->io_watcher.fd, (struct sockaddr*) &addr, sizeof(addr));
} while (r == -1 && errno == EINTR); } while (r == -1 && errno == EINTR);
if (r == -1 && errno != EAFNOSUPPORT) if (r == -1) {
#if defined(BSD) /* The macro BSD is from sys/param.h */
if (errno != EAFNOSUPPORT && errno != EINVAL)
return UV__ERR(errno);
#else
return UV__ERR(errno); return UV__ERR(errno);
#endif
}
handle->flags &= ~UV_HANDLE_UDP_CONNECTED; handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
return 0; return 0;
} }
int uv__udp_send(uv_udp_send_t* req, int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle, uv_udp_t* handle,
const uv_buf_t bufs[], const uv_buf_t bufs[],
@ -880,7 +926,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
#if !defined(__OpenBSD__) && \ #if !defined(__OpenBSD__) && \
!defined(__NetBSD__) && \ !defined(__NetBSD__) && \
!defined(__ANDROID__) && \ !defined(__ANDROID__) && \
!defined(__DragonFly__) & \ !defined(__DragonFly__) && \
!defined(__QNX__) !defined(__QNX__)
static int uv__udp_set_source_membership4(uv_udp_t* handle, static int uv__udp_set_source_membership4(uv_udp_t* handle,
const struct sockaddr_in* multicast_addr, const struct sockaddr_in* multicast_addr,

View File

@ -274,6 +274,20 @@ int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
} }
int uv_ip_name(const struct sockaddr *src, char *dst, size_t size) {
switch (src->sa_family) {
case AF_INET:
return uv_inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr,
dst, size);
case AF_INET6:
return uv_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)src)->sin6_addr,
dst, size);
default:
return UV_EAFNOSUPPORT;
}
}
int uv_tcp_bind(uv_tcp_t* handle, int uv_tcp_bind(uv_tcp_t* handle,
const struct sockaddr* addr, const struct sockaddr* addr,
unsigned int flags) { unsigned int flags) {
@ -887,7 +901,12 @@ void uv_library_shutdown(void) {
uv__process_title_cleanup(); uv__process_title_cleanup();
uv__signal_cleanup(); uv__signal_cleanup();
#ifdef __MVS__
/* TODO(itodorov) - zos: revisit when Woz compiler is available. */
uv__os390_cleanup();
#else
uv__threadpool_cleanup(); uv__threadpool_cleanup();
#endif
uv__store_relaxed(&was_shutdown, 1); uv__store_relaxed(&was_shutdown, 1);
} }

View File

@ -574,10 +574,10 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
handle->cb(handle, NULL, 0, uv_translate_sys_error(err)); handle->cb(handle, NULL, 0, uv_translate_sys_error(err));
} }
if (!(handle->flags & UV_HANDLE_CLOSING)) { if (handle->flags & UV_HANDLE_CLOSING) {
uv_fs_event_queue_readdirchanges(loop, handle);
} else {
uv_want_endgame(loop, (uv_handle_t*)handle); uv_want_endgame(loop, (uv_handle_t*)handle);
} else if (uv__is_active(handle)) {
uv_fs_event_queue_readdirchanges(loop, handle);
} }
} }

View File

@ -758,7 +758,7 @@ void fs__read_filemap(uv_fs_t* req, struct uv__fd_info_s* fd_info) {
void* view; void* view;
if (rw_flags == UV_FS_O_WRONLY) { if (rw_flags == UV_FS_O_WRONLY) {
SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED); SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FLAGS);
return; return;
} }
if (fd_info->is_directory) { if (fd_info->is_directory) {
@ -912,6 +912,11 @@ void fs__read(uv_fs_t* req) {
SET_REQ_RESULT(req, bytes); SET_REQ_RESULT(req, bytes);
} else { } else {
error = GetLastError(); error = GetLastError();
if (error == ERROR_ACCESS_DENIED) {
error = ERROR_INVALID_FLAGS;
}
if (error == ERROR_HANDLE_EOF) { if (error == ERROR_HANDLE_EOF) {
SET_REQ_RESULT(req, bytes); SET_REQ_RESULT(req, bytes);
} else { } else {
@ -936,7 +941,7 @@ void fs__write_filemap(uv_fs_t* req, HANDLE file,
FILETIME ft; FILETIME ft;
if (rw_flags == UV_FS_O_RDONLY) { if (rw_flags == UV_FS_O_RDONLY) {
SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED); SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FLAGS);
return; return;
} }
if (fd_info->is_directory) { if (fd_info->is_directory) {
@ -1052,6 +1057,7 @@ void fs__write(uv_fs_t* req) {
OVERLAPPED overlapped, *overlapped_ptr; OVERLAPPED overlapped, *overlapped_ptr;
LARGE_INTEGER offset_; LARGE_INTEGER offset_;
DWORD bytes; DWORD bytes;
DWORD error;
int result; int result;
unsigned int index; unsigned int index;
LARGE_INTEGER original_position; LARGE_INTEGER original_position;
@ -1111,7 +1117,13 @@ void fs__write(uv_fs_t* req) {
if (result || bytes > 0) { if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes); SET_REQ_RESULT(req, bytes);
} else { } else {
SET_REQ_WIN32_ERROR(req, GetLastError()); error = GetLastError();
if (error == ERROR_ACCESS_DENIED) {
error = ERROR_INVALID_FLAGS;
}
SET_REQ_WIN32_ERROR(req, error);
} }
} }

View File

@ -1252,7 +1252,6 @@ static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) {
assert(req != NULL); assert(req != NULL);
assert(req->type == UV_WRITE); assert(req->type == UV_WRITE);
assert(handle->type == UV_NAMED_PIPE); assert(handle->type == UV_NAMED_PIPE);
assert(req->write_buffer.base);
result = WriteFile(handle->handle, result = WriteFile(handle->handle,
req->write_buffer.base, req->write_buffer.base,
@ -1797,7 +1796,6 @@ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
* it. */ * it. */
eof_timer_destroy(handle); eof_timer_destroy(handle);
handle->flags &= ~UV_HANDLE_READABLE;
uv_read_stop((uv_stream_t*) handle); uv_read_stop((uv_stream_t*) handle);
handle->read_cb((uv_stream_t*) handle, UV_EOF, &buf); handle->read_cb((uv_stream_t*) handle, UV_EOF, &buf);

View File

@ -169,7 +169,9 @@ static WCHAR* search_path_join_test(const WCHAR* dir,
size_t cwd_len) { size_t cwd_len) {
WCHAR *result, *result_pos; WCHAR *result, *result_pos;
DWORD attrs; DWORD attrs;
if (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') { if (dir_len > 2 &&
((dir[0] == L'\\' || dir[0] == L'/') &&
(dir[1] == L'\\' || dir[1] == L'/'))) {
/* It's a UNC path so ignore cwd */ /* It's a UNC path so ignore cwd */
cwd_len = 0; cwd_len = 0;
} else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) { } else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) {

View File

@ -1044,7 +1044,6 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
handle->flags &= ~UV_HANDLE_READING; handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle); DECREASE_ACTIVE_COUNT(loop, handle);
} }
handle->flags &= ~UV_HANDLE_READABLE;
buf.base = 0; buf.base = 0;
buf.len = 0; buf.len = 0;
@ -1081,7 +1080,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
} }
} else { } else {
/* Connection closed */ /* Connection closed */
handle->flags &= ~(UV_HANDLE_READING | UV_HANDLE_READABLE); handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle); DECREASE_ACTIVE_COUNT(loop, handle);
handle->read_cb((uv_stream_t*)handle, UV_EOF, &buf); handle->read_cb((uv_stream_t*)handle, UV_EOF, &buf);
@ -1651,7 +1650,7 @@ int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int f
err = WSAGetLastError(); err = WSAGetLastError();
if (err == ERROR_IO_PENDING) { if (err == ERROR_IO_PENDING) {
/* Result should complete immediately, since we already called connect, /* Result should complete immediately, since we already called connect,
* but emperically, we sometimes have to poll the kernel a couple times * but empirically, we sometimes have to poll the kernel a couple times
* until it notices that. */ * until it notices that. */
while (!WSAGetOverlappedResult(client1, &overlap, &bytes, FALSE, &flags)) { while (!WSAGetOverlappedResult(client1, &overlap, &bytes, FALSE, &flags)) {
err = WSAGetLastError(); err = WSAGetLastError();

View File

@ -103,7 +103,7 @@ static UINT __stdcall uv__thread_start(void* arg) {
uv__free(ctx_p); uv__free(ctx_p);
uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
uv_key_set(&uv__current_thread_key, (void*) ctx.self); uv_key_set(&uv__current_thread_key, ctx.self);
ctx.entry(ctx.arg); ctx.entry(ctx.arg);
@ -183,7 +183,18 @@ int uv_thread_create_ex(uv_thread_t* tid,
uv_thread_t uv_thread_self(void) { uv_thread_t uv_thread_self(void) {
uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
return (uv_thread_t) uv_key_get(&uv__current_thread_key); uv_thread_t key = uv_key_get(&uv__current_thread_key);
if (key == NULL) {
/* If the thread wasn't started by uv_thread_create (such as the main
* thread), we assign an id to it now. */
if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
GetCurrentProcess(), &key, 0,
FALSE, DUPLICATE_SAME_ACCESS)) {
uv_fatal_error(GetLastError(), "DuplicateHandle");
}
uv_key_set(&uv__current_thread_key, key);
}
return key;
} }

View File

@ -1083,7 +1083,7 @@ int uv__udp_connect(uv_udp_t* handle,
int uv__udp_disconnect(uv_udp_t* handle) { int uv__udp_disconnect(uv_udp_t* handle) {
int err; int err;
struct sockaddr addr; struct sockaddr_storage addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));

View File

@ -1674,7 +1674,10 @@ int uv_os_gethostname(char* buffer, size_t* size) {
uv__once_init(); /* Initialize winsock */ uv__once_init(); /* Initialize winsock */
if (GetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0) if (pGetHostNameW == NULL)
return UV_ENOSYS;
if (pGetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0)
return uv_translate_sys_error(WSAGetLastError()); return uv_translate_sys_error(WSAGetLastError());
convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str); convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str);

View File

@ -45,12 +45,15 @@ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
/* User32.dll function pointer */ /* User32.dll function pointer */
sSetWinEventHook pSetWinEventHook; sSetWinEventHook pSetWinEventHook;
/* ws2_32.dll function pointer */
uv_sGetHostNameW pGetHostNameW;
void uv_winapi_init(void) { void uv_winapi_init(void) {
HMODULE ntdll_module; HMODULE ntdll_module;
HMODULE powrprof_module; HMODULE powrprof_module;
HMODULE user32_module; HMODULE user32_module;
HMODULE kernel32_module; HMODULE kernel32_module;
HMODULE ws2_32_module;
ntdll_module = GetModuleHandleA("ntdll.dll"); ntdll_module = GetModuleHandleA("ntdll.dll");
if (ntdll_module == NULL) { if (ntdll_module == NULL) {
@ -134,4 +137,11 @@ void uv_winapi_init(void) {
pSetWinEventHook = (sSetWinEventHook) pSetWinEventHook = (sSetWinEventHook)
GetProcAddress(user32_module, "SetWinEventHook"); GetProcAddress(user32_module, "SetWinEventHook");
} }
ws2_32_module = LoadLibraryA("ws2_32.dll");
if (ws2_32_module != NULL) {
pGetHostNameW = (uv_sGetHostNameW) GetProcAddress(
ws2_32_module,
"GetHostNameW");
}
} }

View File

@ -4759,4 +4759,11 @@ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotifi
/* User32.dll function pointer */ /* User32.dll function pointer */
extern sSetWinEventHook pSetWinEventHook; extern sSetWinEventHook pSetWinEventHook;
/* ws2_32.dll function pointer */
/* mingw doesn't have this definition, so let's declare it here locally */
typedef int (WINAPI *uv_sGetHostNameW)
(PWSTR,
int);
extern uv_sGetHostNameW pGetHostNameW;
#endif /* UV_WIN_WINAPI_H_ */ #endif /* UV_WIN_WINAPI_H_ */

View File

@ -81,7 +81,6 @@ HELPER_DECLARE (tcp_pump_server)
HELPER_DECLARE (pipe_pump_server) HELPER_DECLARE (pipe_pump_server)
HELPER_DECLARE (tcp4_echo_server) HELPER_DECLARE (tcp4_echo_server)
HELPER_DECLARE (pipe_echo_server) HELPER_DECLARE (pipe_echo_server)
HELPER_DECLARE (dns_server)
TASK_LIST_START TASK_LIST_START
BENCHMARK_ENTRY (sizes) BENCHMARK_ENTRY (sizes)

View File

@ -1,340 +0,0 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
uv_write_t req;
uv_buf_t buf;
} write_req_t;
/* used to track multiple DNS requests received */
typedef struct {
char* prevbuf_ptr;
int prevbuf_pos;
int prevbuf_rem;
} dnsstate;
/* modify handle to append dnsstate */
typedef struct {
uv_tcp_t handle;
dnsstate state;
} dnshandle;
static uv_loop_t* loop;
static uv_tcp_t server;
static void after_write(uv_write_t* req, int status);
static void after_read(uv_stream_t*, ssize_t nread, const uv_buf_t* buf);
static void on_close(uv_handle_t* peer);
static void on_connection(uv_stream_t*, int status);
#define WRITE_BUF_LEN (64*1024)
#define DNSREC_LEN (4)
#define LEN_OFFSET 0
#define QUERYID_OFFSET 2
static unsigned char DNSRsp[] = {
0, 43, 0, 0, 0x81, 0x80, 0, 1, 0, 1, 0, 0, 0, 0
};
static unsigned char qrecord[] = {
5, 'e', 'c', 'h', 'o', 's', 3, 's', 'r', 'v', 0, 0, 1, 0, 1
};
static unsigned char arecord[] = {
0xc0, 0x0c, 0, 1, 0, 1, 0, 0, 5, 0xbd, 0, 4, 10, 0, 1, 1
};
static void after_write(uv_write_t* req, int status) {
write_req_t* wr;
if (status) {
fprintf(stderr, "uv_write error: %s\n", uv_strerror(status));
ASSERT(0);
}
wr = (write_req_t*) req;
/* Free the read/write buffer and the request */
free(wr->buf.base);
free(wr);
}
static void after_shutdown(uv_shutdown_t* req, int status) {
uv_close((uv_handle_t*) req->handle, on_close);
free(req);
}
static void addrsp(write_req_t* wr, char* hdr) {
char * dnsrsp;
short int rsplen;
short int* reclen;
rsplen = sizeof(DNSRsp) + sizeof(qrecord) + sizeof(arecord);
ASSERT (rsplen + wr->buf.len < WRITE_BUF_LEN);
dnsrsp = wr->buf.base + wr->buf.len;
/* copy stock response */
memcpy(dnsrsp, DNSRsp, sizeof(DNSRsp));
memcpy(dnsrsp + sizeof(DNSRsp), qrecord, sizeof(qrecord));
memcpy(dnsrsp + sizeof(DNSRsp) + sizeof(qrecord), arecord, sizeof(arecord));
/* overwrite with network order length and id from request header */
reclen = (short int*)dnsrsp;
*reclen = htons(rsplen-2);
dnsrsp[QUERYID_OFFSET] = hdr[QUERYID_OFFSET];
dnsrsp[QUERYID_OFFSET+1] = hdr[QUERYID_OFFSET+1];
wr->buf.len += rsplen;
}
static void process_req(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf) {
write_req_t* wr;
dnshandle* dns = (dnshandle*)handle;
char hdrbuf[DNSREC_LEN];
int hdrbuf_remaining = DNSREC_LEN;
int rec_remaining = 0;
int readbuf_remaining;
char* dnsreq;
char* hdrstart;
int usingprev = 0;
wr = (write_req_t*) malloc(sizeof *wr);
wr->buf.base = (char*)malloc(WRITE_BUF_LEN);
wr->buf.len = 0;
if (dns->state.prevbuf_ptr != NULL) {
dnsreq = dns->state.prevbuf_ptr + dns->state.prevbuf_pos;
readbuf_remaining = dns->state.prevbuf_rem;
usingprev = 1;
} else {
dnsreq = buf->base;
readbuf_remaining = nread;
}
hdrstart = dnsreq;
while (dnsreq != NULL) {
/* something to process */
while (readbuf_remaining > 0) {
/* something to process in current buffer */
if (hdrbuf_remaining > 0) {
/* process len and id */
if (readbuf_remaining < hdrbuf_remaining) {
/* too little to get request header. save for next buffer */
memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining],
dnsreq,
readbuf_remaining);
hdrbuf_remaining = DNSREC_LEN - readbuf_remaining;
break;
} else {
/* save header */
memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining],
dnsreq,
hdrbuf_remaining);
dnsreq += hdrbuf_remaining;
readbuf_remaining -= hdrbuf_remaining;
hdrbuf_remaining = 0;
/* get record length */
rec_remaining = (unsigned) hdrbuf[0] * 256 + (unsigned) hdrbuf[1];
rec_remaining -= (DNSREC_LEN - 2);
}
}
if (rec_remaining <= readbuf_remaining) {
/* prepare reply */
addrsp(wr, hdrbuf);
/* move to next record */
dnsreq += rec_remaining;
hdrstart = dnsreq;
readbuf_remaining -= rec_remaining;
rec_remaining = 0;
hdrbuf_remaining = DNSREC_LEN;
} else {
/* otherwise this buffer is done. */
rec_remaining -= readbuf_remaining;
break;
}
}
/* If we had to use bytes from prev buffer, start processing the current
* one.
*/
if (usingprev == 1) {
/* free previous buffer */
free(dns->state.prevbuf_ptr);
dnsreq = buf->base;
readbuf_remaining = nread;
usingprev = 0;
} else {
dnsreq = NULL;
}
}
/* send write buffer */
if (wr->buf.len > 0) {
if (uv_write((uv_write_t*) &wr->req, handle, &wr->buf, 1, after_write)) {
FATAL("uv_write failed");
}
}
if (readbuf_remaining > 0) {
/* save start of record position, so we can continue on next read */
dns->state.prevbuf_ptr = buf->base;
dns->state.prevbuf_pos = hdrstart - buf->base;
dns->state.prevbuf_rem = nread - dns->state.prevbuf_pos;
} else {
/* nothing left in this buffer */
dns->state.prevbuf_ptr = NULL;
dns->state.prevbuf_pos = 0;
dns->state.prevbuf_rem = 0;
free(buf->base);
}
}
static void after_read(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf) {
uv_shutdown_t* req;
if (nread < 0) {
/* Error or EOF */
ASSERT(nread == UV_EOF);
if (buf->base) {
free(buf->base);
}
req = malloc(sizeof *req);
uv_shutdown(req, handle, after_shutdown);
return;
}
if (nread == 0) {
/* Everything OK, but nothing read. */
free(buf->base);
return;
}
/* process requests and send responses */
process_req(handle, nread, buf);
}
static void on_close(uv_handle_t* peer) {
free(peer);
}
static void buf_alloc(uv_handle_t* handle,
size_t suggested_size,
uv_buf_t* buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
static void on_connection(uv_stream_t* server, int status) {
dnshandle* handle;
int r;
ASSERT(status == 0);
handle = (dnshandle*) malloc(sizeof *handle);
ASSERT_NOT_NULL(handle);
/* initialize read buffer state */
handle->state.prevbuf_ptr = 0;
handle->state.prevbuf_pos = 0;
handle->state.prevbuf_rem = 0;
r = uv_tcp_init(loop, (uv_tcp_t*)handle);
ASSERT(r == 0);
r = uv_accept(server, (uv_stream_t*)handle);
ASSERT(r == 0);
r = uv_read_start((uv_stream_t*)handle, buf_alloc, after_read);
ASSERT(r == 0);
}
static int dns_start(int port) {
struct sockaddr_in addr;
int r;
ASSERT(0 == uv_ip4_addr("0.0.0.0", port, &addr));
r = uv_tcp_init(loop, &server);
if (r) {
/* TODO: Error codes */
fprintf(stderr, "Socket creation error\n");
return 1;
}
r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
if (r) {
/* TODO: Error codes */
fprintf(stderr, "Bind error\n");
return 1;
}
r = uv_listen((uv_stream_t*)&server, 128, on_connection);
if (r) {
/* TODO: Error codes */
fprintf(stderr, "Listen error\n");
return 1;
}
return 0;
}
HELPER_IMPL(dns_server) {
loop = uv_default_loop();
if (dns_start(TEST_PORT_2))
return 1;
uv_run(loop, UV_RUN_DEFAULT);
return 0;
}

View File

@ -277,7 +277,7 @@ const char* fmt(double d);
/* Reserved test exit codes. */ /* Reserved test exit codes. */
enum test_status { enum test_status {
TEST_OK = 0, TEST_OK = 0,
TEST_SKIP TEST_SKIP = 7
}; };
#define RETURN_OK() \ #define RETURN_OK() \

View File

@ -96,9 +96,6 @@ static void touch_file(const char* name, unsigned int size) {
TEST_IMPL(fs_copyfile) { TEST_IMPL(fs_copyfile) {
#if defined(__ASAN__)
RETURN_SKIP("Test does not currently work in ASAN");
#endif
const char src[] = "test_file_src"; const char src[] = "test_file_src";
uv_loop_t* loop; uv_loop_t* loop;
uv_fs_t req; uv_fs_t req;

View File

@ -380,7 +380,7 @@ static void timer_cb_file(uv_timer_t* handle) {
static void timer_cb_touch(uv_timer_t* timer) { static void timer_cb_touch(uv_timer_t* timer) {
uv_close((uv_handle_t*)timer, NULL); uv_close((uv_handle_t*)timer, NULL);
touch_file("watch_file"); touch_file((char*) timer->data);
timer_cb_touch_called++; timer_cb_touch_called++;
} }
@ -673,9 +673,6 @@ TEST_IMPL(fs_event_watch_file_exact_path) {
TEST_IMPL(fs_event_watch_file_twice) { TEST_IMPL(fs_event_watch_file_twice) {
#if defined(NO_FS_EVENTS) #if defined(NO_FS_EVENTS)
RETURN_SKIP(NO_FS_EVENTS); RETURN_SKIP(NO_FS_EVENTS);
#endif
#if defined(__ASAN__)
RETURN_SKIP("Test does not currently work in ASAN");
#endif #endif
const char path[] = "test/fixtures/empty_file"; const char path[] = "test/fixtures/empty_file";
uv_fs_event_t watchers[2]; uv_fs_event_t watchers[2];
@ -730,6 +727,7 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
r = uv_timer_init(loop, &timer); r = uv_timer_init(loop, &timer);
ASSERT(r == 0); ASSERT(r == 0);
timer.data = "watch_file";
r = uv_timer_start(&timer, timer_cb_touch, 1100, 0); r = uv_timer_start(&timer, timer_cb_touch, 1100, 0);
ASSERT(r == 0); ASSERT(r == 0);
@ -1174,3 +1172,49 @@ TEST_IMPL(fs_event_watch_invalid_path) {
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; return 0;
} }
static int fs_event_cb_stop_calls;
static void fs_event_cb_stop(uv_fs_event_t* handle, const char* path,
int events, int status) {
uv_fs_event_stop(handle);
fs_event_cb_stop_calls++;
}
TEST_IMPL(fs_event_stop_in_cb) {
uv_fs_event_t fs;
uv_timer_t timer;
char path[] = "fs_event_stop_in_cb.txt";
#if defined(NO_FS_EVENTS)
RETURN_SKIP(NO_FS_EVENTS);
#endif
remove(path);
create_file(path);
ASSERT_EQ(0, uv_fs_event_init(uv_default_loop(), &fs));
ASSERT_EQ(0, uv_fs_event_start(&fs, fs_event_cb_stop, path, 0));
/* Note: timer_cb_touch() closes the handle. */
timer.data = path;
ASSERT_EQ(0, uv_timer_init(uv_default_loop(), &timer));
ASSERT_EQ(0, uv_timer_start(&timer, timer_cb_touch, 100, 0));
ASSERT_EQ(0, fs_event_cb_stop_calls);
ASSERT_EQ(0, timer_cb_touch_called);
ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT_EQ(1, fs_event_cb_stop_calls);
ASSERT_EQ(1, timer_cb_touch_called);
uv_close((uv_handle_t*) &fs, NULL);
ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT_EQ(1, fs_event_cb_stop_calls);
remove(path);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -276,21 +276,21 @@ static void fs_open_flags(int add_flags) {
/* r */ /* r */
flags = add_flags | UV_FS_O_RDONLY; flags = add_flags | UV_FS_O_RDONLY;
openFail(absent_file, UV_ENOENT); openFail(absent_file, UV_ENOENT);
writeFail(empty_file, UV_EPERM); writeFail(empty_file, UV_EBADF);
readExpect(empty_file, "", 0); readExpect(empty_file, "", 0);
writeFail(dummy_file, UV_EPERM); writeFail(dummy_file, UV_EBADF);
readExpect(dummy_file, "a", 1); readExpect(dummy_file, "a", 1);
writeFail(empty_dir, UV_EPERM); writeFail(empty_dir, UV_EBADF);
readFail(empty_dir, UV_EISDIR); readFail(empty_dir, UV_EISDIR);
/* rs */ /* rs */
flags = add_flags | UV_FS_O_RDONLY | UV_FS_O_SYNC; flags = add_flags | UV_FS_O_RDONLY | UV_FS_O_SYNC;
openFail(absent_file, UV_ENOENT); openFail(absent_file, UV_ENOENT);
writeFail(empty_file, UV_EPERM); writeFail(empty_file, UV_EBADF);
readExpect(empty_file, "", 0); readExpect(empty_file, "", 0);
writeFail(dummy_file, UV_EPERM); writeFail(dummy_file, UV_EBADF);
readExpect(dummy_file, "a", 1); readExpect(dummy_file, "a", 1);
writeFail(empty_dir, UV_EPERM); writeFail(empty_dir, UV_EBADF);
readFail(empty_dir, UV_EISDIR); readFail(empty_dir, UV_EISDIR);
/* r+ */ /* r+ */
@ -316,18 +316,18 @@ static void fs_open_flags(int add_flags) {
/* w */ /* w */
flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY; flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY;
writeExpect(absent_file, "bc", 2); writeExpect(absent_file, "bc", 2);
readFail(absent_file, UV_EPERM); readFail(absent_file, UV_EBADF);
writeExpect(empty_file, "bc", 2); writeExpect(empty_file, "bc", 2);
readFail(empty_file, UV_EPERM); readFail(empty_file, UV_EBADF);
writeExpect(dummy_file, "bc", 2); writeExpect(dummy_file, "bc", 2);
readFail(dummy_file, UV_EPERM); readFail(dummy_file, UV_EBADF);
openFail(empty_dir, UV_EISDIR); openFail(empty_dir, UV_EISDIR);
/* wx */ /* wx */
flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY | flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY |
UV_FS_O_EXCL; UV_FS_O_EXCL;
writeExpect(absent_file, "bc", 2); writeExpect(absent_file, "bc", 2);
readFail(absent_file, UV_EPERM); readFail(absent_file, UV_EBADF);
openFail(empty_file, UV_EEXIST); openFail(empty_file, UV_EEXIST);
openFail(dummy_file, UV_EEXIST); openFail(dummy_file, UV_EEXIST);
openFail(empty_dir, UV_EEXIST); openFail(empty_dir, UV_EEXIST);
@ -354,19 +354,19 @@ static void fs_open_flags(int add_flags) {
/* a */ /* a */
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY; flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY;
writeExpect(absent_file, "bc", 2); writeExpect(absent_file, "bc", 2);
readFail(absent_file, UV_EPERM); readFail(absent_file, UV_EBADF);
writeExpect(empty_file, "bc", 2); writeExpect(empty_file, "bc", 2);
readFail(empty_file, UV_EPERM); readFail(empty_file, UV_EBADF);
writeExpect(dummy_file, "abc", 3); writeExpect(dummy_file, "abc", 3);
readFail(dummy_file, UV_EPERM); readFail(dummy_file, UV_EBADF);
writeFail(empty_dir, UV_EISDIR); writeFail(empty_dir, UV_EISDIR);
readFail(empty_dir, UV_EPERM); readFail(empty_dir, UV_EBADF);
/* ax */ /* ax */
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY | flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
UV_FS_O_EXCL; UV_FS_O_EXCL;
writeExpect(absent_file, "bc", 2); writeExpect(absent_file, "bc", 2);
readFail(absent_file, UV_EPERM); readFail(absent_file, UV_EBADF);
openFail(empty_file, UV_EEXIST); openFail(empty_file, UV_EEXIST);
openFail(dummy_file, UV_EEXIST); openFail(dummy_file, UV_EEXIST);
openFail(empty_dir, UV_EEXIST); openFail(empty_dir, UV_EEXIST);
@ -375,13 +375,13 @@ static void fs_open_flags(int add_flags) {
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY | flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
UV_FS_O_SYNC; UV_FS_O_SYNC;
writeExpect(absent_file, "bc", 2); writeExpect(absent_file, "bc", 2);
readFail(absent_file, UV_EPERM); readFail(absent_file, UV_EBADF);
writeExpect(empty_file, "bc", 2); writeExpect(empty_file, "bc", 2);
readFail(empty_file, UV_EPERM); readFail(empty_file, UV_EBADF);
writeExpect(dummy_file, "abc", 3); writeExpect(dummy_file, "abc", 3);
readFail(dummy_file, UV_EPERM); readFail(dummy_file, UV_EBADF);
writeFail(empty_dir, UV_EISDIR); writeFail(empty_dir, UV_EISDIR);
readFail(empty_dir, UV_EPERM); readFail(empty_dir, UV_EBADF);
/* a+ */ /* a+ */
flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR; flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR;

View File

@ -230,9 +230,6 @@ static void file_opendir_cb(uv_fs_t* req) {
} }
TEST_IMPL(fs_readdir_file) { TEST_IMPL(fs_readdir_file) {
#if defined(__ASAN__)
RETURN_SKIP("Test does not currently work in ASAN");
#endif
const char* path; const char* path;
int r; int r;

View File

@ -844,7 +844,7 @@ static void check_utime(const char* path,
} else { } else {
double st_atim; double st_atim;
double st_mtim; double st_mtim;
#ifndef __APPLE__ #if !defined(__APPLE__) && !defined(__SUNPRO_C)
/* TODO(vtjnash): would it be better to normalize this? */ /* TODO(vtjnash): would it be better to normalize this? */
ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0); ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0);
ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0); ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0);
@ -2897,9 +2897,6 @@ TEST_IMPL(fs_scandir_non_existent_dir) {
} }
TEST_IMPL(fs_scandir_file) { TEST_IMPL(fs_scandir_file) {
#if defined(__ASAN__)
RETURN_SKIP("Test does not currently work in ASAN");
#endif
const char* path; const char* path;
int r; int r;
@ -3146,9 +3143,6 @@ static void fs_read_bufs(int add_flags) {
uv_fs_req_cleanup(&close_req); uv_fs_req_cleanup(&close_req);
} }
TEST_IMPL(fs_read_bufs) { TEST_IMPL(fs_read_bufs) {
#if defined(__ASAN__)
RETURN_SKIP("Test does not currently work in ASAN");
#endif
fs_read_bufs(0); fs_read_bufs(0);
fs_read_bufs(UV_FS_O_FILEMAP); fs_read_bufs(UV_FS_O_FILEMAP);

65
deps/libuv/test/test-ip-name.c vendored Normal file
View File

@ -0,0 +1,65 @@
/* Copyright The libuv project and contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <stdio.h>
#include <string.h>
union TestAddr {
struct sockaddr addr;
struct sockaddr_in addr4;
struct sockaddr_in6 addr6;
};
TEST_IMPL(ip_name) {
char dst[INET6_ADDRSTRLEN];
union TestAddr test_addr;
struct sockaddr* addr = &test_addr.addr;
struct sockaddr_in* addr4 = &test_addr.addr4;
struct sockaddr_in6* addr6 = &test_addr.addr6;
/* test ip4_name */
ASSERT_EQ(0, uv_ip4_addr("192.168.0.1", TEST_PORT, addr4));
ASSERT_EQ(0, uv_ip4_name(addr4, dst, INET_ADDRSTRLEN));
ASSERT_EQ(0, strcmp("192.168.0.1", dst));
ASSERT_EQ(0, uv_ip_name(addr, dst, INET_ADDRSTRLEN));
ASSERT_EQ(0, strcmp("192.168.0.1", dst));
/* test ip6_name */
ASSERT_EQ(0, uv_ip6_addr("fe80::2acf:daff:fedd:342a", TEST_PORT, addr6));
ASSERT_EQ(0, uv_ip6_name(addr6, dst, INET6_ADDRSTRLEN));
ASSERT_EQ(0, strcmp("fe80::2acf:daff:fedd:342a", dst));
ASSERT_EQ(0, uv_ip_name(addr, dst, INET6_ADDRSTRLEN));
ASSERT_EQ(0, strcmp("fe80::2acf:daff:fedd:342a", dst));
/* test other sa_family */
addr->sa_family = AF_UNIX;
/* size is not a concern here */
ASSERT_EQ(UV_EAFNOSUPPORT, uv_ip_name(addr, dst, INET6_ADDRSTRLEN));
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -161,11 +161,11 @@ TEST_IMPL(ip6_pton) {
#undef GOOD_ADDR_LIST #undef GOOD_ADDR_LIST
#undef BAD_ADDR_LIST #undef BAD_ADDR_LIST
#ifdef SIN6_LEN
TEST_IMPL(ip6_sin6_len) { TEST_IMPL(ip6_sin6_len) {
struct sockaddr_in6 s; struct sockaddr_in6 s;
ASSERT(uv_ip6_addr("::", 0, &s) < 0); ASSERT_EQ(0, uv_ip6_addr("::", 0, &s));
#ifdef SIN6_LEN
ASSERT(s.sin6_len == sizeof(s)); ASSERT(s.sin6_len == sizeof(s));
#endif
return 0; return 0;
} }
#endif

View File

@ -78,6 +78,7 @@ TEST_DECLARE (tty_pty)
TEST_DECLARE (stdio_over_pipes) TEST_DECLARE (stdio_over_pipes)
TEST_DECLARE (stdio_emulate_iocp) TEST_DECLARE (stdio_emulate_iocp)
TEST_DECLARE (ip6_pton) TEST_DECLARE (ip6_pton)
TEST_DECLARE (ip6_sin6_len)
TEST_DECLARE (connect_unspecified) TEST_DECLARE (connect_unspecified)
TEST_DECLARE (ipc_heavy_traffic_deadlock_bug) TEST_DECLARE (ipc_heavy_traffic_deadlock_bug)
TEST_DECLARE (ipc_listen_before_write) TEST_DECLARE (ipc_listen_before_write)
@ -159,6 +160,7 @@ TEST_DECLARE (udp_alloc_cb_fail)
TEST_DECLARE (udp_bind) TEST_DECLARE (udp_bind)
TEST_DECLARE (udp_bind_reuseaddr) TEST_DECLARE (udp_bind_reuseaddr)
TEST_DECLARE (udp_connect) TEST_DECLARE (udp_connect)
TEST_DECLARE (udp_connect6)
TEST_DECLARE (udp_create_early) TEST_DECLARE (udp_create_early)
TEST_DECLARE (udp_create_early_bad_bind) TEST_DECLARE (udp_create_early_bad_bind)
TEST_DECLARE (udp_create_early_bad_domain) TEST_DECLARE (udp_create_early_bad_domain)
@ -390,6 +392,7 @@ TEST_DECLARE (fs_event_close_in_callback)
TEST_DECLARE (fs_event_start_and_close) TEST_DECLARE (fs_event_start_and_close)
TEST_DECLARE (fs_event_error_reporting) TEST_DECLARE (fs_event_error_reporting)
TEST_DECLARE (fs_event_getpath) TEST_DECLARE (fs_event_getpath)
TEST_DECLARE (fs_event_stop_in_cb)
TEST_DECLARE (fs_scandir_empty_dir) TEST_DECLARE (fs_scandir_empty_dir)
TEST_DECLARE (fs_scandir_non_existent_dir) TEST_DECLARE (fs_scandir_non_existent_dir)
TEST_DECLARE (fs_scandir_file) TEST_DECLARE (fs_scandir_file)
@ -458,6 +461,7 @@ TEST_DECLARE (poll_multiple_handles)
TEST_DECLARE (ip4_addr) TEST_DECLARE (ip4_addr)
TEST_DECLARE (ip6_addr_link_local) TEST_DECLARE (ip6_addr_link_local)
TEST_DECLARE (ip_name)
TEST_DECLARE (poll_close_doesnt_corrupt_stack) TEST_DECLARE (poll_close_doesnt_corrupt_stack)
TEST_DECLARE (poll_closesocket) TEST_DECLARE (poll_closesocket)
@ -507,7 +511,7 @@ TEST_DECLARE (getters_setters)
TEST_DECLARE (not_writable_after_shutdown) TEST_DECLARE (not_writable_after_shutdown)
TEST_DECLARE (not_readable_nor_writable_on_read_error) TEST_DECLARE (not_readable_nor_writable_on_read_error)
TEST_DECLARE (not_readable_on_eof) TEST_DECLARE (readable_on_eof)
#ifndef _WIN32 #ifndef _WIN32
TEST_DECLARE (fork_timer) TEST_DECLARE (fork_timer)
@ -610,6 +614,7 @@ TASK_LIST_START
TEST_ENTRY (stdio_over_pipes) TEST_ENTRY (stdio_over_pipes)
TEST_ENTRY (stdio_emulate_iocp) TEST_ENTRY (stdio_emulate_iocp)
TEST_ENTRY (ip6_pton) TEST_ENTRY (ip6_pton)
TEST_ENTRY (ip6_sin6_len)
TEST_ENTRY (connect_unspecified) TEST_ENTRY (connect_unspecified)
TEST_ENTRY (ipc_heavy_traffic_deadlock_bug) TEST_ENTRY (ipc_heavy_traffic_deadlock_bug)
TEST_ENTRY (ipc_listen_before_write) TEST_ENTRY (ipc_listen_before_write)
@ -733,6 +738,7 @@ TASK_LIST_START
TEST_ENTRY (udp_bind) TEST_ENTRY (udp_bind)
TEST_ENTRY (udp_bind_reuseaddr) TEST_ENTRY (udp_bind_reuseaddr)
TEST_ENTRY (udp_connect) TEST_ENTRY (udp_connect)
TEST_ENTRY (udp_connect6)
TEST_ENTRY (udp_create_early) TEST_ENTRY (udp_create_early)
TEST_ENTRY (udp_create_early_bad_bind) TEST_ENTRY (udp_create_early_bad_bind)
TEST_ENTRY (udp_create_early_bad_domain) TEST_ENTRY (udp_create_early_bad_domain)
@ -1050,6 +1056,7 @@ TASK_LIST_START
TEST_ENTRY (fs_event_start_and_close) TEST_ENTRY (fs_event_start_and_close)
TEST_ENTRY_CUSTOM (fs_event_error_reporting, 0, 0, 60000) TEST_ENTRY_CUSTOM (fs_event_error_reporting, 0, 0, 60000)
TEST_ENTRY (fs_event_getpath) TEST_ENTRY (fs_event_getpath)
TEST_ENTRY (fs_event_stop_in_cb)
TEST_ENTRY (fs_scandir_empty_dir) TEST_ENTRY (fs_scandir_empty_dir)
TEST_ENTRY (fs_scandir_non_existent_dir) TEST_ENTRY (fs_scandir_non_existent_dir)
TEST_ENTRY (fs_scandir_file) TEST_ENTRY (fs_scandir_file)
@ -1102,6 +1109,7 @@ TASK_LIST_START
TEST_ENTRY (dlerror) TEST_ENTRY (dlerror)
TEST_ENTRY (ip4_addr) TEST_ENTRY (ip4_addr)
TEST_ENTRY (ip6_addr_link_local) TEST_ENTRY (ip6_addr_link_local)
TEST_ENTRY (ip_name)
TEST_ENTRY (queue_foreach_delete) TEST_ENTRY (queue_foreach_delete)
@ -1141,8 +1149,8 @@ TASK_LIST_START
TEST_HELPER (not_writable_after_shutdown, tcp4_echo_server) TEST_HELPER (not_writable_after_shutdown, tcp4_echo_server)
TEST_ENTRY (not_readable_nor_writable_on_read_error) TEST_ENTRY (not_readable_nor_writable_on_read_error)
TEST_HELPER (not_readable_nor_writable_on_read_error, tcp4_echo_server) TEST_HELPER (not_readable_nor_writable_on_read_error, tcp4_echo_server)
TEST_ENTRY (not_readable_on_eof) TEST_ENTRY (readable_on_eof)
TEST_HELPER (not_readable_on_eof, tcp4_echo_server) TEST_HELPER (readable_on_eof, tcp4_echo_server)
TEST_ENTRY (metrics_idle_time) TEST_ENTRY (metrics_idle_time)
TEST_ENTRY (metrics_idle_time_thread) TEST_ENTRY (metrics_idle_time_thread)

View File

@ -84,6 +84,7 @@ static void pinger_on_close(uv_handle_t* handle) {
static void pinger_after_write(uv_write_t* req, int status) { static void pinger_after_write(uv_write_t* req, int status) {
ASSERT_EQ(status, 0); ASSERT_EQ(status, 0);
free(req->data);
free(req); free(req);
} }
@ -110,6 +111,7 @@ static void pinger_write_ping(pinger_t* pinger) {
req = malloc(sizeof(*req)); req = malloc(sizeof(*req));
ASSERT_NOT_NULL(req); ASSERT_NOT_NULL(req);
req->data = NULL;
ASSERT_EQ(0, uv_write(req, stream, bufs, nbufs, pinger_after_write)); ASSERT_EQ(0, uv_write(req, stream, bufs, nbufs, pinger_after_write));
puts("PING"); puts("PING");
@ -185,6 +187,7 @@ static void ponger_read_cb(uv_stream_t* stream,
writebuf = uv_buf_init(buf->base, nread); writebuf = uv_buf_init(buf->base, nread);
req = malloc(sizeof(*req)); req = malloc(sizeof(*req));
ASSERT_NOT_NULL(req); ASSERT_NOT_NULL(req);
req->data = buf->base;
ASSERT_EQ(0, uv_write(req, stream, &writebuf, 1, pinger_after_write)); ASSERT_EQ(0, uv_write(req, stream, &writebuf, 1, pinger_after_write));
} }

View File

@ -76,9 +76,6 @@ TEST_IMPL(pipe_connect_bad_name) {
TEST_IMPL(pipe_connect_to_file) { TEST_IMPL(pipe_connect_to_file) {
#if defined(__ASAN__)
RETURN_SKIP("Test does not currently work in ASAN");
#endif
const char* path = "test/fixtures/empty_file"; const char* path = "test/fixtures/empty_file";
uv_pipe_t client; uv_pipe_t client;
uv_connect_t req; uv_connect_t req;

View File

@ -35,7 +35,7 @@ static int close_cb_called;
static void write_cb(uv_write_t* req, int status) { static void write_cb(uv_write_t* req, int status) {
write_cb_called++; write_cb_called++;
ASSERT(status == 0); ASSERT_EQ(status, 0);
} }
static void alloc_cb(uv_handle_t* handle, static void alloc_cb(uv_handle_t* handle,
@ -51,12 +51,20 @@ static void close_cb(uv_handle_t* handle) {
} }
static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) {
read_cb_called++; int r;
ASSERT(nread == UV_EOF); ASSERT_EQ(nread, UV_EOF);
ASSERT(0 == uv_is_readable(handle)); ASSERT_EQ(uv_is_readable(handle), 1);
ASSERT_EQ(uv_is_writable(handle), 1);
uv_close((uv_handle_t*) handle, close_cb); if (++read_cb_called == 3) {
uv_close((uv_handle_t*) handle, close_cb);
ASSERT_EQ(uv_is_readable(handle), 0);
ASSERT_EQ(uv_is_writable(handle), 0);
} else {
r = uv_read_start((uv_stream_t*) &tcp_client, alloc_cb, read_cb);
ASSERT_EQ(r, 0);
}
} }
static void connect_cb(uv_connect_t* req, int status) { static void connect_cb(uv_connect_t* req, int status) {
@ -64,10 +72,9 @@ static void connect_cb(uv_connect_t* req, int status) {
uv_buf_t close_me; uv_buf_t close_me;
connect_cb_called++; connect_cb_called++;
ASSERT(status == 0); ASSERT_EQ(status, 0);
r = uv_read_start((uv_stream_t*) &tcp_client, alloc_cb, read_cb); read_cb((uv_stream_t*) &tcp_client, UV_EOF, NULL);
ASSERT(r == 0);
close_me = uv_buf_init(close_me_cmd, sizeof(close_me_cmd)); close_me = uv_buf_init(close_me_cmd, sizeof(close_me_cmd));
@ -77,26 +84,27 @@ static void connect_cb(uv_connect_t* req, int status) {
1, 1,
write_cb); write_cb);
ASSERT(r == 0); ASSERT_EQ(r, 0);
} }
TEST_IMPL(not_readable_on_eof) { TEST_IMPL(readable_on_eof) {
struct sockaddr_in sa; struct sockaddr_in sa;
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &sa)); ASSERT_EQ(uv_ip4_addr("127.0.0.1", TEST_PORT, &sa), 0);
ASSERT(0 == uv_loop_init(&loop)); ASSERT_EQ(uv_loop_init(&loop), 0);
ASSERT(0 == uv_tcp_init(&loop, &tcp_client)); ASSERT_EQ(uv_tcp_init(&loop, &tcp_client), 0);
ASSERT(0 == uv_tcp_connect(&connect_req, ASSERT_EQ(uv_tcp_connect(&connect_req,
&tcp_client, &tcp_client,
(const struct sockaddr*) &sa, (const struct sockaddr*) &sa,
connect_cb)); connect_cb),
0);
ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); ASSERT_EQ(uv_run(&loop, UV_RUN_DEFAULT), 0);
ASSERT(connect_cb_called == 1); ASSERT_EQ(connect_cb_called, 1);
ASSERT(read_cb_called == 1); ASSERT_EQ(read_cb_called, 3);
ASSERT(write_cb_called == 1); ASSERT_EQ(write_cb_called, 1);
ASSERT(close_cb_called == 1); ASSERT_EQ(close_cb_called, 1);
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; return 0;

View File

@ -111,7 +111,7 @@ static int is_supported_system(void) {
if (cnt != 3) { if (cnt != 3) {
return 0; return 0;
} }
/* relase >= 10.0.16299 */ /* release >= 10.0.16299 */
for (cnt = 0; cnt < 3; ++cnt) { for (cnt = 0; cnt < 3; ++cnt) {
if (semver[cnt] > min_semver[cnt]) if (semver[cnt] > min_semver[cnt])
return 1; return 1;

View File

@ -28,6 +28,9 @@ uv_thread_t subthreads[2];
static void check_thread(void* arg) { static void check_thread(void* arg) {
uv_thread_t *thread_id = arg; uv_thread_t *thread_id = arg;
uv_thread_t self_id = uv_thread_self(); uv_thread_t self_id = uv_thread_self();
#ifdef _WIN32
ASSERT_NOT_NULL(self_id);
#endif
ASSERT(uv_thread_equal(&main_thread_id, &self_id) == 0); ASSERT(uv_thread_equal(&main_thread_id, &self_id) == 0);
*thread_id = uv_thread_self(); *thread_id = uv_thread_self();
} }
@ -35,6 +38,9 @@ static void check_thread(void* arg) {
TEST_IMPL(thread_equal) { TEST_IMPL(thread_equal) {
uv_thread_t threads[2]; uv_thread_t threads[2];
main_thread_id = uv_thread_self(); main_thread_id = uv_thread_self();
#ifdef _WIN32
ASSERT_NOT_NULL(main_thread_id);
#endif
ASSERT(0 != uv_thread_equal(&main_thread_id, &main_thread_id)); ASSERT(0 != uv_thread_equal(&main_thread_id, &main_thread_id));
ASSERT(0 == uv_thread_create(threads + 0, check_thread, subthreads + 0)); ASSERT(0 == uv_thread_create(threads + 0, check_thread, subthreads + 0));
ASSERT(0 == uv_thread_create(threads + 1, check_thread, subthreads + 1)); ASSERT(0 == uv_thread_create(threads + 1, check_thread, subthreads + 1));

View File

@ -271,7 +271,7 @@ static void make_expect_screen_erase(struct captured_screen* cs,
static void make_expect_screen_write(struct captured_screen* cs, static void make_expect_screen_write(struct captured_screen* cs,
COORD cursor_position, COORD cursor_position,
const char* text) { const char* text) {
/* postion of cursor */ /* position of cursor */
char* start; char* start;
start = cs->text + cs->si.width * (cursor_position.Y - 1) + start = cs->text + cs->si.width * (cursor_position.Y - 1) +
cursor_position.X - 1; cursor_position.X - 1;
@ -1070,6 +1070,11 @@ TEST_IMPL(tty_set_style) {
WORD attr; WORD attr;
int i, length; int i, length;
#if _MSC_VER >= 1920 && _MSC_VER <= 1929
RETURN_SKIP("Broken on Microsoft Visual Studio 2019, to be investigated. "
"See: https://github.com/libuv/libuv/issues/3304");
#endif
loop = uv_default_loop(); loop = uv_default_loop();
initialize_tty(&tty_out); initialize_tty(&tty_out);
@ -1261,7 +1266,7 @@ TEST_IMPL(tty_save_restore_cursor_position) {
cursor_pos.Y = si.height / 4; cursor_pos.Y = si.height / 4;
set_cursor_position(&tty_out, cursor_pos); set_cursor_position(&tty_out, cursor_pos);
/* restore the cursor postion */ /* restore the cursor position */
snprintf(buffer, sizeof(buffer), "%su", CSI); snprintf(buffer, sizeof(buffer), "%su", CSI);
write_console(&tty_out, buffer); write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos); get_cursor_position(&tty_out, &cursor_pos);
@ -1280,7 +1285,7 @@ TEST_IMPL(tty_save_restore_cursor_position) {
cursor_pos.Y = si.height / 4; cursor_pos.Y = si.height / 4;
set_cursor_position(&tty_out, cursor_pos); set_cursor_position(&tty_out, cursor_pos);
/* restore the cursor postion */ /* restore the cursor position */
snprintf(buffer, sizeof(buffer), "%s8", ESC); snprintf(buffer, sizeof(buffer), "%s8", ESC);
write_console(&tty_out, buffer); write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos); get_cursor_position(&tty_out, &cursor_pos);
@ -1348,6 +1353,11 @@ TEST_IMPL(tty_escape_sequence_processing) {
struct captured_screen actual = {0}, expect = {0}; struct captured_screen actual = {0}, expect = {0};
int dir; int dir;
#if _MSC_VER >= 1920 && _MSC_VER <= 1929
RETURN_SKIP("Broken on Microsoft Visual Studio 2019, to be investigated. "
"See: https://github.com/libuv/libuv/issues/3304");
#endif
loop = uv_default_loop(); loop = uv_default_loop();
initialize_tty(&tty_out); initialize_tty(&tty_out);

View File

@ -124,7 +124,7 @@ TEST_IMPL(udp_connect) {
buf = uv_buf_init("EXIT", 4); buf = uv_buf_init("EXIT", 4);
/* connect() to INADDR_ANY fails on Windows wih WSAEADDRNOTAVAIL */ /* connect() to INADDR_ANY fails on Windows with WSAEADDRNOTAVAIL */
ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &tmp_addr)); ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &tmp_addr));
r = uv_udp_connect(&client, (const struct sockaddr*) &tmp_addr); r = uv_udp_connect(&client, (const struct sockaddr*) &tmp_addr);
#ifdef _WIN32 #ifdef _WIN32

200
deps/libuv/test/test-udp-connect6.c vendored Normal file
View File

@ -0,0 +1,200 @@
/* Copyright libuv project and contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHECK_HANDLE(handle) \
ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client)
static uv_udp_t server;
static uv_udp_t client;
static uv_buf_t buf;
static struct sockaddr_in6 lo_addr;
static int cl_send_cb_called;
static int sv_recv_cb_called;
static int close_cb_called;
static void alloc_cb(uv_handle_t* handle,
size_t suggested_size,
uv_buf_t* buf) {
static char slab[65536];
CHECK_HANDLE(handle);
ASSERT_LE(suggested_size, sizeof(slab));
buf->base = slab;
buf->len = sizeof(slab);
}
static void close_cb(uv_handle_t* handle) {
CHECK_HANDLE(handle);
ASSERT(uv_is_closing(handle));
close_cb_called++;
}
static void cl_send_cb(uv_udp_send_t* req, int status) {
int r;
ASSERT_NOT_NULL(req);
ASSERT_EQ(status, 0);
CHECK_HANDLE(req->handle);
if (++cl_send_cb_called == 1) {
uv_udp_connect(&client, NULL);
r = uv_udp_send(req, &client, &buf, 1, NULL, cl_send_cb);
ASSERT_EQ(r, UV_EDESTADDRREQ);
r = uv_udp_send(req,
&client,
&buf,
1,
(const struct sockaddr*) &lo_addr,
cl_send_cb);
ASSERT_EQ(r, 0);
}
}
static void sv_recv_cb(uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* rcvbuf,
const struct sockaddr* addr,
unsigned flags) {
if (nread > 0) {
ASSERT_EQ(nread, 4);
ASSERT_NOT_NULL(addr);
ASSERT_EQ(memcmp("EXIT", rcvbuf->base, nread), 0);
if (++sv_recv_cb_called == 4) {
uv_close((uv_handle_t*) &server, close_cb);
uv_close((uv_handle_t*) &client, close_cb);
}
}
}
TEST_IMPL(udp_connect6) {
#if defined(__PASE__)
RETURN_SKIP(
"IBMi PASE's UDP connection can not be disconnected with AF_UNSPEC.");
#endif
uv_udp_send_t req;
struct sockaddr_in6 ext_addr;
struct sockaddr_in6 tmp_addr;
int r;
int addrlen;
if (!can_ipv6())
RETURN_SKIP("IPv6 not supported");
ASSERT_EQ(0, uv_ip6_addr("::", TEST_PORT, &lo_addr));
r = uv_udp_init(uv_default_loop(), &server);
ASSERT_EQ(r, 0);
r = uv_udp_bind(&server, (const struct sockaddr*) &lo_addr, 0);
ASSERT_EQ(r, 0);
r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);
ASSERT_EQ(r, 0);
r = uv_udp_init(uv_default_loop(), &client);
ASSERT_EQ(r, 0);
buf = uv_buf_init("EXIT", 4);
/* connect() to INADDR_ANY fails on Windows wih WSAEADDRNOTAVAIL */
ASSERT_EQ(0, uv_ip6_addr("::", TEST_PORT, &tmp_addr));
r = uv_udp_connect(&client, (const struct sockaddr*) &tmp_addr);
#ifdef _WIN32
ASSERT_EQ(r, UV_EADDRNOTAVAIL);
#else
ASSERT_EQ(r, 0);
r = uv_udp_connect(&client, NULL);
ASSERT_EQ(r, 0);
#endif
ASSERT_EQ(0, uv_ip6_addr("2001:4860:4860::8888", TEST_PORT, &ext_addr));
ASSERT_EQ(0, uv_ip6_addr("::1", TEST_PORT, &lo_addr));
r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);
ASSERT_EQ(r, 0);
r = uv_udp_connect(&client, (const struct sockaddr*) &ext_addr);
ASSERT_EQ(r, UV_EISCONN);
addrlen = sizeof(tmp_addr);
r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);
ASSERT_EQ(r, 0);
/* To send messages in connected UDP sockets addr must be NULL */
r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);
ASSERT_EQ(r, UV_EISCONN);
r = uv_udp_try_send(&client, &buf, 1, NULL);
ASSERT_EQ(r, 4);
r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &ext_addr);
ASSERT_EQ(r, UV_EISCONN);
r = uv_udp_connect(&client, NULL);
ASSERT_EQ(r, 0);
r = uv_udp_connect(&client, NULL);
ASSERT_EQ(r, UV_ENOTCONN);
addrlen = sizeof(tmp_addr);
r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);
ASSERT_EQ(r, UV_ENOTCONN);
/* To send messages in disconnected UDP sockets addr must be set */
r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);
ASSERT_EQ(r, 4);
r = uv_udp_try_send(&client, &buf, 1, NULL);
ASSERT_EQ(r, UV_EDESTADDRREQ);
r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);
ASSERT_EQ(r, 0);
r = uv_udp_send(&req,
&client,
&buf,
1,
(const struct sockaddr*) &lo_addr,
cl_send_cb);
ASSERT_EQ(r, UV_EISCONN);
r = uv_udp_send(&req, &client, &buf, 1, NULL, cl_send_cb);
ASSERT_EQ(r, 0);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT_EQ(close_cb_called, 2);
ASSERT_EQ(sv_recv_cb_called, 4);
ASSERT_EQ(cl_send_cb_called, 2);
ASSERT_EQ(client.send_queue_size, 0);
ASSERT_EQ(server.send_queue_size, 0);
MAKE_VALGRIND_HAPPY();
return 0;
}