libuv 1.44.2
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3934 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
parent
41afc3bdd6
commit
f06753b56e
32
deps/libuv/.github/workflows/CI-sample.yml
vendored
Normal file
32
deps/libuv/.github/workflows/CI-sample.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: ci-sample
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!.**'
|
||||
- '.github/workflows/CI-sample.yml'
|
||||
push:
|
||||
branches:
|
||||
- v[0-9].*
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: setup
|
||||
run: cmake -E make_directory ${{runner.workspace}}/libuv/docs/code/build
|
||||
- name: configure
|
||||
# you may like use Ninja on unix-like OS, but for windows, the only easy way is to use Visual Studio if you want Ninja
|
||||
run: cmake ..
|
||||
working-directory: ${{runner.workspace}}/libuv/docs/code/build
|
||||
- name: build
|
||||
run: cmake --build .
|
||||
working-directory: ${{runner.workspace}}/libuv/docs/code/build
|
129
deps/libuv/.github/workflows/CI-unix.yml
vendored
Normal file
129
deps/libuv/.github/workflows/CI-unix.yml
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
name: CI-unix
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!src/win/**'
|
||||
- '!.**'
|
||||
- '.github/workflows/CI-unix.yml'
|
||||
push:
|
||||
branches:
|
||||
- v[0-9].*
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
container: reactnativecommunity/react-native-android:2020-5-20
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Configure android arm64
|
||||
# see build options you can use in https://developer.android.com/ndk/guides/cmake
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
$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-24 ..
|
||||
- name: Build android arm64
|
||||
run: |
|
||||
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake --build build
|
||||
ls -lh 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: Configure
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DBUILD_TESTING=ON -G Ninja
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build
|
||||
ls -lh
|
||||
- name: platform_output
|
||||
run: |
|
||||
./build/uv_run_tests platform_output
|
||||
- name: platform_output_a
|
||||
run: |
|
||||
./build/uv_run_tests_a platform_output
|
||||
- name: Test
|
||||
run: |
|
||||
cd build && ctest -V
|
||||
|
||||
build-ios:
|
||||
runs-on: macos-10.15
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build-ios
|
||||
cd build-ios
|
||||
cmake .. -GXcode -DCMAKE_SYSTEM_NAME:STRING=iOS -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED:BOOL=NO -DCMAKE_CONFIGURATION_TYPES:STRING=Release
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build-ios
|
||||
ls -lh build-ios
|
||||
|
||||
build-cross-qemu:
|
||||
runs-on: ubuntu-latest
|
||||
name: build-cross-qemu-${{ matrix.config.target }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {target: arm, toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static }
|
||||
- {target: armhf, toolchain: gcc-arm-linux-gnueabihf, cc: arm-linux-gnueabihf-gcc, qemu: qemu-arm-static }
|
||||
- {target: aarch64, toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static }
|
||||
- {target: riscv64, toolchain: gcc-riscv64-linux-gnu, cc: riscv64-linux-gnu-gcc, qemu: qemu-riscv64-static }
|
||||
- {target: ppc, toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static }
|
||||
- {target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static }
|
||||
- {target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le-static }
|
||||
- {target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x-static }
|
||||
- {target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips-static }
|
||||
- {target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static }
|
||||
- {target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static }
|
||||
- {target: mips64el,toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc,qemu: qemu-mips64el-static }
|
||||
- {target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static }
|
||||
- {target: arm (u64 slots), toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static}
|
||||
- {target: aarch64 (u64 slots), toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static}
|
||||
- {target: ppc (u64 slots), toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static}
|
||||
- {target: ppc64 (u64 slots), toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install QEMU
|
||||
# this ensure install latest qemu on ubuntu, apt get version is old
|
||||
env:
|
||||
QEMU_SRC: "http://archive.ubuntu.com/ubuntu/pool/universe/q/qemu"
|
||||
QEMU_VER: "qemu-user-static_4\\.2-.*_amd64.deb$"
|
||||
run: |
|
||||
DEB=`curl -s $QEMU_SRC/ | grep -o -E 'href="([^"#]+)"' | cut -d'"' -f2 | grep $QEMU_VER | tail -1`
|
||||
wget $QEMU_SRC/$DEB
|
||||
sudo dpkg -i $DEB
|
||||
- name: Install ${{ matrix.config.toolchain }}
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install ${{ matrix.config.toolchain }} -y
|
||||
- name: Configure with ${{ matrix.config.cc }}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DBUILD_TESTING=ON -DQEMU=ON -DCMAKE_C_COMPILER=${{ matrix.config.cc }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build
|
||||
ls -lh build
|
||||
- name: Test
|
||||
run: |
|
||||
${{ matrix.config.qemu }} build/uv_run_tests_a
|
51
deps/libuv/.github/workflows/CI-win.yml
vendored
Normal file
51
deps/libuv/.github/workflows/CI-win.yml
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
name: CI-win
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!src/unix/**'
|
||||
- '!.**'
|
||||
- '.github/workflows/CI-win.yml'
|
||||
push:
|
||||
branches:
|
||||
- v[0-9].*
|
||||
- master
|
||||
|
||||
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 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: platform_output
|
||||
shell: cmd
|
||||
run: |
|
||||
build\\Debug\\uv_run_tests.exe platform_output
|
||||
- name: platform_output_a
|
||||
shell: cmd
|
||||
run: |
|
||||
build\\Debug\\uv_run_tests_a.exe platform_output
|
||||
- name: Test
|
||||
shell: cmd
|
||||
run: |
|
||||
cd build
|
||||
ctest -C Debug -V
|
23
deps/libuv/.github/workflows/sanitizer.yml
vendored
23
deps/libuv/.github/workflows/sanitizer.yml
vendored
@ -1,6 +1,16 @@
|
||||
name: Sanitizer checks
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!.**'
|
||||
- '.github/workflows/sanitizer.yml'
|
||||
push:
|
||||
branches:
|
||||
- v[0-9].*
|
||||
- master
|
||||
|
||||
jobs:
|
||||
sanitizers:
|
||||
@ -12,15 +22,20 @@ jobs:
|
||||
sudo apt-get install ninja-build
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: TSAN
|
||||
- name: TSAN Build
|
||||
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: TSAN Test
|
||||
continue-on-error: true # currently permit failures
|
||||
run: |
|
||||
./build-tsan/uv_run_tests_a
|
||||
- name: ASAN Build
|
||||
run: |
|
||||
mkdir build-asan
|
||||
(cd build-asan && cmake .. -G Ninja -DBUILD_TESTING=ON -DASAN=ON -DCMAKE_BUILD_TYPE=Debug)
|
||||
cmake --build build-asan
|
||||
- name: ASAN Test
|
||||
run: |
|
||||
./build-asan/uv_run_tests_a
|
||||
|
9
deps/libuv/AUTHORS
vendored
9
deps/libuv/AUTHORS
vendored
@ -508,3 +508,12 @@ Paul Evans <leonerd@leonerd.org.uk>
|
||||
wyckster <wyckster@hotmail.com>
|
||||
Vittore F. Scolari <vittore.scolari@gmail.com>
|
||||
roflcopter4 <15476346+roflcopter4@users.noreply.github.com>
|
||||
V-for-Vasili <vasili.skurydzin@protonmail.com>
|
||||
Denny C. Dai <dennycd@me.com>
|
||||
Hannah Shi <hannahshisfb@gmail.com>
|
||||
tuftedocelot <tuftedocelot@fastmail.fm>
|
||||
blogdaren <blogdaren@163.com>
|
||||
chucksilvers <chuq@chuq.com>
|
||||
Sergey Fedorov <vital.had@gmail.com>
|
||||
theanarkh <2923878201@qq.com>
|
||||
Samuel Cabrero <samuelcabrero@gmail.com>
|
||||
|
10
deps/libuv/CMakeLists.txt
vendored
10
deps/libuv/CMakeLists.txt
vendored
@ -125,6 +125,7 @@ set(uv_sources
|
||||
src/inet.c
|
||||
src/random.c
|
||||
src/strscpy.c
|
||||
src/strtok.c
|
||||
src/threadpool.c
|
||||
src/timer.c
|
||||
src/uv-common.c
|
||||
@ -269,6 +270,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "GNU")
|
||||
src/unix/hurd.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD")
|
||||
list(APPEND uv_defines _GNU_SOURCE)
|
||||
list(APPEND uv_libraries dl freebsd-glue)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112)
|
||||
list(APPEND uv_libraries dl rt)
|
||||
@ -458,7 +464,6 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-async-null-cb.c
|
||||
test/test-async.c
|
||||
test/test-barrier.c
|
||||
test/test-callback-order.c
|
||||
test/test-callback-stack.c
|
||||
test/test-close-fd.c
|
||||
test/test-close-order.c
|
||||
@ -557,10 +562,12 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-spawn.c
|
||||
test/test-stdio-over-pipes.c
|
||||
test/test-strscpy.c
|
||||
test/test-strtok.c
|
||||
test/test-tcp-alloc-cb-fail.c
|
||||
test/test-tcp-bind-error.c
|
||||
test/test-tcp-bind6-error.c
|
||||
test/test-tcp-close-accept.c
|
||||
test/test-tcp-close-after-read-timeout.c
|
||||
test/test-tcp-close-while-connecting.c
|
||||
test/test-tcp-close.c
|
||||
test/test-tcp-close-reset.c
|
||||
@ -574,6 +581,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-tcp-open.c
|
||||
test/test-tcp-read-stop.c
|
||||
test/test-tcp-read-stop-start.c
|
||||
test/test-tcp-rst.c
|
||||
test/test-tcp-shutdown-after-write.c
|
||||
test/test-tcp-try-write.c
|
||||
test/test-tcp-try-write-error.c
|
||||
|
130
deps/libuv/ChangeLog
vendored
130
deps/libuv/ChangeLog
vendored
@ -1,4 +1,132 @@
|
||||
2022.03.09, Version 1.44.1 (Stable)
|
||||
2022.07.12, Version 1.44.2 (Stable)
|
||||
|
||||
Changes since version 1.44.1:
|
||||
|
||||
* Add SHA to ChangeLog (Jameson Nash)
|
||||
|
||||
* aix, ibmi: handle server hang when remote sends TCP RST (V-for-Vasili)
|
||||
|
||||
* build: make CI a bit noisier (Jameson Nash)
|
||||
|
||||
* process: reset the signal mask if the fork fails (Jameson Nash)
|
||||
|
||||
* zos: implement cmpxchgi() using assembly (Shuowang (Wayne) Zhang)
|
||||
|
||||
* build: AC_SUBST for AM_CFLAGS (Claes Nästén)
|
||||
|
||||
* ibmi: Implement UDP disconnect (V-for-Vasili)
|
||||
|
||||
* doc: update active maintainers list (Ben Noordhuis)
|
||||
|
||||
* build: fix kFreeBSD build (James McCoy)
|
||||
|
||||
* build: remove Windows 2016 workflows (Darshan Sen)
|
||||
|
||||
* Revert "win,errors: remap ERROR_ACCESS_DENIED to UV_EACCES" (Darshan Sen)
|
||||
|
||||
* unix: simplify getpwuid call (Jameson Nash)
|
||||
|
||||
* build: filter CI by paths and branches (Jameson Nash)
|
||||
|
||||
* build: add iOS to macos CI (Jameson Nash)
|
||||
|
||||
* build: re-enable CI for windows changes (Jameson Nash)
|
||||
|
||||
* process,iOS: fix build breakage in process.c (Denny C. Dai)
|
||||
|
||||
* test: remove unused declarations in tcp_rst test (V-for-Vasili)
|
||||
|
||||
* core: add thread-safe strtok implementation (Guilherme Íscaro)
|
||||
|
||||
* win: fix incompatible-types warning (twosee)
|
||||
|
||||
* test: fix flaky file watcher test (Ben Noordhuis)
|
||||
|
||||
* build: fix AIX xlc autotools build (V-for-Vasili)
|
||||
|
||||
* unix,win: fix UV_RUN_ONCE + uv_idle_stop loop hang (Ben Noordhuis)
|
||||
|
||||
* win: fix unexpected ECONNRESET error on TCP socket (twosee)
|
||||
|
||||
* doc: make sample cross-platform build (gengjiawen)
|
||||
|
||||
* test: separate some static variables by test cases (Hannah Shi)
|
||||
|
||||
* sunos: fs-event callback can be called after uv_close() (Andy Fiddaman)
|
||||
|
||||
* uv: re-register interest in a file after change (Shuowang (Wayne) Zhang)
|
||||
|
||||
* uv: register UV_RENAME event for _RFIM_UNLINK (Shuowang (Wayne) Zhang)
|
||||
|
||||
* uv: register __rfim_event 156 as UV_RENAME (Shuowang (Wayne) Zhang)
|
||||
|
||||
* doc: remove smartos from supported platforms (Ben Noordhuis)
|
||||
|
||||
* macos: avoid posix_spawnp() cwd bug (Jameson Nash)
|
||||
|
||||
* release: check versions of autogen scripts are newer (Jameson Nash)
|
||||
|
||||
* test: rewrite embed test (Ben Noordhuis)
|
||||
|
||||
* openbsd: use utimensat instead of lutimes (tuftedocelot)
|
||||
|
||||
* doc: fix link to uvwget example main() function (blogdaren)
|
||||
|
||||
* unix: use MSG_CMSG_CLOEXEC where supported (Ben Noordhuis)
|
||||
|
||||
* test: remove disabled callback_order test (Ben Noordhuis)
|
||||
|
||||
* win,pipe: fix bugs with pipe resource lifetime management (Jameson Nash)
|
||||
|
||||
* loop: better align order-of-events behavior between platforms (Jameson Nash)
|
||||
|
||||
* aix,test: uv_backend_fd is not supported by poll (V-for-Vasili)
|
||||
|
||||
* kqueue: skip EVFILT_PROC when invalidating fds (chucksilvers)
|
||||
|
||||
* darwin: fix atomic-ops.h ppc64 build (Sergey Fedorov)
|
||||
|
||||
* zos: don't err when killing a zombie process (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: avoid fs event callbacks after uv_close() (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: correctly format interface addresses names (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: add uv_interface_addresses() netmask support (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: improve memory management of ip addresses (Shuowang (Wayne) Zhang)
|
||||
|
||||
* tcp,pipe: fail `bind` or `listen` after `close` (theanarkh)
|
||||
|
||||
* zos: implement uv_available_parallelism() (Shuowang (Wayne) Zhang)
|
||||
|
||||
* udp,win: fix UDP compiler warning (Jameson Nash)
|
||||
|
||||
* zos: fix early exit of epoll_wait() (Shuowang (Wayne) Zhang)
|
||||
|
||||
* unix,tcp: fix errno handling in uv__tcp_bind() (Samuel Cabrero)
|
||||
|
||||
* shutdown,unix: reduce code duplication (Jameson Nash)
|
||||
|
||||
* unix: fix c99 comments (Ben Noordhuis)
|
||||
|
||||
* unix: retry tcgetattr/tcsetattr() on EINTR (Ben Noordhuis)
|
||||
|
||||
* docs: update introduction.rst (Ikko Ashimine)
|
||||
|
||||
* unix,stream: optimize uv_shutdown() codepath (Jameson Nash)
|
||||
|
||||
* zos: delay signal handling until after normal i/o (Shuowang (Wayne) Zhang)
|
||||
|
||||
* stream: uv__drain() always needs to stop POLLOUT (Jameson Nash)
|
||||
|
||||
* unix,tcp: allow EINVAL errno from setsockopt in uv_tcp_close_reset() (Stacey
|
||||
Marshall)
|
||||
|
||||
* win,shutdown: improve how shutdown is dispatched (Jameson Nash)
|
||||
|
||||
|
||||
2022.03.09, Version 1.44.1 (Stable), e8b7eb6908a847ffbe6ab2eec7428e43a0aa53a2
|
||||
|
||||
Changes since version 1.44.0:
|
||||
|
||||
|
13
deps/libuv/MAINTAINERS.md
vendored
13
deps/libuv/MAINTAINERS.md
vendored
@ -1,10 +1,7 @@
|
||||
|
||||
# Project Maintainers
|
||||
|
||||
libuv is currently managed by the following individuals:
|
||||
|
||||
* **Anna Henningsen** ([@addaleax](https://github.com/addaleax))
|
||||
* **Bartosz Sosnowski** ([@bzoz](https://github.com/bzoz))
|
||||
* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis))
|
||||
- GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis)
|
||||
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
|
||||
@ -13,13 +10,10 @@ libuv is currently managed by the following individuals:
|
||||
- GPG key: 5735 3E0D BDAA A7E8 39B6 6A1A FF47 D5E4 AD8B 4FDC (pubkey-cjihrig-kb)
|
||||
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
|
||||
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
|
||||
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
|
||||
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
|
||||
* **Jameson Nash** ([@vtjnash](https://github.com/vtjnash))
|
||||
- GPG key: AEAD 0A4B 6867 6775 1A0E 4AEF 34A2 5FB1 2824 6514 (pubkey-vtjnash)
|
||||
- GPG key: CFBB 9CA9 A5BE AFD7 0E2B 3C5A 79A6 7C55 A367 9C8B (pubkey2022-vtjnash)
|
||||
* **Jiawen Geng** ([@gengjiawen](https://github.com/gengjiawen))
|
||||
* **John Barboza** ([@jbarz](https://github.com/jbarz))
|
||||
* **Kaoru Takanashi** ([@erw7](https://github.com/erw7))
|
||||
- GPG Key: 5804 F999 8A92 2AFB A398 47A0 7183 5090 6134 887F (pubkey-erw7)
|
||||
* **Richard Lau** ([@richardlau](https://github.com/richardlau))
|
||||
@ -29,6 +23,13 @@ libuv is currently managed by the following individuals:
|
||||
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
|
||||
- GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul)
|
||||
|
||||
## Project Maintainers emeriti
|
||||
|
||||
* **Anna Henningsen** ([@addaleax](https://github.com/addaleax))
|
||||
* **Bartosz Sosnowski** ([@bzoz](https://github.com/bzoz))
|
||||
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
|
||||
* **John Barboza** ([@jbarz](https://github.com/jbarz))
|
||||
|
||||
## Storing a maintainer key in Git
|
||||
|
||||
It's quite handy to store a maintainer's signature as a git blob, and have
|
||||
|
12
deps/libuv/Makefile.am
vendored
12
deps/libuv/Makefile.am
vendored
@ -43,7 +43,9 @@ libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/uv-data-getter-setters.c \
|
||||
src/uv-common.c \
|
||||
src/uv-common.h \
|
||||
src/version.c
|
||||
src/version.c \
|
||||
src/strtok.c \
|
||||
src/strtok.h
|
||||
|
||||
if SUNOS
|
||||
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
|
||||
@ -150,7 +152,6 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-async.c \
|
||||
test/test-async-null-cb.c \
|
||||
test/test-barrier.c \
|
||||
test/test-callback-order.c \
|
||||
test/test-callback-stack.c \
|
||||
test/test-close-fd.c \
|
||||
test/test-close-order.c \
|
||||
@ -250,11 +251,13 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-spawn.c \
|
||||
test/test-stdio-over-pipes.c \
|
||||
test/test-strscpy.c \
|
||||
test/test-strtok.c \
|
||||
test/test-tcp-alloc-cb-fail.c \
|
||||
test/test-tcp-bind-error.c \
|
||||
test/test-tcp-bind6-error.c \
|
||||
test/test-tcp-close-accept.c \
|
||||
test/test-tcp-close-while-connecting.c \
|
||||
test/test-tcp-close-after-read-timeout.c \
|
||||
test/test-tcp-close.c \
|
||||
test/test-tcp-close-reset.c \
|
||||
test/test-tcp-create-socket-early.c \
|
||||
@ -266,6 +269,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-tcp-open.c \
|
||||
test/test-tcp-read-stop.c \
|
||||
test/test-tcp-read-stop-start.c \
|
||||
test/test-tcp-rst.c \
|
||||
test/test-tcp-shutdown-after-write.c \
|
||||
test/test-tcp-unexpected-read.c \
|
||||
test/test-tcp-oob.c \
|
||||
@ -463,6 +467,10 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/hurd.c
|
||||
endif
|
||||
|
||||
if KFREEBSD
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
uvinclude_HEADERS += include/uv/linux.h
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
|
1
deps/libuv/SUPPORTED_PLATFORMS.md
vendored
1
deps/libuv/SUPPORTED_PLATFORMS.md
vendored
@ -10,7 +10,6 @@
|
||||
| IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
|
||||
| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos |
|
||||
| Linux with musl | Tier 2 | musl >= 1.0 | |
|
||||
| SmartOS | Tier 3 | >= 14.4 | |
|
||||
| Android | Tier 3 | NDK >= r15b | Android 7.0, `-DANDROID_PLATFORM=android-24` |
|
||||
| MinGW | Tier 3 | MinGW32 and MinGW-w64 | |
|
||||
| SunOS | Tier 3 | Solaris 121 and later | |
|
||||
|
35
deps/libuv/autogen.sh
vendored
35
deps/libuv/autogen.sh
vendored
@ -14,9 +14,16 @@
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
set -eu
|
||||
cd `dirname "$0"`
|
||||
|
||||
if [ "$LIBTOOLIZE" = "" ] && [ "`uname`" = "Darwin" ]; then
|
||||
if [ "${1:-dev}" == "release" ]; then
|
||||
export LIBUV_RELEASE=true
|
||||
else
|
||||
export LIBUV_RELEASE=false
|
||||
fi
|
||||
|
||||
if [ "${LIBTOOLIZE:-}" = "" ] && [ "`uname`" = "Darwin" ]; then
|
||||
LIBTOOLIZE=glibtoolize
|
||||
fi
|
||||
|
||||
@ -25,9 +32,17 @@ AUTOCONF=${AUTOCONF:-autoconf}
|
||||
AUTOMAKE=${AUTOMAKE:-automake}
|
||||
LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
|
||||
|
||||
aclocal_version=`"$ACLOCAL" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
autoconf_version=`"$AUTOCONF" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
automake_version=`"$AUTOMAKE" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
automake_version_major=`echo "$automake_version" | cut -d. -f1`
|
||||
automake_version_minor=`echo "$automake_version" | cut -d. -f2`
|
||||
libtoolize_version=`"$LIBTOOLIZE" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
|
||||
if [ $aclocal_version != $automake_version ]; then
|
||||
echo "FATAL: aclocal version appears not to be from the same as automake"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
UV_EXTRA_AUTOMAKE_FLAGS=
|
||||
if test "$automake_version_major" -gt 1 || \
|
||||
@ -39,8 +54,22 @@ fi
|
||||
echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \
|
||||
> m4/libuv-extra-automake-flags.m4
|
||||
|
||||
set -ex
|
||||
"$LIBTOOLIZE" --copy
|
||||
(set -x
|
||||
"$LIBTOOLIZE" --copy --force
|
||||
"$ACLOCAL" -I m4
|
||||
)
|
||||
if $LIBUV_RELEASE; then
|
||||
"$AUTOCONF" -o /dev/null m4/libuv-check-versions.m4
|
||||
echo "
|
||||
AC_PREREQ($autoconf_version)
|
||||
AC_INIT([libuv-release-check], [0.0])
|
||||
AM_INIT_AUTOMAKE([$automake_version])
|
||||
LT_PREREQ($libtoolize_version)
|
||||
AC_OUTPUT
|
||||
" > m4/libuv-check-versions.m4
|
||||
fi
|
||||
(
|
||||
set -x
|
||||
"$AUTOCONF"
|
||||
"$AUTOMAKE" --add-missing --copy
|
||||
)
|
||||
|
7
deps/libuv/configure.ac
vendored
7
deps/libuv/configure.ac
vendored
@ -13,7 +13,7 @@
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([libuv], [1.44.1], [https://github.com/libuv/libuv/issues])
|
||||
AC_INIT([libuv], [1.44.2], [https://github.com/libuv/libuv/issues])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
m4_include([m4/libuv-extra-automake-flags.m4])
|
||||
m4_include([m4/as_case.m4])
|
||||
@ -28,7 +28,9 @@ AM_PROG_CC_C_O
|
||||
CC_ATTRIBUTE_VISIBILITY([default], [
|
||||
CC_FLAG_VISIBILITY([CFLAGS="${CFLAGS} -fvisibility=hidden"])
|
||||
])
|
||||
CC_CHECK_CFLAGS_APPEND([-fno-strict-aliasing])
|
||||
# Xlc has a flag "-f<filename>". Need to use CC_CHECK_FLAG_SUPPORTED_APPEND so
|
||||
# we exclude -fno-strict-aliasing for xlc
|
||||
CC_CHECK_FLAG_SUPPORTED_APPEND([-fno-strict-aliasing])
|
||||
CC_CHECK_CFLAGS_APPEND([-g])
|
||||
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wall])
|
||||
@ -60,6 +62,7 @@ AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])
|
||||
AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])])
|
||||
AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])])
|
||||
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([KFREEBSD], [AS_CASE([$host_os],[kfreebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([HAIKU], [AS_CASE([$host_os],[haiku], [true], [false])])
|
||||
AM_CONDITIONAL([HURD], [AS_CASE([$host_os],[gnu*], [true], [false])])
|
||||
AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])])
|
||||
|
51
deps/libuv/docs/code/CMakeLists.txt
vendored
Normal file
51
deps/libuv/docs/code/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(libuv_sample)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
add_subdirectory("../../" build)
|
||||
|
||||
set(SIMPLE_SAMPLES
|
||||
cgi
|
||||
helloworld
|
||||
dns
|
||||
detach
|
||||
default-loop
|
||||
idle-basic
|
||||
idle-compute
|
||||
interfaces
|
||||
locks
|
||||
onchange
|
||||
pipe-echo-server
|
||||
ref-timer
|
||||
spawn
|
||||
tcp-echo-server
|
||||
thread-create
|
||||
udp-dhcp
|
||||
uvcat
|
||||
uvstop
|
||||
uvtee
|
||||
)
|
||||
IF (NOT WIN32)
|
||||
list(APPEND SIMPLE_SAMPLES
|
||||
signal
|
||||
progress
|
||||
queue-cancel
|
||||
queue-work
|
||||
tty
|
||||
tty-gravity
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
foreach (X IN LISTS SIMPLE_SAMPLES)
|
||||
add_executable(${X} ${X}/main.c)
|
||||
target_link_libraries(${X} uv_a)
|
||||
endforeach ()
|
||||
|
||||
|
||||
FIND_PACKAGE(CURL)
|
||||
IF(CURL_FOUND)
|
||||
add_executable(uvwget uvwget/main.c)
|
||||
target_link_libraries(uvwget uv_a ${CURL_LIBRARIES})
|
||||
ENDIF(CURL_FOUND)
|
4
deps/libuv/docs/code/cgi/main.c
vendored
4
deps/libuv/docs/code/cgi/main.c
vendored
@ -15,8 +15,8 @@ void cleanup_handles(uv_process_t *req, int64_t exit_status, int term_signal) {
|
||||
}
|
||||
|
||||
void invoke_cgi_script(uv_tcp_t *client) {
|
||||
size_t size = 500;
|
||||
char path[size];
|
||||
char path[500];
|
||||
size_t size = sizeof(path);
|
||||
uv_exepath(path, &size);
|
||||
strcpy(path + (strlen(path) - strlen("cgi")), "tick");
|
||||
|
||||
|
14
deps/libuv/docs/code/interfaces/main.c
vendored
14
deps/libuv/docs/code/interfaces/main.c
vendored
@ -11,17 +11,17 @@ int main() {
|
||||
|
||||
printf("Number of interfaces: %d\n", count);
|
||||
while (i--) {
|
||||
uv_interface_address_t interface = info[i];
|
||||
uv_interface_address_t interface_a = info[i];
|
||||
|
||||
printf("Name: %s\n", interface.name);
|
||||
printf("Internal? %s\n", interface.is_internal ? "Yes" : "No");
|
||||
printf("Name: %s\n", interface_a.name);
|
||||
printf("Internal? %s\n", interface_a.is_internal ? "Yes" : "No");
|
||||
|
||||
if (interface.address.address4.sin_family == AF_INET) {
|
||||
uv_ip4_name(&interface.address.address4, buf, sizeof(buf));
|
||||
if (interface_a.address.address4.sin_family == AF_INET) {
|
||||
uv_ip4_name(&interface_a.address.address4, buf, sizeof(buf));
|
||||
printf("IPv4 address: %s\n", buf);
|
||||
}
|
||||
else if (interface.address.address4.sin_family == AF_INET6) {
|
||||
uv_ip6_name(&interface.address.address6, buf, sizeof(buf));
|
||||
else if (interface_a.address.address4.sin_family == AF_INET6) {
|
||||
uv_ip6_name(&interface_a.address.address6, buf, sizeof(buf));
|
||||
printf("IPv6 address: %s\n", buf);
|
||||
}
|
||||
|
||||
|
5
deps/libuv/docs/code/thread-create/main.c
vendored
5
deps/libuv/docs/code/thread-create/main.c
vendored
@ -1,5 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
@ -7,7 +6,7 @@ void hare(void *arg) {
|
||||
int tracklen = *((int *) arg);
|
||||
while (tracklen) {
|
||||
tracklen--;
|
||||
sleep(1);
|
||||
uv_sleep(1000);
|
||||
fprintf(stderr, "Hare ran another step\n");
|
||||
}
|
||||
fprintf(stderr, "Hare done running!\n");
|
||||
@ -18,7 +17,7 @@ void tortoise(void *arg) {
|
||||
while (tracklen) {
|
||||
tracklen--;
|
||||
fprintf(stderr, "Tortoise ran another step\n");
|
||||
sleep(3);
|
||||
uv_sleep(3000);
|
||||
}
|
||||
fprintf(stderr, "Tortoise done running!\n");
|
||||
}
|
||||
|
3
deps/libuv/docs/code/udp-dhcp/main.c
vendored
3
deps/libuv/docs/code/udp-dhcp/main.c
vendored
@ -53,7 +53,8 @@ uv_buf_t make_discover_msg() {
|
||||
// HOPS
|
||||
buffer.base[3] = 0x0;
|
||||
// XID 4 bytes
|
||||
buffer.base[4] = (unsigned int) random();
|
||||
if (uv_random(NULL, NULL, &buffer.base[4], 4, 0, NULL))
|
||||
abort();
|
||||
// SECS
|
||||
buffer.base[8] = 0x0;
|
||||
// FLAGS
|
||||
|
1
deps/libuv/docs/code/uvcat/main.c
vendored
1
deps/libuv/docs/code/uvcat/main.c
vendored
@ -1,7 +1,6 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <uv.h>
|
||||
|
||||
void on_read(uv_fs_t *req);
|
||||
|
1
deps/libuv/docs/code/uvtee/main.c
vendored
1
deps/libuv/docs/code/uvtee/main.c
vendored
@ -1,6 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
2
deps/libuv/docs/src/guide/introduction.rst
vendored
2
deps/libuv/docs/src/guide/introduction.rst
vendored
@ -53,7 +53,7 @@ Code
|
||||
----
|
||||
|
||||
All the example code and the source of the book is included as part of
|
||||
the libuv_ project on Github.
|
||||
the libuv_ project on GitHub.
|
||||
Clone or Download libuv_, then build it::
|
||||
|
||||
sh autogen.sh
|
||||
|
2
deps/libuv/docs/src/guide/utilities.rst
vendored
2
deps/libuv/docs/src/guide/utilities.rst
vendored
@ -220,7 +220,7 @@ progress with the download whenever libuv notifies of I/O readiness.
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 1-9,140-
|
||||
:lines: 1-9,142-
|
||||
:emphasize-lines: 7,21,24-25
|
||||
|
||||
The way each library is integrated with libuv will vary. In the case of
|
||||
|
2
deps/libuv/include/uv/version.h
vendored
2
deps/libuv/include/uv/version.h
vendored
@ -32,7 +32,7 @@
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 44
|
||||
#define UV_VERSION_PATCH 1
|
||||
#define UV_VERSION_PATCH 2
|
||||
#define UV_VERSION_IS_RELEASE 1
|
||||
#define UV_VERSION_SUFFIX ""
|
||||
|
||||
|
6
deps/libuv/include/uv/win.h
vendored
6
deps/libuv/include/uv/win.h
vendored
@ -377,6 +377,12 @@ typedef struct {
|
||||
OVERLAPPED overlapped; \
|
||||
size_t queued_bytes; \
|
||||
} io; \
|
||||
/* in v2, we can move these to the UV_CONNECT_PRIVATE_FIELDS */ \
|
||||
struct { \
|
||||
ULONG_PTR result; /* overlapped.Internal is reused to hold the result */\
|
||||
HANDLE pipeHandle; \
|
||||
DWORD duplex_flags; \
|
||||
} connect; \
|
||||
} u; \
|
||||
struct uv_req_s* next_req;
|
||||
|
||||
|
16
deps/libuv/m4/libuv-check-flags.m4
vendored
16
deps/libuv/m4/libuv-check-flags.m4
vendored
@ -73,6 +73,8 @@ AC_DEFUN([CC_CHECK_CFLAG_APPEND], [
|
||||
|
||||
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
|
||||
[AM_CFLAGS="$AM_CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3])
|
||||
|
||||
AC_SUBST([AM_CFLAGS])
|
||||
])
|
||||
|
||||
dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not])
|
||||
@ -102,6 +104,20 @@ AC_DEFUN([CC_CHECK_LDFLAGS], [
|
||||
[$2], [$3])
|
||||
])
|
||||
|
||||
dnl Check if flag is supported by both compiler and linker
|
||||
dnl If so, append it to AM_CFLAGS
|
||||
dnl CC_CHECK_FLAG_SUPPORTED_APPEND([FLAG])
|
||||
|
||||
AC_DEFUN([CC_CHECK_FLAG_SUPPORTED_APPEND], [
|
||||
CC_CHECK_CFLAGS([$1],
|
||||
[CC_CHECK_LDFLAGS([$1],
|
||||
[AM_CFLAGS="$AM_CFLAGS $1";
|
||||
DEBUG_CFLAGS="$DEBUG_CFLAGS $1";
|
||||
AC_SUBST([AM_CFLAGS])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
|
||||
dnl the current linker to avoid undefined references in a shared object.
|
||||
AC_DEFUN([CC_NOUNDEFINED], [
|
||||
|
7
deps/libuv/m4/libuv-check-versions.m4
vendored
Normal file
7
deps/libuv/m4/libuv-check-versions.m4
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
AC_PREREQ(2.71)
|
||||
AC_INIT([libuv-release-check], [0.0])
|
||||
AM_INIT_AUTOMAKE([1.16.5])
|
||||
LT_PREREQ(2.4.7)
|
||||
AC_OUTPUT
|
||||
|
52
deps/libuv/src/strtok.c
vendored
Normal file
52
deps/libuv/src/strtok.c
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "strtok.h"
|
||||
|
||||
char* uv__strtok(char* str, const char* sep, char** itr) {
|
||||
const char* sep_itr;
|
||||
char* tmp;
|
||||
char* start;
|
||||
|
||||
if (str == NULL)
|
||||
start = tmp = *itr;
|
||||
else
|
||||
start = tmp = str;
|
||||
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
|
||||
while (*tmp != '\0') {
|
||||
sep_itr = sep;
|
||||
while (*sep_itr != '\0') {
|
||||
if (*tmp == *sep_itr) {
|
||||
*itr = tmp + 1;
|
||||
*tmp = '\0';
|
||||
return start;
|
||||
}
|
||||
sep_itr++;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
*itr = NULL;
|
||||
return start;
|
||||
}
|
27
deps/libuv/src/strtok.h
vendored
Normal file
27
deps/libuv/src/strtok.h
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_STRTOK_H_
|
||||
#define UV_STRTOK_H_
|
||||
|
||||
char* uv__strtok(char* str, const char* sep, char** itr);
|
||||
|
||||
#endif /* UV_STRTOK_H_ */
|
15
deps/libuv/src/unix/atomic-ops.h
vendored
15
deps/libuv/src/unix/atomic-ops.h
vendored
@ -37,12 +37,11 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
|
||||
: "memory");
|
||||
return out;
|
||||
#elif defined(__MVS__)
|
||||
unsigned int op4;
|
||||
if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
|
||||
(unsigned int*) ptr, *ptr, &op4))
|
||||
return oldval;
|
||||
else
|
||||
return op4;
|
||||
/* Use hand-rolled assembly because codegen from builtin __plo_CSST results in
|
||||
* a runtime bug.
|
||||
*/
|
||||
__asm(" cs %0,%2,%1 \n " : "+r"(oldval), "+m"(*ptr) : "r"(newval) :);
|
||||
return oldval;
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
|
||||
#else
|
||||
@ -55,7 +54,9 @@ UV_UNUSED(static void cpu_relax(void)) {
|
||||
__asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */
|
||||
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||
__asm__ __volatile__ ("yield" ::: "memory");
|
||||
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
|
||||
#elif (defined(__ppc__) || defined(__ppc64__)) && defined(__APPLE__)
|
||||
__asm volatile ("" : : : "memory");
|
||||
#elif !defined(__APPLE__) && (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__))
|
||||
__asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
110
deps/libuv/src/unix/core.c
vendored
110
deps/libuv/src/unix/core.c
vendored
@ -20,6 +20,7 @@
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include "strtok.h"
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdio.h> /* printf */
|
||||
@ -80,7 +81,8 @@ extern char** environ;
|
||||
#endif
|
||||
|
||||
#if defined(__MVS__)
|
||||
#include <sys/ioctl.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include "zos-sys-info.h"
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
@ -93,7 +95,7 @@ extern char** environ;
|
||||
# include <sanitizer/linux_syscall_hooks.h>
|
||||
#endif
|
||||
|
||||
static int uv__run_pending(uv_loop_t* loop);
|
||||
static void uv__run_pending(uv_loop_t* loop);
|
||||
|
||||
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
|
||||
STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec));
|
||||
@ -159,6 +161,15 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
||||
|
||||
case UV_FS_EVENT:
|
||||
uv__fs_event_close((uv_fs_event_t*)handle);
|
||||
#if defined(__sun) || defined(__MVS__)
|
||||
/*
|
||||
* On Solaris, illumos, and z/OS we will not be able to dissociate the
|
||||
* watcher for an event which is pending delivery, so we cannot always call
|
||||
* uv__make_close_pending() straight away. The backend will call the
|
||||
* function once the event has cleared.
|
||||
*/
|
||||
return;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case UV_POLL:
|
||||
@ -371,7 +382,7 @@ int uv_loop_alive(const uv_loop_t* loop) {
|
||||
int uv_run(uv_loop_t* loop, uv_run_mode mode) {
|
||||
int timeout;
|
||||
int r;
|
||||
int ran_pending;
|
||||
int can_sleep;
|
||||
|
||||
r = uv__loop_alive(loop);
|
||||
if (!r)
|
||||
@ -380,16 +391,25 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
|
||||
while (r != 0 && loop->stop_flag == 0) {
|
||||
uv__update_time(loop);
|
||||
uv__run_timers(loop);
|
||||
ran_pending = uv__run_pending(loop);
|
||||
|
||||
can_sleep =
|
||||
QUEUE_EMPTY(&loop->pending_queue) && QUEUE_EMPTY(&loop->idle_handles);
|
||||
|
||||
uv__run_pending(loop);
|
||||
uv__run_idle(loop);
|
||||
uv__run_prepare(loop);
|
||||
|
||||
timeout = 0;
|
||||
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
|
||||
if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT)
|
||||
timeout = uv__backend_timeout(loop);
|
||||
|
||||
uv__io_poll(loop, timeout);
|
||||
|
||||
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
|
||||
* times to avoid loop starvation.*/
|
||||
for (r = 0; r < 8 && !QUEUE_EMPTY(&loop->pending_queue); r++)
|
||||
uv__run_pending(loop);
|
||||
|
||||
/* Run one final update on the provider_idle_time in case uv__io_poll
|
||||
* returned because the timeout expired, but no events were received. This
|
||||
* call will be ignored if the provider_entry_time was either never set (if
|
||||
@ -653,28 +673,23 @@ int uv__cloexec(int fd, int set) {
|
||||
|
||||
|
||||
ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
|
||||
struct cmsghdr* cmsg;
|
||||
#if defined(__ANDROID__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__linux__)
|
||||
ssize_t rc;
|
||||
rc = recvmsg(fd, msg, flags | MSG_CMSG_CLOEXEC);
|
||||
if (rc == -1)
|
||||
return UV__ERR(errno);
|
||||
return rc;
|
||||
#else
|
||||
struct cmsghdr* cmsg;
|
||||
int* pfd;
|
||||
int* end;
|
||||
#if defined(__linux__)
|
||||
static int no_msg_cmsg_cloexec;
|
||||
if (0 == uv__load_relaxed(&no_msg_cmsg_cloexec)) {
|
||||
rc = recvmsg(fd, msg, flags | 0x40000000); /* MSG_CMSG_CLOEXEC */
|
||||
if (rc != -1)
|
||||
return rc;
|
||||
if (errno != EINVAL)
|
||||
return UV__ERR(errno);
|
||||
rc = recvmsg(fd, msg, flags);
|
||||
if (rc == -1)
|
||||
return UV__ERR(errno);
|
||||
uv__store_relaxed(&no_msg_cmsg_cloexec, 1);
|
||||
} else {
|
||||
rc = recvmsg(fd, msg, flags);
|
||||
}
|
||||
#else
|
||||
ssize_t rc;
|
||||
rc = recvmsg(fd, msg, flags);
|
||||
#endif
|
||||
if (rc == -1)
|
||||
return UV__ERR(errno);
|
||||
if (msg->msg_controllen == 0)
|
||||
@ -687,6 +702,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
|
||||
pfd += 1)
|
||||
uv__cloexec(*pfd, 1);
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -779,14 +795,11 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
|
||||
}
|
||||
|
||||
|
||||
static int uv__run_pending(uv_loop_t* loop) {
|
||||
static void uv__run_pending(uv_loop_t* loop) {
|
||||
QUEUE* q;
|
||||
QUEUE pq;
|
||||
uv__io_t* w;
|
||||
|
||||
if (QUEUE_EMPTY(&loop->pending_queue))
|
||||
return 0;
|
||||
|
||||
QUEUE_MOVE(&loop->pending_queue, &pq);
|
||||
|
||||
while (!QUEUE_EMPTY(&pq)) {
|
||||
@ -796,8 +809,6 @@ static int uv__run_pending(uv_loop_t* loop) {
|
||||
w = QUEUE_DATA(q, uv__io_t, pending_queue);
|
||||
w->cb(loop, w, POLLOUT);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -1162,24 +1173,17 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
size_t name_size;
|
||||
size_t homedir_size;
|
||||
size_t shell_size;
|
||||
long initsize;
|
||||
int r;
|
||||
|
||||
if (pwd == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
|
||||
if (initsize <= 0)
|
||||
bufsize = 4096;
|
||||
else
|
||||
bufsize = (size_t) initsize;
|
||||
|
||||
uid = geteuid();
|
||||
buf = NULL;
|
||||
|
||||
for (;;) {
|
||||
uv__free(buf);
|
||||
/* Calling sysconf(_SC_GETPW_R_SIZE_MAX) would get the suggested size, but it
|
||||
* is frequently 1024 or 4096, so we can just use that directly. The pwent
|
||||
* will not usually be large. */
|
||||
for (bufsize = 2000;; bufsize *= 2) {
|
||||
buf = uv__malloc(bufsize);
|
||||
|
||||
if (buf == NULL)
|
||||
@ -1189,21 +1193,18 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
|
||||
while (r == EINTR);
|
||||
|
||||
if (r != 0 || result == NULL)
|
||||
uv__free(buf);
|
||||
|
||||
if (r != ERANGE)
|
||||
break;
|
||||
|
||||
bufsize *= 2;
|
||||
}
|
||||
|
||||
if (r != 0) {
|
||||
uv__free(buf);
|
||||
if (r != 0)
|
||||
return UV__ERR(r);
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
uv__free(buf);
|
||||
if (result == NULL)
|
||||
return UV_ENOENT;
|
||||
}
|
||||
|
||||
/* Allocate memory for the username, shell, and home directory */
|
||||
name_size = strlen(pw.pw_name) + 1;
|
||||
@ -1556,6 +1557,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
|
||||
char* cloned_path;
|
||||
char* path_env;
|
||||
char* token;
|
||||
char* itr;
|
||||
|
||||
if (buf == NULL || buflen == NULL || *buflen == 0)
|
||||
return UV_EINVAL;
|
||||
@ -1597,7 +1599,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
|
||||
if (cloned_path == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
token = strtok(cloned_path, ":");
|
||||
token = uv__strtok(cloned_path, ":", &itr);
|
||||
while (token != NULL) {
|
||||
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, prog);
|
||||
if (realpath(trypath, abspath) == abspath) {
|
||||
@ -1616,7 +1618,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
token = uv__strtok(NULL, ":", &itr);
|
||||
}
|
||||
uv__free(cloned_path);
|
||||
|
||||
@ -1646,7 +1648,13 @@ unsigned int uv_available_parallelism(void) {
|
||||
|
||||
return (unsigned) rc;
|
||||
#elif defined(__MVS__)
|
||||
return 1; /* TODO(bnoordhuis) Read from CSD_NUMBER_ONLINE_CPUS? */
|
||||
int rc;
|
||||
|
||||
rc = __get_num_online_cpus();
|
||||
if (rc < 1)
|
||||
rc = 1;
|
||||
|
||||
return (unsigned) rc;
|
||||
#else /* __linux__ */
|
||||
long rc;
|
||||
|
||||
|
3
deps/libuv/src/unix/fs.c
vendored
3
deps/libuv/src/unix/fs.c
vendored
@ -1181,7 +1181,8 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) {
|
||||
defined(_AIX71) || \
|
||||
defined(__sun) || \
|
||||
defined(__HAIKU__) || \
|
||||
defined(__GNU__)
|
||||
defined(__GNU__) || \
|
||||
defined(__OpenBSD__)
|
||||
struct timespec ts[2];
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
|
1
deps/libuv/src/unix/internal.h
vendored
1
deps/libuv/src/unix/internal.h
vendored
@ -277,7 +277,6 @@ void uv__tcp_close(uv_tcp_t* handle);
|
||||
size_t uv__thread_stack_size(void);
|
||||
void uv__udp_close(uv_udp_t* handle);
|
||||
void uv__udp_finish_close(uv_udp_t* handle);
|
||||
uv_handle_type uv__handle_type(int fd);
|
||||
FILE* uv__open_file(const char* path);
|
||||
int uv__getpwuid_r(uv_passwd_t* pwd);
|
||||
int uv__search_path(const char* prog, char* buf, size_t* buflen);
|
||||
|
2
deps/libuv/src/unix/kqueue.c
vendored
2
deps/libuv/src/unix/kqueue.c
vendored
@ -456,7 +456,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
||||
|
||||
/* Invalidate events with same file descriptor */
|
||||
for (i = 0; i < nfds; i++)
|
||||
if ((int) events[i].ident == fd)
|
||||
if ((int) events[i].ident == fd && events[i].filter != EVFILT_PROC)
|
||||
events[i].ident = -1;
|
||||
}
|
||||
|
||||
|
36
deps/libuv/src/unix/os390-syscalls.c
vendored
36
deps/libuv/src/unix/os390-syscalls.c
vendored
@ -284,6 +284,8 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
|
||||
nmsgsfds_t size;
|
||||
struct pollfd* pfds;
|
||||
int pollret;
|
||||
int pollfdret;
|
||||
int pollmsgret;
|
||||
int reventcount;
|
||||
int nevents;
|
||||
struct pollfd msg_fd;
|
||||
@ -304,24 +306,24 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lst->size > 0)
|
||||
_SET_FDS_MSGS(size, 1, lst->size - 1);
|
||||
else
|
||||
_SET_FDS_MSGS(size, 0, 0);
|
||||
assert(lst->size > 0);
|
||||
_SET_FDS_MSGS(size, 1, lst->size - 1);
|
||||
pfds = lst->items;
|
||||
pollret = poll(pfds, size, timeout);
|
||||
if (pollret <= 0)
|
||||
return pollret;
|
||||
|
||||
assert(lst->size > 0);
|
||||
|
||||
pollret = _NFDS(pollret) + _NMSGS(pollret);
|
||||
pollfdret = _NFDS(pollret);
|
||||
pollmsgret = _NMSGS(pollret);
|
||||
|
||||
reventcount = 0;
|
||||
nevents = 0;
|
||||
msg_fd = pfds[lst->size - 1];
|
||||
msg_fd = pfds[lst->size - 1]; /* message queue is always last entry */
|
||||
maxevents = maxevents - pollmsgret; /* allow spot for message queue */
|
||||
for (i = 0;
|
||||
i < lst->size && i < maxevents && reventcount < pollret; ++i) {
|
||||
i < lst->size - 1 &&
|
||||
nevents < maxevents &&
|
||||
reventcount < pollfdret; ++i) {
|
||||
struct epoll_event ev;
|
||||
struct pollfd* pfd;
|
||||
|
||||
@ -332,18 +334,18 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
|
||||
ev.fd = pfd->fd;
|
||||
ev.events = pfd->revents;
|
||||
ev.is_msg = 0;
|
||||
if (pfd->revents & POLLIN && pfd->revents & POLLOUT)
|
||||
reventcount += 2;
|
||||
else if (pfd->revents & (POLLIN | POLLOUT))
|
||||
++reventcount;
|
||||
|
||||
pfd->revents = 0;
|
||||
reventcount++;
|
||||
events[nevents++] = ev;
|
||||
}
|
||||
|
||||
if (msg_fd.revents != 0 && msg_fd.fd != -1)
|
||||
if (i == lst->size)
|
||||
events[nevents - 1].is_msg = 1;
|
||||
if (pollmsgret > 0 && msg_fd.revents != 0 && msg_fd.fd != -1) {
|
||||
struct epoll_event ev;
|
||||
ev.fd = msg_fd.fd;
|
||||
ev.events = msg_fd.revents;
|
||||
ev.is_msg = 1;
|
||||
events[nevents++] = ev;
|
||||
}
|
||||
|
||||
return nevents;
|
||||
}
|
||||
|
297
deps/libuv/src/unix/os390.c
vendored
297
deps/libuv/src/unix/os390.c
vendored
@ -278,7 +278,9 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
|
||||
__net_ifconf6header_t ifc;
|
||||
__net_ifconf6entry_t* ifr;
|
||||
__net_ifconf6entry_t* p;
|
||||
__net_ifconf6entry_t flg;
|
||||
unsigned int i;
|
||||
int count_names;
|
||||
unsigned char netmask[16] = {0};
|
||||
|
||||
*count = 0;
|
||||
/* Assume maximum buffer size allowable */
|
||||
@ -287,24 +289,33 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
|
||||
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
|
||||
return UV__ERR(errno);
|
||||
|
||||
ifc.__nif6h_version = 1;
|
||||
ifc.__nif6h_buflen = maxsize;
|
||||
ifc.__nif6h_buffer = uv__calloc(1, maxsize);;
|
||||
ifc.__nif6h_buffer = uv__calloc(1, maxsize);
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
|
||||
if (ifc.__nif6h_buffer == NULL) {
|
||||
uv__close(sockfd);
|
||||
return UV__ERR(errno);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
ifc.__nif6h_version = 1;
|
||||
ifc.__nif6h_buflen = maxsize;
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
|
||||
/* This will error on a system that does not support IPv6. However, we want
|
||||
* to treat this as there being 0 interfaces so we can continue to get IPv4
|
||||
* interfaces in uv_interface_addresses(). So return 0 instead of the error.
|
||||
*/
|
||||
uv__free(ifc.__nif6h_buffer);
|
||||
uv__close(sockfd);
|
||||
errno = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*count = 0;
|
||||
ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
|
||||
while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
|
||||
p = ifr;
|
||||
ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
|
||||
|
||||
if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
|
||||
p->__nif6e_addr.sin6_family == AF_INET))
|
||||
if (!(p->__nif6e_addr.sin6_family == AF_INET6))
|
||||
continue;
|
||||
|
||||
if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
|
||||
@ -313,21 +324,28 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
|
||||
++(*count);
|
||||
}
|
||||
|
||||
if ((*count) == 0) {
|
||||
uv__free(ifc.__nif6h_buffer);
|
||||
uv__close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Alloc the return interface structs */
|
||||
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
|
||||
*addresses = uv__calloc(1, *count * sizeof(uv_interface_address_t));
|
||||
if (!(*addresses)) {
|
||||
uv__free(ifc.__nif6h_buffer);
|
||||
uv__close(sockfd);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
address = *addresses;
|
||||
|
||||
count_names = 0;
|
||||
ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
|
||||
while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
|
||||
p = ifr;
|
||||
ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
|
||||
|
||||
if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
|
||||
p->__nif6e_addr.sin6_family == AF_INET))
|
||||
if (!(p->__nif6e_addr.sin6_family == AF_INET6))
|
||||
continue;
|
||||
|
||||
if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
|
||||
@ -335,20 +353,41 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
|
||||
|
||||
/* All conditions above must match count loop */
|
||||
|
||||
address->name = uv__strdup(p->__nif6e_name);
|
||||
i = 0;
|
||||
/* Ignore EBCDIC space (0x40) padding in name */
|
||||
while (i < ARRAY_SIZE(p->__nif6e_name) &&
|
||||
p->__nif6e_name[i] != 0x40 &&
|
||||
p->__nif6e_name[i] != 0)
|
||||
++i;
|
||||
address->name = uv__malloc(i + 1);
|
||||
if (address->name == NULL) {
|
||||
uv_free_interface_addresses(*addresses, count_names);
|
||||
uv__free(ifc.__nif6h_buffer);
|
||||
uv__close(sockfd);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
memcpy(address->name, p->__nif6e_name, i);
|
||||
address->name[i] = '\0';
|
||||
__e2a_s(address->name);
|
||||
count_names++;
|
||||
|
||||
if (p->__nif6e_addr.sin6_family == AF_INET6)
|
||||
address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr);
|
||||
else
|
||||
address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr);
|
||||
address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr);
|
||||
|
||||
/* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
|
||||
for (i = 0; i < (p->__nif6e_prefixlen / 8); i++)
|
||||
netmask[i] = 0xFF;
|
||||
|
||||
address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
|
||||
memset(address->phys_addr, 0, sizeof(address->phys_addr));
|
||||
if (p->__nif6e_prefixlen % 8)
|
||||
netmask[i] = 0xFF << (8 - (p->__nif6e_prefixlen % 8));
|
||||
|
||||
address->netmask.netmask6.sin6_len = p->__nif6e_prefixlen;
|
||||
memcpy(&(address->netmask.netmask6.sin6_addr), netmask, 16);
|
||||
address->netmask.netmask6.sin6_family = AF_INET6;
|
||||
|
||||
address->is_internal = p->__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
|
||||
address++;
|
||||
}
|
||||
|
||||
uv__free(ifc.__nif6h_buffer);
|
||||
uv__close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
@ -362,14 +401,18 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
struct ifreq flg;
|
||||
struct ifreq* ifr;
|
||||
struct ifreq* p;
|
||||
uv_interface_address_t* addresses_v6;
|
||||
int count_v6;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
int count_names;
|
||||
|
||||
*count = 0;
|
||||
*addresses = NULL;
|
||||
|
||||
/* get the ipv6 addresses first */
|
||||
uv_interface_address_t* addresses_v6;
|
||||
uv__interface_addresses_v6(&addresses_v6, &count_v6);
|
||||
if ((rc = uv__interface_addresses_v6(&addresses_v6, &count_v6)) != 0)
|
||||
return rc;
|
||||
|
||||
/* now get the ipv4 addresses */
|
||||
|
||||
@ -377,12 +420,27 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
maxsize = 16384;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (0 > sockfd)
|
||||
if (0 > sockfd) {
|
||||
if (count_v6)
|
||||
uv_free_interface_addresses(addresses_v6, count_v6);
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
|
||||
ifc.ifc_req = uv__calloc(1, maxsize);
|
||||
|
||||
if (ifc.ifc_req == NULL) {
|
||||
if (count_v6)
|
||||
uv_free_interface_addresses(addresses_v6, count_v6);
|
||||
uv__close(sockfd);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
ifc.ifc_len = maxsize;
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
|
||||
if (count_v6)
|
||||
uv_free_interface_addresses(addresses_v6, count_v6);
|
||||
uv__free(ifc.ifc_req);
|
||||
uv__close(sockfd);
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
@ -403,6 +461,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
|
||||
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
||||
if (count_v6)
|
||||
uv_free_interface_addresses(addresses_v6, count_v6);
|
||||
uv__free(ifc.ifc_req);
|
||||
uv__close(sockfd);
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
@ -413,27 +474,35 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
if (*count == 0) {
|
||||
if (*count == 0 && count_v6 == 0) {
|
||||
uv__free(ifc.ifc_req);
|
||||
uv__close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Alloc the return interface structs */
|
||||
*addresses = uv__malloc((*count + count_v6) *
|
||||
*addresses = uv__calloc(1, (*count + count_v6) *
|
||||
sizeof(uv_interface_address_t));
|
||||
|
||||
if (!(*addresses)) {
|
||||
if (count_v6)
|
||||
uv_free_interface_addresses(addresses_v6, count_v6);
|
||||
uv__free(ifc.ifc_req);
|
||||
uv__close(sockfd);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
address = *addresses;
|
||||
|
||||
/* copy over the ipv6 addresses */
|
||||
memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t));
|
||||
address += count_v6;
|
||||
*count += count_v6;
|
||||
uv__free(addresses_v6);
|
||||
/* copy over the ipv6 addresses if any are found */
|
||||
if (count_v6) {
|
||||
memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t));
|
||||
address += count_v6;
|
||||
*count += count_v6;
|
||||
/* free ipv6 addresses, but keep address names */
|
||||
uv__free(addresses_v6);
|
||||
}
|
||||
|
||||
count_names = *count;
|
||||
ifr = ifc.ifc_req;
|
||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||
p = ifr;
|
||||
@ -446,6 +515,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
|
||||
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
||||
uv_free_interface_addresses(*addresses, count_names);
|
||||
uv__free(ifc.ifc_req);
|
||||
uv__close(sockfd);
|
||||
return UV_ENOSYS;
|
||||
}
|
||||
@ -455,22 +526,43 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
|
||||
/* All conditions above must match count loop */
|
||||
|
||||
address->name = uv__strdup(p->ifr_name);
|
||||
i = 0;
|
||||
/* Ignore EBCDIC space (0x40) padding in name */
|
||||
while (i < ARRAY_SIZE(p->ifr_name) &&
|
||||
p->ifr_name[i] != 0x40 &&
|
||||
p->ifr_name[i] != 0)
|
||||
++i;
|
||||
address->name = uv__malloc(i + 1);
|
||||
if (address->name == NULL) {
|
||||
uv_free_interface_addresses(*addresses, count_names);
|
||||
uv__free(ifc.ifc_req);
|
||||
uv__close(sockfd);
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
memcpy(address->name, p->ifr_name, i);
|
||||
address->name[i] = '\0';
|
||||
__e2a_s(address->name);
|
||||
count_names++;
|
||||
|
||||
if (p->ifr_addr.sa_family == AF_INET6) {
|
||||
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
||||
} else {
|
||||
address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
|
||||
address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
|
||||
uv_free_interface_addresses(*addresses, count_names);
|
||||
uv__free(ifc.ifc_req);
|
||||
uv__close(sockfd);
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
|
||||
address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
|
||||
address->netmask.netmask4.sin_family = AF_INET;
|
||||
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
|
||||
memset(address->phys_addr, 0, sizeof(address->phys_addr));
|
||||
address++;
|
||||
}
|
||||
|
||||
#undef ADDR_SIZE
|
||||
#undef MAX
|
||||
|
||||
uv__free(ifc.ifc_req);
|
||||
uv__close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
@ -529,27 +621,17 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||
}
|
||||
|
||||
|
||||
void uv__fs_event_close(uv_fs_event_t* handle) {
|
||||
uv_fs_event_stop(handle);
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
|
||||
const char* filename, unsigned int flags) {
|
||||
static int os390_regfileint(uv_fs_event_t* handle, char* path) {
|
||||
uv__os390_epoll* ep;
|
||||
_RFIS reg_struct;
|
||||
char* path;
|
||||
int rc;
|
||||
|
||||
if (uv__is_active(handle))
|
||||
return UV_EINVAL;
|
||||
|
||||
ep = handle->loop->ep;
|
||||
assert(ep->msg_queue != -1);
|
||||
|
||||
@ -558,17 +640,10 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
|
||||
reg_struct.__rfis_type = 1;
|
||||
memcpy(reg_struct.__rfis_utok, &handle, sizeof(handle));
|
||||
|
||||
path = uv__strdup(filename);
|
||||
if (path == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct);
|
||||
if (rc != 0)
|
||||
return UV__ERR(errno);
|
||||
|
||||
uv__handle_start(handle);
|
||||
handle->path = path;
|
||||
handle->cb = cb;
|
||||
memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok,
|
||||
sizeof(handle->rfis_rftok));
|
||||
|
||||
@ -576,7 +651,33 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
|
||||
const char* filename, unsigned int flags) {
|
||||
char* path;
|
||||
int rc;
|
||||
|
||||
if (uv__is_active(handle))
|
||||
return UV_EINVAL;
|
||||
|
||||
path = uv__strdup(filename);
|
||||
if (path == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
rc = os390_regfileint(handle, path);
|
||||
if (rc != 0) {
|
||||
uv__free(path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
uv__handle_start(handle);
|
||||
handle->path = path;
|
||||
handle->cb = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv__fs_event_stop(uv_fs_event_t* handle) {
|
||||
uv__os390_epoll* ep;
|
||||
_RFIS reg_struct;
|
||||
int rc;
|
||||
@ -602,12 +703,40 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
if (rc != 0 && errno != EALREADY && errno != ENOENT)
|
||||
abort();
|
||||
|
||||
if (handle->path != NULL) {
|
||||
uv__free(handle->path);
|
||||
handle->path = NULL;
|
||||
}
|
||||
|
||||
if (rc != 0 && errno == EALREADY)
|
||||
return -1;
|
||||
|
||||
uv__handle_stop(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
uv__fs_event_stop(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv__fs_event_close(uv_fs_event_t* handle) {
|
||||
/*
|
||||
* If we were unable to unregister file interest here, then it is most likely
|
||||
* that there is a pending queued change notification. When this happens, we
|
||||
* don't want to complete the close as it will free the underlying memory for
|
||||
* the handle, causing a use-after-free problem when the event is processed.
|
||||
* We defer the final cleanup until after the event is consumed in
|
||||
* os390_message_queue_handler().
|
||||
*/
|
||||
if (uv__fs_event_stop(handle) == 0)
|
||||
uv__make_close_pending((uv_handle_t*) handle);
|
||||
}
|
||||
|
||||
|
||||
static int os390_message_queue_handler(uv__os390_epoll* ep) {
|
||||
uv_fs_event_t* handle;
|
||||
int msglen;
|
||||
@ -628,7 +757,15 @@ static int os390_message_queue_handler(uv__os390_epoll* ep) {
|
||||
events = 0;
|
||||
if (msg.__rfim_event == _RFIM_ATTR || msg.__rfim_event == _RFIM_WRITE)
|
||||
events = UV_CHANGE;
|
||||
else if (msg.__rfim_event == _RFIM_RENAME)
|
||||
else if (msg.__rfim_event == _RFIM_RENAME || msg.__rfim_event == _RFIM_UNLINK)
|
||||
events = UV_RENAME;
|
||||
else if (msg.__rfim_event == 156)
|
||||
/* TODO(gabylb): zos - this event should not happen, need to investigate.
|
||||
*
|
||||
* This event seems to occur when the watched file is [re]moved, or an
|
||||
* editor (like vim) renames then creates the file on save (for vim, that's
|
||||
* when backupcopy=no|auto).
|
||||
*/
|
||||
events = UV_RENAME;
|
||||
else
|
||||
/* Some event that we are not interested in. */
|
||||
@ -639,6 +776,26 @@ static int os390_message_queue_handler(uv__os390_epoll* ep) {
|
||||
*/
|
||||
__a2e_l(msg.__rfim_utok, sizeof(msg.__rfim_utok));
|
||||
handle = *(uv_fs_event_t**)(msg.__rfim_utok);
|
||||
assert(handle != NULL);
|
||||
|
||||
assert((handle->flags & UV_HANDLE_CLOSED) == 0);
|
||||
if (uv__is_closing(handle)) {
|
||||
uv__handle_stop(handle);
|
||||
uv__make_close_pending((uv_handle_t*) handle);
|
||||
return 0;
|
||||
} else if (handle->path == NULL) {
|
||||
/* _RFIS_UNREG returned EALREADY. */
|
||||
uv__handle_stop(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The file is implicitly unregistered when the change notification is
|
||||
* sent, only one notification is sent per registration. So we need to
|
||||
* re-register interest in a file after each change notification we
|
||||
* receive.
|
||||
*/
|
||||
assert(handle->path != NULL);
|
||||
os390_regfileint(handle, handle->path);
|
||||
handle->cb(handle, uv__basename_r(handle->path), events, 0);
|
||||
return 1;
|
||||
}
|
||||
@ -650,6 +807,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
struct epoll_event* pe;
|
||||
struct epoll_event e;
|
||||
uv__os390_epoll* ep;
|
||||
int have_signals;
|
||||
int real_timeout;
|
||||
QUEUE* q;
|
||||
uv__io_t* w;
|
||||
@ -712,6 +870,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
count = 48; /* Benchmarks suggest this gives the best throughput. */
|
||||
real_timeout = timeout;
|
||||
int nevents = 0;
|
||||
have_signals = 0;
|
||||
|
||||
if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
|
||||
reset_timeout = 1;
|
||||
@ -796,6 +955,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
ep = loop->ep;
|
||||
if (pe->is_msg) {
|
||||
os390_message_queue_handler(ep);
|
||||
nevents++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -825,19 +985,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
pe->events |= w->pevents & (POLLIN | POLLOUT);
|
||||
|
||||
if (pe->events != 0) {
|
||||
uv__metrics_update_idle_time(loop);
|
||||
w->cb(loop, w, pe->events);
|
||||
/* Run signal watchers last. This also affects child process watchers
|
||||
* because those are implemented in terms of signal watchers.
|
||||
*/
|
||||
if (w == &loop->signal_io_watcher) {
|
||||
have_signals = 1;
|
||||
} else {
|
||||
uv__metrics_update_idle_time(loop);
|
||||
w->cb(loop, w, pe->events);
|
||||
}
|
||||
nevents++;
|
||||
}
|
||||
}
|
||||
loop->watchers[loop->nwatchers] = NULL;
|
||||
loop->watchers[loop->nwatchers + 1] = NULL;
|
||||
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
if (have_signals != 0) {
|
||||
uv__metrics_update_idle_time(loop);
|
||||
loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
|
||||
}
|
||||
|
||||
loop->watchers[loop->nwatchers] = NULL;
|
||||
loop->watchers[loop->nwatchers + 1] = NULL;
|
||||
|
||||
if (have_signals != 0)
|
||||
return; /* Event loop should cycle now so don't poll again. */
|
||||
|
||||
if (nevents != 0) {
|
||||
if (nfds == ARRAY_SIZE(events) && --count != 0) {
|
||||
/* Poll for more events but don't block this time. */
|
||||
@ -872,6 +1048,5 @@ int uv__io_fork(uv_loop_t* loop) {
|
||||
*/
|
||||
loop->ep = NULL;
|
||||
|
||||
uv__platform_loop_delete(loop);
|
||||
return uv__platform_loop_init(loop);
|
||||
}
|
||||
|
6
deps/libuv/src/unix/pipe.c
vendored
6
deps/libuv/src/unix/pipe.c
vendored
@ -51,7 +51,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
||||
/* Already bound? */
|
||||
if (uv__stream_fd(handle) >= 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (uv__is_closing(handle)) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
/* Make a copy of the file name, it outlives this function's scope. */
|
||||
pipe_fname = uv__strdup(name);
|
||||
if (pipe_fname == NULL)
|
||||
@ -319,7 +321,7 @@ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
|
||||
if (handle->accepted_fd == -1)
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
else
|
||||
return uv__handle_type(handle->accepted_fd);
|
||||
return uv_guess_handle(handle->accepted_fd);
|
||||
}
|
||||
|
||||
|
||||
|
40
deps/libuv/src/unix/process.c
vendored
40
deps/libuv/src/unix/process.c
vendored
@ -35,7 +35,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#if defined(__APPLE__) && !TARGET_OS_IPHONE
|
||||
#if defined(__APPLE__)
|
||||
# include <spawn.h>
|
||||
# include <paths.h>
|
||||
# include <sys/kauth.h>
|
||||
@ -671,27 +671,25 @@ static int uv__spawn_resolve_and_spawn(const uv_process_options_t* options,
|
||||
if (options->env != NULL)
|
||||
env = options->env;
|
||||
|
||||
/* If options->file contains a slash, posix_spawn/posix_spawnp behave
|
||||
* the same, and don't involve PATH resolution at all. Otherwise, if
|
||||
* options->file does not include a slash, but no custom environment is
|
||||
* to be used, the environment used for path resolution as well for the
|
||||
* child process is that of the parent process, so posix_spawnp is the
|
||||
* way to go. */
|
||||
if (strchr(options->file, '/') != NULL || options->env == NULL) {
|
||||
/* If options->file contains a slash, posix_spawn/posix_spawnp should behave
|
||||
* the same, and do not involve PATH resolution at all. The libc
|
||||
* `posix_spawnp` provided by Apple is buggy (since 10.15), so we now emulate it
|
||||
* here, per https://github.com/libuv/libuv/pull/3583. */
|
||||
if (strchr(options->file, '/') != NULL) {
|
||||
do
|
||||
err = posix_spawnp(pid, options->file, actions, attrs, options->args, env);
|
||||
err = posix_spawn(pid, options->file, actions, attrs, options->args, env);
|
||||
while (err == EINTR);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Look for the definition of PATH in the provided env */
|
||||
path = uv__spawn_find_path_in_env(options->env);
|
||||
path = uv__spawn_find_path_in_env(env);
|
||||
|
||||
/* The following resolution logic (execvpe emulation) is copied from
|
||||
* https://git.musl-libc.org/cgit/musl/tree/src/process/execvp.c
|
||||
* and adapted to work for our specific usage */
|
||||
|
||||
/* If no path was provided in options->env, use the default value
|
||||
/* If no path was provided in env, use the default value
|
||||
* to look for the executable */
|
||||
if (path == NULL)
|
||||
path = _PATH_DEFPATH;
|
||||
@ -812,11 +810,6 @@ static int uv__spawn_and_init_child_fork(const uv_process_options_t* options,
|
||||
|
||||
*pid = fork();
|
||||
|
||||
if (*pid == -1) {
|
||||
/* Failed to fork */
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
|
||||
if (*pid == 0) {
|
||||
/* Fork succeeded, in the child process */
|
||||
uv__process_child_init(options, stdio_count, pipes, error_fd);
|
||||
@ -826,6 +819,10 @@ static int uv__spawn_and_init_child_fork(const uv_process_options_t* options,
|
||||
if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0)
|
||||
abort();
|
||||
|
||||
if (*pid == -1)
|
||||
/* Failed to fork */
|
||||
return UV__ERR(errno);
|
||||
|
||||
/* Fork succeeded, in the parent process */
|
||||
return 0;
|
||||
}
|
||||
@ -1066,9 +1063,16 @@ int uv_process_kill(uv_process_t* process, int signum) {
|
||||
|
||||
|
||||
int uv_kill(int pid, int signum) {
|
||||
if (kill(pid, signum))
|
||||
if (kill(pid, signum)) {
|
||||
#if defined(__MVS__)
|
||||
/* EPERM is returned if the process is a zombie. */
|
||||
siginfo_t infop;
|
||||
if (errno == EPERM &&
|
||||
waitid(P_PID, pid, &infop, WNOHANG | WNOWAIT | WEXITED) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
return UV__ERR(errno);
|
||||
else
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
95
deps/libuv/src/unix/stream.c
vendored
95
deps/libuv/src/unix/stream.c
vendored
@ -66,6 +66,7 @@ static void uv__read(uv_stream_t* stream);
|
||||
static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
|
||||
static void uv__write_callbacks(uv_stream_t* stream);
|
||||
static size_t uv__write_req_size(uv_write_t* req);
|
||||
static void uv__drain(uv_stream_t* stream);
|
||||
|
||||
|
||||
void uv__stream_init(uv_loop_t* loop,
|
||||
@ -453,17 +454,7 @@ void uv__stream_destroy(uv_stream_t* stream) {
|
||||
|
||||
uv__stream_flush_write_queue(stream, UV_ECANCELED);
|
||||
uv__write_callbacks(stream);
|
||||
|
||||
if (stream->shutdown_req) {
|
||||
/* The ECANCELED error code is a lie, the shutdown(2) syscall is a
|
||||
* fait accompli at this point. Maybe we should revisit this in v0.11.
|
||||
* A possible reason for leaving it unchanged is that it informs the
|
||||
* callee that the handle has been destroyed.
|
||||
*/
|
||||
uv__req_unregister(stream->loop, stream->shutdown_req);
|
||||
stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED);
|
||||
stream->shutdown_req = NULL;
|
||||
}
|
||||
uv__drain(stream);
|
||||
|
||||
assert(stream->write_queue_size == 0);
|
||||
}
|
||||
@ -641,7 +632,9 @@ done:
|
||||
|
||||
int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
|
||||
int err;
|
||||
|
||||
if (uv__is_closing(stream)) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
switch (stream->type) {
|
||||
case UV_TCP:
|
||||
err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb);
|
||||
@ -667,25 +660,30 @@ static void uv__drain(uv_stream_t* stream) {
|
||||
int err;
|
||||
|
||||
assert(QUEUE_EMPTY(&stream->write_queue));
|
||||
uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
|
||||
uv__stream_osx_interrupt_select(stream);
|
||||
if (!(stream->flags & UV_HANDLE_CLOSING)) {
|
||||
uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
|
||||
uv__stream_osx_interrupt_select(stream);
|
||||
}
|
||||
|
||||
/* Shutdown? */
|
||||
if ((stream->flags & UV_HANDLE_SHUTTING) &&
|
||||
!(stream->flags & UV_HANDLE_CLOSING) &&
|
||||
if (!(stream->flags & UV_HANDLE_SHUTTING))
|
||||
return;
|
||||
|
||||
req = stream->shutdown_req;
|
||||
assert(req);
|
||||
|
||||
if ((stream->flags & UV_HANDLE_CLOSING) ||
|
||||
!(stream->flags & UV_HANDLE_SHUT)) {
|
||||
assert(stream->shutdown_req);
|
||||
|
||||
req = stream->shutdown_req;
|
||||
stream->shutdown_req = NULL;
|
||||
stream->flags &= ~UV_HANDLE_SHUTTING;
|
||||
uv__req_unregister(stream->loop, req);
|
||||
|
||||
err = 0;
|
||||
if (shutdown(uv__stream_fd(stream), SHUT_WR))
|
||||
if (stream->flags & UV_HANDLE_CLOSING)
|
||||
/* The user destroyed the stream before we got to do the shutdown. */
|
||||
err = UV_ECANCELED;
|
||||
else if (shutdown(uv__stream_fd(stream), SHUT_WR))
|
||||
err = UV__ERR(errno);
|
||||
|
||||
if (err == 0)
|
||||
else /* Success. */
|
||||
stream->flags |= UV_HANDLE_SHUT;
|
||||
|
||||
if (req->cb != NULL)
|
||||
@ -926,7 +924,6 @@ static void uv__write(uv_stream_t* stream) {
|
||||
}
|
||||
|
||||
req->error = n;
|
||||
// XXX(jwn): this must call uv__stream_flush_write_queue(stream, n) here, since we won't generate any more events
|
||||
uv__write_req_finish(req);
|
||||
uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
|
||||
uv__stream_osx_interrupt_select(stream);
|
||||
@ -964,49 +961,6 @@ static void uv__write_callbacks(uv_stream_t* stream) {
|
||||
}
|
||||
|
||||
|
||||
uv_handle_type uv__handle_type(int fd) {
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t sslen;
|
||||
socklen_t len;
|
||||
int type;
|
||||
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
sslen = sizeof(ss);
|
||||
|
||||
if (getsockname(fd, (struct sockaddr*)&ss, &sslen))
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
|
||||
len = sizeof type;
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len))
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
|
||||
if (type == SOCK_STREAM) {
|
||||
#if defined(_AIX) || defined(__DragonFly__)
|
||||
/* on AIX/DragonFly the getsockname call returns an empty sa structure
|
||||
* for sockets of type AF_UNIX. For all other types it will
|
||||
* return a properly filled in structure.
|
||||
*/
|
||||
if (sslen == 0)
|
||||
return UV_NAMED_PIPE;
|
||||
#endif
|
||||
switch (ss.ss_family) {
|
||||
case AF_UNIX:
|
||||
return UV_NAMED_PIPE;
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
return UV_TCP;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == SOCK_DGRAM &&
|
||||
(ss.ss_family == AF_INET || ss.ss_family == AF_INET6))
|
||||
return UV_UDP;
|
||||
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
}
|
||||
|
||||
|
||||
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
|
||||
stream->flags |= UV_HANDLE_READ_EOF;
|
||||
stream->flags &= ~UV_HANDLE_READING;
|
||||
@ -1278,7 +1232,8 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
|
||||
|
||||
assert(uv__stream_fd(stream) >= 0);
|
||||
|
||||
/* Initialize request */
|
||||
/* Initialize request. The `shutdown(2)` call will always be deferred until
|
||||
* `uv__drain`, just before the callback is run. */
|
||||
uv__req_init(stream->loop, req, UV_SHUTDOWN);
|
||||
req->handle = stream;
|
||||
req->cb = cb;
|
||||
@ -1286,8 +1241,8 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
|
||||
stream->flags |= UV_HANDLE_SHUTTING;
|
||||
stream->flags &= ~UV_HANDLE_WRITABLE;
|
||||
|
||||
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
|
||||
uv__stream_osx_interrupt_select(stream);
|
||||
if (QUEUE_EMPTY(&stream->write_queue))
|
||||
uv__io_feed(stream->loop, &stream->io_watcher);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
36
deps/libuv/src/unix/sunos.c
vendored
36
deps/libuv/src/unix/sunos.c
vendored
@ -154,7 +154,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
sigset_t set;
|
||||
uint64_t base;
|
||||
uint64_t diff;
|
||||
uint64_t idle_poll;
|
||||
unsigned int nfds;
|
||||
unsigned int i;
|
||||
int saved_errno;
|
||||
@ -424,7 +423,7 @@ void uv_loadavg(double avg[3]) {
|
||||
#if defined(PORT_SOURCE_FILE)
|
||||
|
||||
static int uv__fs_event_rearm(uv_fs_event_t *handle) {
|
||||
if (handle->fd == -1)
|
||||
if (handle->fd == PORT_DELETED)
|
||||
return UV_EBADF;
|
||||
|
||||
if (port_associate(handle->loop->fs_fd,
|
||||
@ -475,6 +474,12 @@ static void uv__fs_event_read(uv_loop_t* loop,
|
||||
handle = (uv_fs_event_t*) pe.portev_user;
|
||||
assert((r == 0) && "unexpected port_get() error");
|
||||
|
||||
if (uv__is_closing(handle)) {
|
||||
uv__handle_stop(handle);
|
||||
uv__make_close_pending((uv_handle_t*) handle);
|
||||
break;
|
||||
}
|
||||
|
||||
events = 0;
|
||||
if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED))
|
||||
events |= UV_CHANGE;
|
||||
@ -542,12 +547,14 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
static int uv__fs_event_stop(uv_fs_event_t* handle) {
|
||||
int ret = 0;
|
||||
|
||||
if (!uv__is_active(handle))
|
||||
return 0;
|
||||
|
||||
if (handle->fd == PORT_FIRED || handle->fd == PORT_LOADED) {
|
||||
port_dissociate(handle->loop->fs_fd,
|
||||
if (handle->fd == PORT_LOADED) {
|
||||
ret = port_dissociate(handle->loop->fs_fd,
|
||||
PORT_SOURCE_FILE,
|
||||
(uintptr_t) &handle->fo);
|
||||
}
|
||||
@ -556,13 +563,28 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
uv__free(handle->path);
|
||||
handle->path = NULL;
|
||||
handle->fo.fo_name = NULL;
|
||||
uv__handle_stop(handle);
|
||||
if (ret == 0)
|
||||
uv__handle_stop(handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
(void) uv__fs_event_stop(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uv__fs_event_close(uv_fs_event_t* handle) {
|
||||
uv_fs_event_stop(handle);
|
||||
/*
|
||||
* If we were unable to dissociate the port here, then it is most likely
|
||||
* that there is a pending queued event. When this happens, we don't want
|
||||
* to complete the close as it will free the underlying memory for the
|
||||
* handle, causing a use-after-free problem when the event is processed.
|
||||
* We defer the final cleanup until after the event is consumed in
|
||||
* uv__fs_event_read().
|
||||
*/
|
||||
if (uv__fs_event_stop(handle) == 0)
|
||||
uv__make_close_pending((uv_handle_t*) handle);
|
||||
}
|
||||
|
||||
#else /* !defined(PORT_SOURCE_FILE) */
|
||||
|
17
deps/libuv/src/unix/tcp.c
vendored
17
deps/libuv/src/unix/tcp.c
vendored
@ -184,14 +184,15 @@ int uv__tcp_bind(uv_tcp_t* tcp,
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
|
||||
err = bind(tcp->io_watcher.fd, addr, addrlen);
|
||||
if (err == -1 && errno != EADDRINUSE) {
|
||||
if (errno == EAFNOSUPPORT)
|
||||
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
|
||||
* socket created with AF_INET to an AF_INET6 address or vice versa. */
|
||||
return UV_EINVAL;
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
tcp->delayed_error = UV__ERR(errno);
|
||||
tcp->delayed_error = (err == -1) ? UV__ERR(errno) : 0;
|
||||
|
||||
tcp->flags |= UV_HANDLE_BOUND;
|
||||
if (addr->sa_family == AF_INET6)
|
||||
@ -320,8 +321,16 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
|
||||
return UV_EINVAL;
|
||||
|
||||
fd = uv__stream_fd(handle);
|
||||
if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
|
||||
return UV__ERR(errno);
|
||||
if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) {
|
||||
if (errno == EINVAL) {
|
||||
/* Open Group Specifications Issue 7, 2018 edition states that
|
||||
* EINVAL may mean the socket has been shut down already.
|
||||
* Behavior observed on Solaris, illumos and macOS. */
|
||||
errno = 0;
|
||||
} else {
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
}
|
||||
|
||||
uv_close((uv_handle_t*) handle, close_cb);
|
||||
return 0;
|
||||
|
78
deps/libuv/src/unix/tty.c
vendored
78
deps/libuv/src/unix/tty.c
vendored
@ -66,6 +66,19 @@ static int orig_termios_fd = -1;
|
||||
static struct termios orig_termios;
|
||||
static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER;
|
||||
|
||||
int uv__tcsetattr(int fd, int how, const struct termios *term) {
|
||||
int rc;
|
||||
|
||||
do
|
||||
rc = tcsetattr(fd, how, term);
|
||||
while (rc == -1 && errno == EINTR);
|
||||
|
||||
if (rc == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uv__tty_is_slave(const int fd) {
|
||||
int result;
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
@ -268,13 +281,18 @@ static void uv__tty_make_raw(struct termios* tio) {
|
||||
int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
|
||||
struct termios tmp;
|
||||
int fd;
|
||||
int rc;
|
||||
|
||||
if (tty->mode == (int) mode)
|
||||
return 0;
|
||||
|
||||
fd = uv__stream_fd(tty);
|
||||
if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
|
||||
if (tcgetattr(fd, &tty->orig_termios))
|
||||
do
|
||||
rc = tcgetattr(fd, &tty->orig_termios);
|
||||
while (rc == -1 && errno == EINTR);
|
||||
|
||||
if (rc == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
/* This is used for uv_tty_reset_mode() */
|
||||
@ -304,11 +322,11 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
|
||||
}
|
||||
|
||||
/* Apply changes after draining */
|
||||
if (tcsetattr(fd, TCSADRAIN, &tmp))
|
||||
return UV__ERR(errno);
|
||||
rc = uv__tcsetattr(fd, TCSADRAIN, &tmp);
|
||||
if (rc == 0)
|
||||
tty->mode = mode;
|
||||
|
||||
tty->mode = mode;
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -331,7 +349,7 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
|
||||
|
||||
|
||||
uv_handle_type uv_guess_handle(uv_file file) {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_storage ss;
|
||||
struct stat s;
|
||||
socklen_t len;
|
||||
int type;
|
||||
@ -342,8 +360,24 @@ uv_handle_type uv_guess_handle(uv_file file) {
|
||||
if (isatty(file))
|
||||
return UV_TTY;
|
||||
|
||||
if (fstat(file, &s))
|
||||
if (fstat(file, &s)) {
|
||||
#if defined(__PASE__)
|
||||
/* On ibmi receiving RST from TCP instead of FIN immediately puts fd into
|
||||
* an error state. fstat will return EINVAL, getsockname will also return
|
||||
* EINVAL, even if sockaddr_storage is valid. (If file does not refer to a
|
||||
* socket, ENOTSOCK is returned instead.)
|
||||
* In such cases, we will permit the user to open the connection as uv_tcp
|
||||
* still, so that the user can get immediately notified of the error in
|
||||
* their read callback and close this fd.
|
||||
*/
|
||||
len = sizeof(ss);
|
||||
if (getsockname(file, (struct sockaddr*) &ss, &len)) {
|
||||
if (errno == EINVAL)
|
||||
return UV_TCP;
|
||||
}
|
||||
#endif
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
}
|
||||
|
||||
if (S_ISREG(s.st_mode))
|
||||
return UV_FILE;
|
||||
@ -357,16 +391,29 @@ uv_handle_type uv_guess_handle(uv_file file) {
|
||||
if (!S_ISSOCK(s.st_mode))
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
|
||||
len = sizeof(ss);
|
||||
if (getsockname(file, (struct sockaddr*) &ss, &len)) {
|
||||
#if defined(_AIX)
|
||||
/* On aix receiving RST from TCP instead of FIN immediately puts fd into
|
||||
* an error state. In such case getsockname will return EINVAL, even if
|
||||
* sockaddr_storage is valid.
|
||||
* In such cases, we will permit the user to open the connection as uv_tcp
|
||||
* still, so that the user can get immediately notified of the error in
|
||||
* their read callback and close this fd.
|
||||
*/
|
||||
if (errno == EINVAL) {
|
||||
return UV_TCP;
|
||||
}
|
||||
#endif
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
}
|
||||
|
||||
len = sizeof(type);
|
||||
if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len))
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
|
||||
len = sizeof(sa);
|
||||
if (getsockname(file, &sa, &len))
|
||||
return UV_UNKNOWN_HANDLE;
|
||||
|
||||
if (type == SOCK_DGRAM)
|
||||
if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
|
||||
if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6)
|
||||
return UV_UDP;
|
||||
|
||||
if (type == SOCK_STREAM) {
|
||||
@ -379,9 +426,9 @@ uv_handle_type uv_guess_handle(uv_file file) {
|
||||
return UV_NAMED_PIPE;
|
||||
#endif /* defined(_AIX) || defined(__DragonFly__) */
|
||||
|
||||
if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
|
||||
if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6)
|
||||
return UV_TCP;
|
||||
if (sa.sa_family == AF_UNIX)
|
||||
if (ss.ss_family == AF_UNIX)
|
||||
return UV_NAMED_PIPE;
|
||||
}
|
||||
|
||||
@ -403,8 +450,7 @@ int uv_tty_reset_mode(void) {
|
||||
|
||||
err = 0;
|
||||
if (orig_termios_fd != -1)
|
||||
if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios))
|
||||
err = UV__ERR(errno);
|
||||
err = uv__tcsetattr(orig_termios_fd, TCSANOW, &orig_termios);
|
||||
|
||||
uv_spinlock_unlock(&termios_spinlock);
|
||||
errno = saved_errno;
|
||||
|
9
deps/libuv/src/unix/udp.c
vendored
9
deps/libuv/src/unix/udp.c
vendored
@ -704,7 +704,16 @@ int uv__udp_disconnect(uv_udp_t* handle) {
|
||||
|
||||
do {
|
||||
errno = 0;
|
||||
#ifdef __PASE__
|
||||
/* On IBMi a connectionless transport socket can be disconnected by
|
||||
* either setting the addr parameter to NULL or setting the
|
||||
* addr_length parameter to zero, and issuing another connect().
|
||||
* https://www.ibm.com/docs/en/i/7.4?topic=ssw_ibm_i_74/apis/connec.htm
|
||||
*/
|
||||
r = connect(handle->io_watcher.fd, (struct sockaddr*) NULL, 0);
|
||||
#else
|
||||
r = connect(handle->io_watcher.fd, (struct sockaddr*) &addr, sizeof(addr));
|
||||
#endif
|
||||
} while (r == -1 && errno == EINTR);
|
||||
|
||||
if (r == -1) {
|
||||
|
4
deps/libuv/src/uv-common.c
vendored
4
deps/libuv/src/uv-common.c
vendored
@ -295,7 +295,9 @@ int uv_tcp_bind(uv_tcp_t* handle,
|
||||
|
||||
if (handle->type != UV_TCP)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (uv__is_closing(handle)) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
if (addr->sa_family == AF_INET)
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
else if (addr->sa_family == AF_INET6)
|
||||
|
13
deps/libuv/src/win/core.c
vendored
13
deps/libuv/src/win/core.c
vendored
@ -592,7 +592,7 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
|
||||
int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
||||
DWORD timeout;
|
||||
int r;
|
||||
int ran_pending;
|
||||
int can_sleep;
|
||||
|
||||
r = uv__loop_alive(loop);
|
||||
if (!r)
|
||||
@ -602,12 +602,14 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
||||
uv_update_time(loop);
|
||||
uv__run_timers(loop);
|
||||
|
||||
ran_pending = uv__process_reqs(loop);
|
||||
can_sleep = loop->pending_reqs_tail == NULL && loop->idle_handles == NULL;
|
||||
|
||||
uv__process_reqs(loop);
|
||||
uv__idle_invoke(loop);
|
||||
uv__prepare_invoke(loop);
|
||||
|
||||
timeout = 0;
|
||||
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
|
||||
if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT)
|
||||
timeout = uv_backend_timeout(loop);
|
||||
|
||||
if (pGetQueuedCompletionStatusEx)
|
||||
@ -615,6 +617,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
||||
else
|
||||
uv__poll_wine(loop, timeout);
|
||||
|
||||
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
|
||||
* times to avoid loop starvation.*/
|
||||
for (r = 0; r < 8 && loop->pending_reqs_tail != NULL; r++)
|
||||
uv__process_reqs(loop);
|
||||
|
||||
/* Run one final update on the provider_idle_time in case uv__poll*
|
||||
* returned because the timeout expired, but no events were received. This
|
||||
* call will be ignored if the provider_entry_time was either never set (if
|
||||
|
2
deps/libuv/src/win/error.c
vendored
2
deps/libuv/src/win/error.c
vendored
@ -73,7 +73,6 @@ int uv_translate_sys_error(int sys_errno) {
|
||||
case WSAEACCES: return UV_EACCES;
|
||||
case ERROR_ELEVATION_REQUIRED: return UV_EACCES;
|
||||
case ERROR_CANT_ACCESS_FILE: return UV_EACCES;
|
||||
case ERROR_ACCESS_DENIED: return UV_EACCES;
|
||||
case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
|
||||
case WSAEADDRINUSE: return UV_EADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
|
||||
@ -155,6 +154,7 @@ int uv_translate_sys_error(int sys_errno) {
|
||||
case WSAENOTSOCK: return UV_ENOTSOCK;
|
||||
case ERROR_NOT_SUPPORTED: return UV_ENOTSUP;
|
||||
case ERROR_BROKEN_PIPE: return UV_EOF;
|
||||
case ERROR_ACCESS_DENIED: return UV_EPERM;
|
||||
case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM;
|
||||
case ERROR_BAD_PIPE: return UV_EPIPE;
|
||||
case ERROR_NO_DATA: return UV_EPIPE;
|
||||
|
9
deps/libuv/src/win/internal.h
vendored
9
deps/libuv/src/win/internal.h
vendored
@ -88,6 +88,9 @@ void uv__process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
uv_req_t* req);
|
||||
void uv__process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
uv_connect_t* req);
|
||||
void uv__process_tcp_shutdown_req(uv_loop_t* loop,
|
||||
uv_tcp_t* stream,
|
||||
uv_shutdown_t* req);
|
||||
|
||||
void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
|
||||
void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
|
||||
@ -130,6 +133,7 @@ int uv__pipe_write(uv_loop_t* loop,
|
||||
size_t nbufs,
|
||||
uv_stream_t* send_handle,
|
||||
uv_write_cb cb);
|
||||
void uv__pipe_shutdown(uv_loop_t* loop, uv_pipe_t* handle, uv_shutdown_t* req);
|
||||
|
||||
void uv__process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
uv_req_t* req);
|
||||
@ -143,7 +147,6 @@ void uv__process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
uv_shutdown_t* req);
|
||||
|
||||
void uv__pipe_close(uv_loop_t* loop, uv_pipe_t* handle);
|
||||
void uv__pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle);
|
||||
void uv__pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
|
||||
|
||||
|
||||
@ -177,7 +180,9 @@ void uv__process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
|
||||
*/
|
||||
void uv__process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
|
||||
uv_connect_t* req);
|
||||
|
||||
void uv__process_tty_shutdown_req(uv_loop_t* loop,
|
||||
uv_tty_t* stream,
|
||||
uv_shutdown_t* req);
|
||||
void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle);
|
||||
|
||||
|
||||
|
464
deps/libuv/src/win/pipe.c
vendored
464
deps/libuv/src/win/pipe.c
vendored
@ -121,14 +121,10 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
|
||||
|
||||
|
||||
static void uv__pipe_connection_init(uv_pipe_t* handle) {
|
||||
assert(!(handle->flags & UV_HANDLE_PIPESERVER));
|
||||
uv__connection_init((uv_stream_t*) handle);
|
||||
handle->read_req.data = handle;
|
||||
handle->pipe.conn.eof_timer = NULL;
|
||||
assert(!(handle->flags & UV_HANDLE_PIPESERVER));
|
||||
if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
|
||||
handle->pipe.conn.readfile_thread_handle = NULL;
|
||||
InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -393,6 +389,8 @@ int uv__create_stdio_pipe_pair(uv_loop_t* loop,
|
||||
unsigned int client_flags;
|
||||
int err;
|
||||
|
||||
uv__pipe_connection_init(parent_pipe);
|
||||
|
||||
server_pipe = INVALID_HANDLE_VALUE;
|
||||
client_pipe = INVALID_HANDLE_VALUE;
|
||||
|
||||
@ -427,7 +425,6 @@ int uv__create_stdio_pipe_pair(uv_loop_t* loop,
|
||||
goto error;
|
||||
}
|
||||
|
||||
uv__pipe_connection_init(parent_pipe);
|
||||
parent_pipe->handle = server_pipe;
|
||||
*child_pipe_ptr = client_pipe;
|
||||
|
||||
@ -462,7 +459,9 @@ static int uv__set_pipe_handle(uv_loop_t* loop,
|
||||
DWORD current_mode = 0;
|
||||
DWORD err = 0;
|
||||
|
||||
if (handle->flags & UV_HANDLE_PIPESERVER)
|
||||
assert(handle->flags & UV_HANDLE_CONNECTION);
|
||||
assert(!(handle->flags & UV_HANDLE_PIPESERVER));
|
||||
if (handle->flags & UV_HANDLE_CLOSING)
|
||||
return UV_EINVAL;
|
||||
if (handle->handle != INVALID_HANDLE_VALUE)
|
||||
return UV_EBUSY;
|
||||
@ -478,18 +477,17 @@ static int uv__set_pipe_handle(uv_loop_t* loop,
|
||||
*/
|
||||
if (!GetNamedPipeHandleState(pipeHandle, ¤t_mode, NULL, NULL,
|
||||
NULL, NULL, 0)) {
|
||||
return -1;
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
} else if (current_mode & PIPE_NOWAIT) {
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
return -1;
|
||||
return UV_EACCES;
|
||||
}
|
||||
} else {
|
||||
/* If this returns ERROR_INVALID_PARAMETER we probably opened
|
||||
* something that is not a pipe. */
|
||||
if (err == ERROR_INVALID_PARAMETER) {
|
||||
SetLastError(WSAENOTSOCK);
|
||||
return UV_ENOTSOCK;
|
||||
}
|
||||
return -1;
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
}
|
||||
|
||||
@ -500,13 +498,15 @@ static int uv__set_pipe_handle(uv_loop_t* loop,
|
||||
sizeof(mode_info),
|
||||
FileModeInformation);
|
||||
if (nt_status != STATUS_SUCCESS) {
|
||||
return -1;
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT ||
|
||||
mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) {
|
||||
/* Non-overlapped pipe. */
|
||||
handle->flags |= UV_HANDLE_NON_OVERLAPPED_PIPE;
|
||||
handle->pipe.conn.readfile_thread_handle = NULL;
|
||||
InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);
|
||||
} else {
|
||||
/* Overlapped pipe. Try to associate with IOCP. */
|
||||
if (CreateIoCompletionPort(pipeHandle,
|
||||
@ -578,135 +578,109 @@ static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {
|
||||
}
|
||||
|
||||
|
||||
void uv__pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
||||
int err;
|
||||
void uv__pipe_shutdown(uv_loop_t* loop, uv_pipe_t* handle, uv_shutdown_t *req) {
|
||||
DWORD result;
|
||||
uv_shutdown_t* req;
|
||||
NTSTATUS nt_status;
|
||||
IO_STATUS_BLOCK io_status;
|
||||
FILE_PIPE_LOCAL_INFORMATION pipe_info;
|
||||
|
||||
assert(handle->flags & UV_HANDLE_CONNECTION);
|
||||
assert(req != NULL);
|
||||
assert(handle->stream.conn.write_reqs_pending == 0);
|
||||
SET_REQ_SUCCESS(req);
|
||||
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
uv__insert_pending_req(loop, (uv_req_t*) req);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try to avoid flushing the pipe buffer in the thread pool. */
|
||||
nt_status = pNtQueryInformationFile(handle->handle,
|
||||
&io_status,
|
||||
&pipe_info,
|
||||
sizeof pipe_info,
|
||||
FilePipeLocalInformation);
|
||||
|
||||
if (nt_status != STATUS_SUCCESS) {
|
||||
SET_REQ_ERROR(req, pRtlNtStatusToDosError(nt_status));
|
||||
handle->flags |= UV_HANDLE_WRITABLE; /* Questionable. */
|
||||
uv__insert_pending_req(loop, (uv_req_t*) req);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
|
||||
/* Short-circuit, no need to call FlushFileBuffers:
|
||||
* all writes have been read. */
|
||||
uv__insert_pending_req(loop, (uv_req_t*) req);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Run FlushFileBuffers in the thread pool. */
|
||||
result = QueueUserWorkItem(pipe_shutdown_thread_proc,
|
||||
req,
|
||||
WT_EXECUTELONGFUNCTION);
|
||||
if (!result) {
|
||||
SET_REQ_ERROR(req, GetLastError());
|
||||
handle->flags |= UV_HANDLE_WRITABLE; /* Questionable. */
|
||||
uv__insert_pending_req(loop, (uv_req_t*) req);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uv__pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
||||
uv__ipc_xfer_queue_item_t* xfer_queue_item;
|
||||
|
||||
if ((handle->flags & UV_HANDLE_CONNECTION) &&
|
||||
handle->stream.conn.shutdown_req != NULL &&
|
||||
handle->stream.conn.write_reqs_pending == 0) {
|
||||
req = handle->stream.conn.shutdown_req;
|
||||
assert(handle->reqs_pending == 0);
|
||||
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
|
||||
/* Clear the shutdown_req field so we don't go here again. */
|
||||
handle->stream.conn.shutdown_req = NULL;
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
/* Free pending sockets */
|
||||
while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {
|
||||
QUEUE* q;
|
||||
SOCKET socket;
|
||||
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
UNREGISTER_HANDLE_REQ(loop, handle, req);
|
||||
q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);
|
||||
QUEUE_REMOVE(q);
|
||||
xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
|
||||
|
||||
/* Already closing. Cancel the shutdown. */
|
||||
if (req->cb) {
|
||||
req->cb(req, UV_ECANCELED);
|
||||
/* Materialize socket and close it */
|
||||
socket = WSASocketW(FROM_PROTOCOL_INFO,
|
||||
FROM_PROTOCOL_INFO,
|
||||
FROM_PROTOCOL_INFO,
|
||||
&xfer_queue_item->xfer_info.socket_info,
|
||||
0,
|
||||
WSA_FLAG_OVERLAPPED);
|
||||
uv__free(xfer_queue_item);
|
||||
|
||||
if (socket != INVALID_SOCKET)
|
||||
closesocket(socket);
|
||||
}
|
||||
handle->pipe.conn.ipc_xfer_queue_length = 0;
|
||||
|
||||
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
|
||||
UnregisterWait(handle->read_req.wait_handle);
|
||||
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try to avoid flushing the pipe buffer in the thread pool. */
|
||||
nt_status = pNtQueryInformationFile(handle->handle,
|
||||
&io_status,
|
||||
&pipe_info,
|
||||
sizeof pipe_info,
|
||||
FilePipeLocalInformation);
|
||||
|
||||
if (nt_status != STATUS_SUCCESS) {
|
||||
/* Failure */
|
||||
UNREGISTER_HANDLE_REQ(loop, handle, req);
|
||||
|
||||
handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */
|
||||
if (req->cb) {
|
||||
err = pRtlNtStatusToDosError(nt_status);
|
||||
req->cb(req, uv_translate_sys_error(err));
|
||||
if (handle->read_req.event_handle != NULL) {
|
||||
CloseHandle(handle->read_req.event_handle);
|
||||
handle->read_req.event_handle = NULL;
|
||||
}
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
|
||||
/* Short-circuit, no need to call FlushFileBuffers. */
|
||||
uv__insert_pending_req(loop, (uv_req_t*) req);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Run FlushFileBuffers in the thread pool. */
|
||||
result = QueueUserWorkItem(pipe_shutdown_thread_proc,
|
||||
req,
|
||||
WT_EXECUTELONGFUNCTION);
|
||||
if (result) {
|
||||
return;
|
||||
|
||||
} else {
|
||||
/* Failure. */
|
||||
UNREGISTER_HANDLE_REQ(loop, handle, req);
|
||||
|
||||
handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */
|
||||
if (req->cb) {
|
||||
err = GetLastError();
|
||||
req->cb(req, uv_translate_sys_error(err));
|
||||
}
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
return;
|
||||
}
|
||||
if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)
|
||||
DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
handle->reqs_pending == 0) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
/* Free pending sockets */
|
||||
while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {
|
||||
QUEUE* q;
|
||||
SOCKET socket;
|
||||
|
||||
q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);
|
||||
QUEUE_REMOVE(q);
|
||||
xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
|
||||
|
||||
/* Materialize socket and close it */
|
||||
socket = WSASocketW(FROM_PROTOCOL_INFO,
|
||||
FROM_PROTOCOL_INFO,
|
||||
FROM_PROTOCOL_INFO,
|
||||
&xfer_queue_item->xfer_info.socket_info,
|
||||
0,
|
||||
WSA_FLAG_OVERLAPPED);
|
||||
uv__free(xfer_queue_item);
|
||||
|
||||
if (socket != INVALID_SOCKET)
|
||||
closesocket(socket);
|
||||
}
|
||||
handle->pipe.conn.ipc_xfer_queue_length = 0;
|
||||
|
||||
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
|
||||
UnregisterWait(handle->read_req.wait_handle);
|
||||
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (handle->read_req.event_handle != NULL) {
|
||||
CloseHandle(handle->read_req.event_handle);
|
||||
handle->read_req.event_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)
|
||||
DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_PIPESERVER) {
|
||||
assert(handle->pipe.serv.accept_reqs);
|
||||
uv__free(handle->pipe.serv.accept_reqs);
|
||||
handle->pipe.serv.accept_reqs = NULL;
|
||||
}
|
||||
|
||||
uv__handle_close(handle);
|
||||
if (handle->flags & UV_HANDLE_PIPESERVER) {
|
||||
assert(handle->pipe.serv.accept_reqs);
|
||||
uv__free(handle->pipe.serv.accept_reqs);
|
||||
handle->pipe.serv.accept_reqs = NULL;
|
||||
}
|
||||
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
|
||||
|
||||
@ -731,7 +705,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
||||
if (!name) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
if (uv__is_closing(handle)) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
|
||||
handle->pipe.serv.pending_instances = default_pending_pipe_instances;
|
||||
}
|
||||
@ -815,7 +791,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
||||
assert(loop);
|
||||
|
||||
/* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait
|
||||
* for the pipe to become available with WaitNamedPipe. */
|
||||
* up to 30 seconds for the pipe to become available with WaitNamedPipe. */
|
||||
while (WaitNamedPipeW(handle->name, 30000)) {
|
||||
/* The pipe is now available, try to connect. */
|
||||
pipeHandle = open_named_pipe(handle->name, &duplex_flags);
|
||||
@ -825,9 +801,10 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
if (pipeHandle != INVALID_HANDLE_VALUE &&
|
||||
!uv__set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) {
|
||||
if (pipeHandle != INVALID_HANDLE_VALUE) {
|
||||
SET_REQ_SUCCESS(req);
|
||||
req->u.connect.pipeHandle = pipeHandle;
|
||||
req->u.connect.duplex_flags = duplex_flags;
|
||||
} else {
|
||||
SET_REQ_ERROR(req, GetLastError());
|
||||
}
|
||||
@ -849,6 +826,18 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
||||
UV_REQ_INIT(req, UV_CONNECT);
|
||||
req->handle = (uv_stream_t*) handle;
|
||||
req->cb = cb;
|
||||
req->u.connect.pipeHandle = INVALID_HANDLE_VALUE;
|
||||
req->u.connect.duplex_flags = 0;
|
||||
|
||||
if (handle->flags & UV_HANDLE_PIPESERVER) {
|
||||
err = ERROR_INVALID_PARAMETER;
|
||||
goto error;
|
||||
}
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
err = ERROR_PIPE_BUSY;
|
||||
goto error;
|
||||
}
|
||||
uv__pipe_connection_init(handle);
|
||||
|
||||
/* Convert name to UTF16. */
|
||||
nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
|
||||
@ -888,17 +877,8 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
||||
goto error;
|
||||
}
|
||||
|
||||
assert(pipeHandle != INVALID_HANDLE_VALUE);
|
||||
|
||||
if (uv__set_pipe_handle(loop,
|
||||
(uv_pipe_t*) req->handle,
|
||||
pipeHandle,
|
||||
-1,
|
||||
duplex_flags)) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
}
|
||||
|
||||
req->u.connect.pipeHandle = pipeHandle;
|
||||
req->u.connect.duplex_flags = duplex_flags;
|
||||
SET_REQ_SUCCESS(req);
|
||||
uv__insert_pending_req(loop, (uv_req_t*) req);
|
||||
handle->reqs_pending++;
|
||||
@ -937,7 +917,7 @@ void uv__pipe_interrupt_read(uv_pipe_t* handle) {
|
||||
/* Cancel asynchronous read. */
|
||||
r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
|
||||
assert(r || GetLastError() == ERROR_NOT_FOUND);
|
||||
|
||||
(void) r;
|
||||
} else {
|
||||
/* Cancel synchronous read (which is happening in the thread pool). */
|
||||
HANDLE thread;
|
||||
@ -973,17 +953,30 @@ void uv__pipe_interrupt_read(uv_pipe_t* handle) {
|
||||
void uv__pipe_read_stop(uv_pipe_t* handle) {
|
||||
handle->flags &= ~UV_HANDLE_READING;
|
||||
DECREASE_ACTIVE_COUNT(handle->loop, handle);
|
||||
|
||||
uv__pipe_interrupt_read(handle);
|
||||
}
|
||||
|
||||
|
||||
/* Cleans up uv_pipe_t (server or connection) and all resources associated with
|
||||
* it. */
|
||||
void uv__pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
|
||||
void uv__pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {
|
||||
int i;
|
||||
HANDLE pipeHandle;
|
||||
|
||||
if (handle->flags & UV_HANDLE_READING) {
|
||||
handle->flags &= ~UV_HANDLE_READING;
|
||||
DECREASE_ACTIVE_COUNT(loop, handle);
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_LISTENING) {
|
||||
handle->flags &= ~UV_HANDLE_LISTENING;
|
||||
DECREASE_ACTIVE_COUNT(loop, handle);
|
||||
}
|
||||
|
||||
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
|
||||
uv__handle_closing(handle);
|
||||
|
||||
uv__pipe_interrupt_read(handle);
|
||||
|
||||
if (handle->name) {
|
||||
@ -1003,35 +996,17 @@ void uv__pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
handle->flags &= ~UV_HANDLE_WRITABLE;
|
||||
eof_timer_destroy(handle);
|
||||
}
|
||||
|
||||
if ((handle->flags & UV_HANDLE_CONNECTION)
|
||||
&& handle->handle != INVALID_HANDLE_VALUE)
|
||||
&& handle->handle != INVALID_HANDLE_VALUE) {
|
||||
/* This will eventually destroy the write queue for us too. */
|
||||
close_pipe(handle);
|
||||
}
|
||||
|
||||
|
||||
void uv__pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_READING) {
|
||||
handle->flags &= ~UV_HANDLE_READING;
|
||||
DECREASE_ACTIVE_COUNT(loop, handle);
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_LISTENING) {
|
||||
handle->flags &= ~UV_HANDLE_LISTENING;
|
||||
DECREASE_ACTIVE_COUNT(loop, handle);
|
||||
}
|
||||
|
||||
uv__pipe_cleanup(loop, handle);
|
||||
|
||||
if (handle->reqs_pending == 0) {
|
||||
if (handle->reqs_pending == 0)
|
||||
uv__want_endgame(loop, (uv_handle_t*) handle);
|
||||
}
|
||||
|
||||
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
uv__handle_closing(handle);
|
||||
}
|
||||
|
||||
|
||||
@ -1099,6 +1074,7 @@ int uv__pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
|
||||
|
||||
} else {
|
||||
pipe_client = (uv_pipe_t*) client;
|
||||
uv__pipe_connection_init(pipe_client);
|
||||
|
||||
/* Find a connection instance that has been connected, but not yet
|
||||
* accepted. */
|
||||
@ -1110,7 +1086,6 @@ int uv__pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
|
||||
}
|
||||
|
||||
/* Initialize the client handle and copy the pipeHandle to the client */
|
||||
uv__pipe_connection_init(pipe_client);
|
||||
pipe_client->handle = req->pipeHandle;
|
||||
pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
|
||||
|
||||
@ -2094,10 +2069,9 @@ void uv__process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
uv__queue_non_overlapped_write(handle);
|
||||
}
|
||||
|
||||
if (handle->stream.conn.shutdown_req != NULL &&
|
||||
handle->stream.conn.write_reqs_pending == 0) {
|
||||
uv__want_endgame(loop, (uv_handle_t*)handle);
|
||||
}
|
||||
if (handle->stream.conn.write_reqs_pending == 0)
|
||||
if (handle->flags & UV_HANDLE_SHUTTING)
|
||||
uv__pipe_shutdown(loop, handle, handle->stream.conn.shutdown_req);
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
}
|
||||
@ -2110,7 +2084,7 @@ void uv__process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
assert(handle->type == UV_NAMED_PIPE);
|
||||
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
/* The req->pipeHandle should be freed already in uv__pipe_cleanup(). */
|
||||
/* The req->pipeHandle should be freed already in uv__pipe_close(). */
|
||||
assert(req->pipeHandle == INVALID_HANDLE_VALUE);
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
return;
|
||||
@ -2140,52 +2114,72 @@ void uv__process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
|
||||
void uv__process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
uv_connect_t* req) {
|
||||
HANDLE pipeHandle;
|
||||
DWORD duplex_flags;
|
||||
int err;
|
||||
|
||||
assert(handle->type == UV_NAMED_PIPE);
|
||||
|
||||
UNREGISTER_HANDLE_REQ(loop, handle, req);
|
||||
|
||||
if (req->cb) {
|
||||
err = 0;
|
||||
if (REQ_SUCCESS(req)) {
|
||||
uv__pipe_connection_init(handle);
|
||||
} else {
|
||||
err = GET_REQ_ERROR(req);
|
||||
}
|
||||
req->cb(req, uv_translate_sys_error(err));
|
||||
err = 0;
|
||||
if (REQ_SUCCESS(req)) {
|
||||
pipeHandle = req->u.connect.pipeHandle;
|
||||
duplex_flags = req->u.connect.duplex_flags;
|
||||
err = uv__set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags);
|
||||
if (err)
|
||||
CloseHandle(pipeHandle);
|
||||
} else {
|
||||
err = uv_translate_sys_error(GET_REQ_ERROR(req));
|
||||
}
|
||||
|
||||
if (req->cb)
|
||||
req->cb(req, err);
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uv__process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
uv_shutdown_t* req) {
|
||||
int err;
|
||||
|
||||
assert(handle->type == UV_NAMED_PIPE);
|
||||
|
||||
/* Clear the shutdown_req field so we don't go here again. */
|
||||
handle->stream.conn.shutdown_req = NULL;
|
||||
handle->flags &= ~UV_HANDLE_SHUTTING;
|
||||
UNREGISTER_HANDLE_REQ(loop, handle, req);
|
||||
|
||||
if (handle->flags & UV_HANDLE_READABLE) {
|
||||
/* Initialize and optionally start the eof timer. Only do this if the pipe
|
||||
* is readable and we haven't seen EOF come in ourselves. */
|
||||
eof_timer_init(handle);
|
||||
|
||||
/* If reading start the timer right now. Otherwise uv__pipe_queue_read will
|
||||
* start it. */
|
||||
if (handle->flags & UV_HANDLE_READ_PENDING) {
|
||||
eof_timer_start(handle);
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
/* Already closing. Cancel the shutdown. */
|
||||
err = UV_ECANCELED;
|
||||
} else if (!REQ_SUCCESS(req)) {
|
||||
/* An error occurred in trying to shutdown gracefully. */
|
||||
err = uv_translate_sys_error(GET_REQ_ERROR(req));
|
||||
} else {
|
||||
/* This pipe is not readable. We can just close it to let the other end
|
||||
* know that we're done writing. */
|
||||
close_pipe(handle);
|
||||
if (handle->flags & UV_HANDLE_READABLE) {
|
||||
/* Initialize and optionally start the eof timer. Only do this if the pipe
|
||||
* is readable and we haven't seen EOF come in ourselves. */
|
||||
eof_timer_init(handle);
|
||||
|
||||
/* If reading start the timer right now. Otherwise uv__pipe_queue_read will
|
||||
* start it. */
|
||||
if (handle->flags & UV_HANDLE_READ_PENDING) {
|
||||
eof_timer_start(handle);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* This pipe is not readable. We can just close it to let the other end
|
||||
* know that we're done writing. */
|
||||
close_pipe(handle);
|
||||
}
|
||||
err = 0;
|
||||
}
|
||||
|
||||
if (req->cb) {
|
||||
req->cb(req, 0);
|
||||
}
|
||||
if (req->cb)
|
||||
req->cb(req, err);
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
}
|
||||
@ -2200,7 +2194,8 @@ static void eof_timer_init(uv_pipe_t* pipe) {
|
||||
pipe->pipe.conn.eof_timer = (uv_timer_t*) uv__malloc(sizeof *pipe->pipe.conn.eof_timer);
|
||||
|
||||
r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer);
|
||||
assert(r == 0); /* timers can't fail */
|
||||
assert(r == 0); /* timers can't fail */
|
||||
(void) r;
|
||||
pipe->pipe.conn.eof_timer->data = pipe;
|
||||
uv_unref((uv_handle_t*) pipe->pipe.conn.eof_timer);
|
||||
}
|
||||
@ -2280,10 +2275,16 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
|
||||
IO_STATUS_BLOCK io_status;
|
||||
FILE_ACCESS_INFORMATION access;
|
||||
DWORD duplex_flags = 0;
|
||||
int err;
|
||||
|
||||
if (os_handle == INVALID_HANDLE_VALUE)
|
||||
return UV_EBADF;
|
||||
if (pipe->flags & UV_HANDLE_PIPESERVER)
|
||||
return UV_EINVAL;
|
||||
if (pipe->flags & UV_HANDLE_CONNECTION)
|
||||
return UV_EBUSY;
|
||||
|
||||
uv__pipe_connection_init(pipe);
|
||||
uv__once_init();
|
||||
/* In order to avoid closing a stdio file descriptor 0-2, duplicate the
|
||||
* underlying OS handle and forget about the original fd.
|
||||
@ -2300,6 +2301,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
assert(os_handle != INVALID_HANDLE_VALUE);
|
||||
file = -1;
|
||||
}
|
||||
|
||||
@ -2327,17 +2329,17 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
|
||||
if (access.AccessFlags & FILE_READ_DATA)
|
||||
duplex_flags |= UV_HANDLE_READABLE;
|
||||
|
||||
if (os_handle == INVALID_HANDLE_VALUE ||
|
||||
uv__set_pipe_handle(pipe->loop,
|
||||
pipe,
|
||||
os_handle,
|
||||
file,
|
||||
duplex_flags) == -1) {
|
||||
return UV_EINVAL;
|
||||
err = uv__set_pipe_handle(pipe->loop,
|
||||
pipe,
|
||||
os_handle,
|
||||
file,
|
||||
duplex_flags);
|
||||
if (err) {
|
||||
if (file == -1)
|
||||
CloseHandle(os_handle);
|
||||
return err;
|
||||
}
|
||||
|
||||
uv__pipe_connection_init(pipe);
|
||||
|
||||
if (pipe->ipc) {
|
||||
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
|
||||
pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
|
||||
@ -2361,6 +2363,51 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
|
||||
uv__once_init();
|
||||
name_info = NULL;
|
||||
|
||||
if (handle->name != NULL) {
|
||||
/* The user might try to query the name before we are connected,
|
||||
* and this is just easier to return the cached value if we have it. */
|
||||
name_buf = handle->name;
|
||||
name_len = wcslen(name_buf);
|
||||
|
||||
/* check how much space we need */
|
||||
addrlen = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
name_buf,
|
||||
name_len,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!addrlen) {
|
||||
*size = 0;
|
||||
err = uv_translate_sys_error(GetLastError());
|
||||
return err;
|
||||
} else if (addrlen >= *size) {
|
||||
*size = addrlen + 1;
|
||||
err = UV_ENOBUFS;
|
||||
goto error;
|
||||
}
|
||||
|
||||
addrlen = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
name_buf,
|
||||
name_len,
|
||||
buffer,
|
||||
addrlen,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!addrlen) {
|
||||
*size = 0;
|
||||
err = uv_translate_sys_error(GetLastError());
|
||||
return err;
|
||||
}
|
||||
|
||||
*size = addrlen;
|
||||
buffer[addrlen] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (handle->handle == INVALID_HANDLE_VALUE) {
|
||||
*size = 0;
|
||||
return UV_EINVAL;
|
||||
@ -2498,6 +2545,11 @@ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
|
||||
if (handle->handle != INVALID_HANDLE_VALUE)
|
||||
return uv__pipe_getname(handle, buffer, size);
|
||||
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
if (handle->name != NULL)
|
||||
return uv__pipe_getname(handle, buffer, size);
|
||||
}
|
||||
|
||||
return UV_EBADF;
|
||||
}
|
||||
|
||||
|
13
deps/libuv/src/win/req-inl.h
vendored
13
deps/libuv/src/win/req-inl.h
vendored
@ -138,13 +138,13 @@ INLINE static void uv__insert_pending_req(uv_loop_t* loop, uv_req_t* req) {
|
||||
} while (0)
|
||||
|
||||
|
||||
INLINE static int uv__process_reqs(uv_loop_t* loop) {
|
||||
INLINE static void uv__process_reqs(uv_loop_t* loop) {
|
||||
uv_req_t* req;
|
||||
uv_req_t* first;
|
||||
uv_req_t* next;
|
||||
|
||||
if (loop->pending_reqs_tail == NULL)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
first = loop->pending_reqs_tail->next_req;
|
||||
next = first;
|
||||
@ -172,12 +172,7 @@ INLINE static int uv__process_reqs(uv_loop_t* loop) {
|
||||
break;
|
||||
|
||||
case UV_SHUTDOWN:
|
||||
/* Tcp shutdown requests don't come here. */
|
||||
assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE);
|
||||
uv__process_pipe_shutdown_req(
|
||||
loop,
|
||||
(uv_pipe_t*) ((uv_shutdown_t*) req)->handle,
|
||||
(uv_shutdown_t*) req);
|
||||
DELEGATE_STREAM_REQ(loop, (uv_shutdown_t*) req, shutdown, handle);
|
||||
break;
|
||||
|
||||
case UV_UDP_RECV:
|
||||
@ -214,8 +209,6 @@ INLINE static int uv__process_reqs(uv_loop_t* loop) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* UV_WIN_REQ_INL_H_ */
|
||||
|
11
deps/libuv/src/win/stream.c
vendored
11
deps/libuv/src/win/stream.c
vendored
@ -29,7 +29,9 @@
|
||||
|
||||
int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
|
||||
int err;
|
||||
|
||||
if (uv__is_closing(stream)) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
err = ERROR_INVALID_PARAMETER;
|
||||
switch (stream->type) {
|
||||
case UV_TCP:
|
||||
@ -217,7 +219,12 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
|
||||
handle->reqs_pending++;
|
||||
REGISTER_HANDLE_REQ(loop, handle, req);
|
||||
|
||||
uv__want_endgame(loop, (uv_handle_t*)handle);
|
||||
if (handle->stream.conn.write_reqs_pending == 0) {
|
||||
if (handle->type == UV_NAMED_PIPE)
|
||||
uv__pipe_shutdown(loop, (uv_pipe_t*) handle, req);
|
||||
else
|
||||
uv__insert_pending_req(loop, (uv_req_t*) req);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
139
deps/libuv/src/win/tcp.c
vendored
139
deps/libuv/src/win/tcp.c
vendored
@ -205,73 +205,76 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
}
|
||||
|
||||
|
||||
void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
void uv__process_tcp_shutdown_req(uv_loop_t* loop, uv_tcp_t* stream, uv_shutdown_t *req) {
|
||||
int err;
|
||||
|
||||
assert(req);
|
||||
assert(stream->stream.conn.write_reqs_pending == 0);
|
||||
assert(!(stream->flags & UV_HANDLE_SHUT));
|
||||
assert(stream->flags & UV_HANDLE_CONNECTION);
|
||||
|
||||
stream->stream.conn.shutdown_req = NULL;
|
||||
stream->flags &= ~UV_HANDLE_SHUTTING;
|
||||
UNREGISTER_HANDLE_REQ(loop, stream, req);
|
||||
|
||||
err = 0;
|
||||
if (stream->flags & UV_HANDLE_CLOSING)
|
||||
/* The user destroyed the stream before we got to do the shutdown. */
|
||||
err = UV_ECANCELED;
|
||||
else if (shutdown(stream->socket, SD_SEND) == SOCKET_ERROR)
|
||||
err = uv_translate_sys_error(WSAGetLastError());
|
||||
else /* Success. */
|
||||
stream->flags |= UV_HANDLE_SHUT;
|
||||
|
||||
if (req->cb)
|
||||
req->cb(req, err);
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(stream);
|
||||
}
|
||||
|
||||
|
||||
void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
unsigned int i;
|
||||
uv_tcp_accept_t* req;
|
||||
|
||||
if (handle->flags & UV_HANDLE_CONNECTION &&
|
||||
handle->stream.conn.shutdown_req != NULL &&
|
||||
handle->stream.conn.write_reqs_pending == 0) {
|
||||
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||
assert(handle->reqs_pending == 0);
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
assert(handle->socket == INVALID_SOCKET);
|
||||
|
||||
UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
|
||||
|
||||
err = 0;
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
err = ERROR_OPERATION_ABORTED;
|
||||
} else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) {
|
||||
err = WSAGetLastError();
|
||||
}
|
||||
|
||||
if (handle->stream.conn.shutdown_req->cb) {
|
||||
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req,
|
||||
uv_translate_sys_error(err));
|
||||
}
|
||||
|
||||
handle->stream.conn.shutdown_req = NULL;
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
handle->reqs_pending == 0) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
assert(handle->socket == INVALID_SOCKET);
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) {
|
||||
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
|
||||
req = &handle->tcp.serv.accept_reqs[i];
|
||||
if (req->wait_handle != INVALID_HANDLE_VALUE) {
|
||||
UnregisterWait(req->wait_handle);
|
||||
req->wait_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (req->event_handle != NULL) {
|
||||
CloseHandle(req->event_handle);
|
||||
req->event_handle = NULL;
|
||||
}
|
||||
if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) {
|
||||
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
|
||||
req = &handle->tcp.serv.accept_reqs[i];
|
||||
if (req->wait_handle != INVALID_HANDLE_VALUE) {
|
||||
UnregisterWait(req->wait_handle);
|
||||
req->wait_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (req->event_handle != NULL) {
|
||||
CloseHandle(req->event_handle);
|
||||
req->event_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uv__free(handle->tcp.serv.accept_reqs);
|
||||
handle->tcp.serv.accept_reqs = NULL;
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_CONNECTION &&
|
||||
handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
|
||||
UnregisterWait(handle->read_req.wait_handle);
|
||||
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (handle->read_req.event_handle != NULL) {
|
||||
CloseHandle(handle->read_req.event_handle);
|
||||
handle->read_req.event_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uv__handle_close(handle);
|
||||
loop->active_tcp_streams--;
|
||||
uv__free(handle->tcp.serv.accept_reqs);
|
||||
handle->tcp.serv.accept_reqs = NULL;
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_CONNECTION &&
|
||||
handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
|
||||
UnregisterWait(handle->read_req.wait_handle);
|
||||
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (handle->read_req.event_handle != NULL) {
|
||||
CloseHandle(handle->read_req.event_handle);
|
||||
handle->read_req.event_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uv__handle_close(handle);
|
||||
loop->active_tcp_streams--;
|
||||
}
|
||||
|
||||
|
||||
@ -1160,9 +1163,10 @@ void uv__process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
closesocket(handle->socket);
|
||||
handle->socket = INVALID_SOCKET;
|
||||
}
|
||||
if (handle->stream.conn.shutdown_req != NULL) {
|
||||
uv__want_endgame(loop, (uv_handle_t*)handle);
|
||||
}
|
||||
if (handle->flags & UV_HANDLE_SHUTTING)
|
||||
uv__process_tcp_shutdown_req(loop,
|
||||
handle,
|
||||
handle->stream.conn.shutdown_req);
|
||||
}
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
@ -1411,7 +1415,7 @@ static void uv__tcp_try_cancel_reqs(uv_tcp_t* tcp) {
|
||||
int writing;
|
||||
|
||||
socket = tcp->socket;
|
||||
reading = tcp->flags & UV_HANDLE_READING;
|
||||
reading = tcp->flags & UV_HANDLE_READ_PENDING;
|
||||
writing = tcp->stream.conn.write_reqs_pending > 0;
|
||||
if (!reading && !writing)
|
||||
return;
|
||||
@ -1458,10 +1462,10 @@ static void uv__tcp_try_cancel_reqs(uv_tcp_t* tcp) {
|
||||
|
||||
void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
|
||||
if (tcp->flags & UV_HANDLE_CONNECTION) {
|
||||
uv__tcp_try_cancel_reqs(tcp);
|
||||
if (tcp->flags & UV_HANDLE_READING) {
|
||||
uv_read_stop((uv_stream_t*) tcp);
|
||||
}
|
||||
uv__tcp_try_cancel_reqs(tcp);
|
||||
} else {
|
||||
if (tcp->tcp.serv.accept_reqs != NULL) {
|
||||
/* First close the incoming sockets to cancel the accept operations before
|
||||
@ -1483,6 +1487,9 @@ void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
|
||||
DECREASE_ACTIVE_COUNT(loop, tcp);
|
||||
}
|
||||
|
||||
tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
uv__handle_closing(tcp);
|
||||
|
||||
/* If any overlapped req failed to cancel, calling `closesocket` now would
|
||||
* cause Win32 to send an RST packet. Try to avoid that for writes, if
|
||||
* possibly applicable, by waiting to process the completion notifications
|
||||
@ -1494,12 +1501,8 @@ void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
|
||||
tcp->socket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
uv__handle_closing(tcp);
|
||||
|
||||
if (tcp->reqs_pending == 0) {
|
||||
uv__want_endgame(tcp->loop, (uv_handle_t*)tcp);
|
||||
}
|
||||
if (tcp->reqs_pending == 0)
|
||||
uv__want_endgame(loop, (uv_handle_t*) tcp);
|
||||
}
|
||||
|
||||
|
||||
|
68
deps/libuv/src/win/tty.c
vendored
68
deps/libuv/src/win/tty.c
vendored
@ -2237,11 +2237,13 @@ void uv__process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
|
||||
req->cb(req, uv_translate_sys_error(err));
|
||||
}
|
||||
|
||||
|
||||
handle->stream.conn.write_reqs_pending--;
|
||||
if (handle->stream.conn.shutdown_req != NULL &&
|
||||
handle->stream.conn.write_reqs_pending == 0) {
|
||||
uv__want_endgame(loop, (uv_handle_t*)handle);
|
||||
}
|
||||
if (handle->stream.conn.write_reqs_pending == 0)
|
||||
if (handle->flags & UV_HANDLE_SHUTTING)
|
||||
uv__process_tty_shutdown_req(loop,
|
||||
handle,
|
||||
handle->stream.conn.shutdown_req);
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
}
|
||||
@ -2262,43 +2264,43 @@ void uv__tty_close(uv_tty_t* handle) {
|
||||
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
uv__handle_closing(handle);
|
||||
|
||||
if (handle->reqs_pending == 0) {
|
||||
if (handle->reqs_pending == 0)
|
||||
uv__want_endgame(handle->loop, (uv_handle_t*) handle);
|
||||
}
|
||||
|
||||
|
||||
void uv__process_tty_shutdown_req(uv_loop_t* loop, uv_tty_t* stream, uv_shutdown_t* req) {
|
||||
assert(stream->stream.conn.write_reqs_pending == 0);
|
||||
assert(req);
|
||||
|
||||
stream->stream.conn.shutdown_req = NULL;
|
||||
stream->flags &= ~UV_HANDLE_SHUTTING;
|
||||
UNREGISTER_HANDLE_REQ(loop, stream, req);
|
||||
|
||||
/* TTY shutdown is really just a no-op */
|
||||
if (req->cb) {
|
||||
if (stream->flags & UV_HANDLE_CLOSING) {
|
||||
req->cb(req, UV_ECANCELED);
|
||||
} else {
|
||||
req->cb(req, 0);
|
||||
}
|
||||
}
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(stream);
|
||||
}
|
||||
|
||||
|
||||
void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
|
||||
if (!(handle->flags & UV_HANDLE_TTY_READABLE) &&
|
||||
handle->stream.conn.shutdown_req != NULL &&
|
||||
handle->stream.conn.write_reqs_pending == 0) {
|
||||
UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
|
||||
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||
assert(handle->reqs_pending == 0);
|
||||
|
||||
/* TTY shutdown is really just a no-op */
|
||||
if (handle->stream.conn.shutdown_req->cb) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED);
|
||||
} else {
|
||||
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0);
|
||||
}
|
||||
}
|
||||
/* The wait handle used for raw reading should be unregistered when the
|
||||
* wait callback runs. */
|
||||
assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
|
||||
handle->tty.rd.read_raw_wait == NULL);
|
||||
|
||||
handle->stream.conn.shutdown_req = NULL;
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
handle->reqs_pending == 0) {
|
||||
/* The wait handle used for raw reading should be unregistered when the
|
||||
* wait callback runs. */
|
||||
assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
|
||||
handle->tty.rd.read_raw_wait == NULL);
|
||||
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
uv__handle_close(handle);
|
||||
}
|
||||
|
||||
|
||||
|
5
deps/libuv/src/win/udp.c
vendored
5
deps/libuv/src/win/udp.c
vendored
@ -1087,7 +1087,7 @@ int uv__udp_disconnect(uv_udp_t* handle) {
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
err = connect(handle->socket, &addr, sizeof(addr));
|
||||
err = connect(handle->socket, (struct sockaddr*) &addr, sizeof(addr));
|
||||
if (err)
|
||||
return uv_translate_sys_error(WSAGetLastError());
|
||||
|
||||
@ -1146,6 +1146,7 @@ int uv__udp_try_send(uv_udp_t* handle,
|
||||
err = uv__convert_to_localhost_if_unspecified(addr, &converted);
|
||||
if (err)
|
||||
return err;
|
||||
addr = (const struct sockaddr*) &converted;
|
||||
}
|
||||
|
||||
/* Already sending a message.*/
|
||||
@ -1169,7 +1170,7 @@ int uv__udp_try_send(uv_udp_t* handle,
|
||||
nbufs,
|
||||
&bytes,
|
||||
0,
|
||||
(const struct sockaddr*) &converted,
|
||||
addr,
|
||||
addrlen,
|
||||
NULL,
|
||||
NULL);
|
||||
|
132
deps/libuv/test/test-embed.c
vendored
132
deps/libuv/test/test-embed.c
vendored
@ -1,4 +1,4 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
@ -25,115 +25,55 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef HAVE_KQUEUE
|
||||
# if defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
# define HAVE_KQUEUE 1
|
||||
# endif
|
||||
#if !defined(_WIN32) && !defined(_AIX)
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_EPOLL
|
||||
# if defined(__linux__)
|
||||
# define HAVE_EPOLL 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
|
||||
|
||||
#if defined(HAVE_KQUEUE)
|
||||
# include <sys/types.h>
|
||||
# include <sys/event.h>
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EPOLL)
|
||||
# include <sys/epoll.h>
|
||||
#endif
|
||||
|
||||
static uv_thread_t embed_thread;
|
||||
static uv_sem_t embed_sem;
|
||||
static uv_timer_t embed_timer;
|
||||
static uv_async_t embed_async;
|
||||
static volatile int embed_closed;
|
||||
|
||||
static int embed_timer_called;
|
||||
static uv_async_t async;
|
||||
static uv_barrier_t barrier;
|
||||
|
||||
|
||||
static void embed_thread_runner(void* arg) {
|
||||
int r;
|
||||
int fd;
|
||||
int timeout;
|
||||
|
||||
while (!embed_closed) {
|
||||
fd = uv_backend_fd(uv_default_loop());
|
||||
timeout = uv_backend_timeout(uv_default_loop());
|
||||
|
||||
do {
|
||||
#if defined(HAVE_KQUEUE)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = timeout / 1000;
|
||||
ts.tv_nsec = (timeout % 1000) * 1000000;
|
||||
r = kevent(fd, NULL, 0, NULL, 0, &ts);
|
||||
#elif defined(HAVE_EPOLL)
|
||||
{
|
||||
struct epoll_event ev;
|
||||
r = epoll_wait(fd, &ev, 1, timeout);
|
||||
}
|
||||
#endif
|
||||
} while (r == -1 && errno == EINTR);
|
||||
uv_async_send(&embed_async);
|
||||
uv_sem_wait(&embed_sem);
|
||||
}
|
||||
static void thread_main(void* arg) {
|
||||
ASSERT_LE(0, uv_barrier_wait(&barrier));
|
||||
uv_sleep(250);
|
||||
ASSERT_EQ(0, uv_async_send(&async));
|
||||
}
|
||||
|
||||
|
||||
static void embed_cb(uv_async_t* async) {
|
||||
uv_run(uv_default_loop(), UV_RUN_ONCE);
|
||||
|
||||
uv_sem_post(&embed_sem);
|
||||
static void async_cb(uv_async_t* handle) {
|
||||
uv_close((uv_handle_t*) handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void embed_timer_cb(uv_timer_t* timer) {
|
||||
embed_timer_called++;
|
||||
embed_closed = 1;
|
||||
|
||||
uv_close((uv_handle_t*) &embed_async, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
TEST_IMPL(embed) {
|
||||
#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
|
||||
uv_loop_t external;
|
||||
uv_thread_t thread;
|
||||
uv_loop_t* loop;
|
||||
|
||||
ASSERT(0 == uv_loop_init(&external));
|
||||
loop = uv_default_loop();
|
||||
ASSERT_EQ(0, uv_async_init(loop, &async, async_cb));
|
||||
ASSERT_EQ(0, uv_barrier_init(&barrier, 2));
|
||||
ASSERT_EQ(0, uv_thread_create(&thread, thread_main, NULL));
|
||||
ASSERT_LE(0, uv_barrier_wait(&barrier));
|
||||
|
||||
embed_timer_called = 0;
|
||||
embed_closed = 0;
|
||||
|
||||
uv_async_init(&external, &embed_async, embed_cb);
|
||||
|
||||
/* Start timer in default loop */
|
||||
uv_timer_init(uv_default_loop(), &embed_timer);
|
||||
uv_timer_start(&embed_timer, embed_timer_cb, 250, 0);
|
||||
|
||||
/* Start worker that will interrupt external loop */
|
||||
uv_sem_init(&embed_sem, 0);
|
||||
uv_thread_create(&embed_thread, embed_thread_runner, NULL);
|
||||
|
||||
/* But run external loop */
|
||||
uv_run(&external, UV_RUN_DEFAULT);
|
||||
|
||||
uv_thread_join(&embed_thread);
|
||||
uv_loop_close(&external);
|
||||
|
||||
ASSERT(embed_timer_called == 1);
|
||||
while (uv_loop_alive(loop)) {
|
||||
#if defined(_WIN32) || defined(_AIX)
|
||||
ASSERT_LE(0, uv_run(loop, UV_RUN_ONCE));
|
||||
#else
|
||||
int rc;
|
||||
do {
|
||||
struct pollfd p;
|
||||
p.fd = uv_backend_fd(loop);
|
||||
p.events = POLLIN;
|
||||
p.revents = 0;
|
||||
rc = poll(&p, 1, uv_backend_timeout(loop));
|
||||
} while (rc == -1 && errno == EINTR);
|
||||
ASSERT_LE(0, uv_run(loop, UV_RUN_NOWAIT));
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSERT_EQ(0, uv_thread_join(&thread));
|
||||
uv_barrier_destroy(&barrier);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
60
deps/libuv/test/test-fs-event.c
vendored
60
deps/libuv/test/test-fs-event.c
vendored
@ -334,19 +334,8 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename,
|
||||
uv_close((uv_handle_t*)handle, close_cb);
|
||||
}
|
||||
|
||||
static void timer_cb_close_handle(uv_timer_t* timer) {
|
||||
uv_handle_t* handle;
|
||||
|
||||
ASSERT_NOT_NULL(timer);
|
||||
handle = timer->data;
|
||||
|
||||
uv_close((uv_handle_t*)timer, NULL);
|
||||
uv_close((uv_handle_t*)handle, close_cb);
|
||||
}
|
||||
|
||||
static void fs_event_cb_file_current_dir(uv_fs_event_t* handle,
|
||||
const char* filename, int events, int status) {
|
||||
ASSERT(fs_event_cb_called == 0);
|
||||
++fs_event_cb_called;
|
||||
|
||||
ASSERT(handle == &fs_event);
|
||||
@ -358,13 +347,7 @@ static void fs_event_cb_file_current_dir(uv_fs_event_t* handle,
|
||||
ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
|
||||
#endif
|
||||
|
||||
/* Regression test for SunOS: touch should generate just one event. */
|
||||
{
|
||||
static uv_timer_t timer;
|
||||
uv_timer_init(handle->loop, &timer);
|
||||
timer.data = handle;
|
||||
uv_timer_start(&timer, timer_cb_close_handle, 250, 0);
|
||||
}
|
||||
uv_close((uv_handle_t*)handle, close_cb);
|
||||
}
|
||||
|
||||
static void timer_cb_file(uv_timer_t* handle) {
|
||||
@ -738,7 +721,8 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(timer_cb_touch_called == 1);
|
||||
ASSERT(fs_event_cb_called == 1);
|
||||
/* FSEvents on macOS sometimes sends one change event, sometimes two. */
|
||||
ASSERT_NE(0, fs_event_cb_called);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
/* Cleanup */
|
||||
@ -923,6 +907,44 @@ TEST_IMPL(fs_event_close_with_pending_event) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_event_close_with_pending_delete_event) {
|
||||
#if defined(NO_FS_EVENTS)
|
||||
RETURN_SKIP(NO_FS_EVENTS);
|
||||
#endif
|
||||
uv_loop_t* loop;
|
||||
int r;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
create_dir("watch_dir");
|
||||
create_file("watch_dir/file");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir/file", 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Generate an fs event. */
|
||||
remove("watch_dir/file");
|
||||
|
||||
/* Allow time for the remove event to propagate to the pending list. */
|
||||
/* XXX - perhaps just for __sun? */
|
||||
uv_sleep(1100);
|
||||
uv_update_time(loop);
|
||||
|
||||
uv_close((uv_handle_t*)&fs_event, close_cb);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
/* Clean up */
|
||||
remove("watch_dir/");
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_event_close_in_callback) {
|
||||
#if defined(NO_FS_EVENTS)
|
||||
RETURN_SKIP(NO_FS_EVENTS);
|
||||
|
17
deps/libuv/test/test-getsockname.c
vendored
17
deps/libuv/test/test-getsockname.c
vendored
@ -30,8 +30,9 @@ static const int server_port = TEST_PORT;
|
||||
/* Will be updated right after making the uv_connect_call */
|
||||
static int connect_port = -1;
|
||||
|
||||
static int getsocknamecount = 0;
|
||||
static int getsocknamecount_tcp = 0;
|
||||
static int getpeernamecount = 0;
|
||||
static int getsocknamecount_udp = 0;
|
||||
|
||||
static uv_loop_t* loop;
|
||||
static uv_tcp_t tcp;
|
||||
@ -131,7 +132,7 @@ static void on_connection(uv_stream_t* server, int status) {
|
||||
r = uv_tcp_getsockname(handle, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "127.0.0.1", server_port, "accepted socket");
|
||||
getsocknamecount++;
|
||||
getsocknamecount_tcp++;
|
||||
|
||||
namelen = sizeof peername;
|
||||
r = uv_tcp_getpeername(handle, &peername, &namelen);
|
||||
@ -154,7 +155,7 @@ static void on_connect(uv_connect_t* req, int status) {
|
||||
r = uv_tcp_getsockname((uv_tcp_t*) req->handle, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "127.0.0.1", 0, "connected socket");
|
||||
getsocknamecount++;
|
||||
getsocknamecount_tcp++;
|
||||
|
||||
namelen = sizeof peername;
|
||||
r = uv_tcp_getpeername((uv_tcp_t*) req->handle, &peername, &namelen);
|
||||
@ -197,7 +198,7 @@ static int tcp_listener(void) {
|
||||
r = uv_tcp_getsockname(&tcpServer, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "0.0.0.0", server_port, "server socket");
|
||||
getsocknamecount++;
|
||||
getsocknamecount_tcp++;
|
||||
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getpeername(&tcpServer, &peername, &namelen);
|
||||
@ -256,7 +257,7 @@ static void udp_recv(uv_udp_t* handle,
|
||||
r = uv_udp_getsockname(&udp, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "0.0.0.0", 0, "udp receiving socket");
|
||||
getsocknamecount++;
|
||||
getsocknamecount_udp++;
|
||||
|
||||
uv_close((uv_handle_t*) &udp, NULL);
|
||||
uv_close((uv_handle_t*) handle, NULL);
|
||||
@ -293,7 +294,7 @@ static int udp_listener(void) {
|
||||
r = uv_udp_getsockname(&udpServer, &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
check_sockname(&sockname, "0.0.0.0", server_port, "udp listener socket");
|
||||
getsocknamecount++;
|
||||
getsocknamecount_udp++;
|
||||
|
||||
r = uv_udp_recv_start(&udpServer, alloc, udp_recv);
|
||||
ASSERT(r == 0);
|
||||
@ -333,7 +334,7 @@ TEST_IMPL(getsockname_tcp) {
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(getsocknamecount == 3);
|
||||
ASSERT(getsocknamecount_tcp == 3);
|
||||
ASSERT(getpeernamecount == 3);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
@ -351,7 +352,7 @@ TEST_IMPL(getsockname_udp) {
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(getsocknamecount == 2);
|
||||
ASSERT(getsocknamecount_udp == 2);
|
||||
|
||||
ASSERT(udp.send_queue_size == 0);
|
||||
ASSERT(udpServer.send_queue_size == 0);
|
||||
|
26
deps/libuv/test/test-idle.c
vendored
26
deps/libuv/test/test-idle.c
vendored
@ -97,3 +97,29 @@ TEST_IMPL(idle_starvation) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void idle_stop(uv_idle_t* handle) {
|
||||
uv_idle_stop(handle);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(idle_check) {
|
||||
ASSERT_EQ(0, uv_idle_init(uv_default_loop(), &idle_handle));
|
||||
ASSERT_EQ(0, uv_idle_start(&idle_handle, idle_stop));
|
||||
|
||||
ASSERT_EQ(0, uv_check_init(uv_default_loop(), &check_handle));
|
||||
ASSERT_EQ(0, uv_check_start(&check_handle, check_cb));
|
||||
|
||||
ASSERT_EQ(1, uv_run(uv_default_loop(), UV_RUN_ONCE));
|
||||
ASSERT_EQ(1, check_cb_called);
|
||||
|
||||
ASSERT_EQ(0, close_cb_called);
|
||||
uv_close((uv_handle_t*) &idle_handle, close_cb);
|
||||
uv_close((uv_handle_t*) &check_handle, close_cb);
|
||||
ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_ONCE));
|
||||
ASSERT_EQ(2, close_cb_called);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
24
deps/libuv/test/test-list.h
vendored
24
deps/libuv/test/test-list.h
vendored
@ -22,7 +22,6 @@
|
||||
#include "uv.h"
|
||||
|
||||
TEST_DECLARE (platform_output)
|
||||
TEST_DECLARE (callback_order)
|
||||
TEST_DECLARE (close_order)
|
||||
TEST_DECLARE (run_once)
|
||||
TEST_DECLARE (run_nowait)
|
||||
@ -123,15 +122,18 @@ TEST_DECLARE (tcp_bind_error_inval)
|
||||
TEST_DECLARE (tcp_bind_localhost_ok)
|
||||
TEST_DECLARE (tcp_bind_invalid_flags)
|
||||
TEST_DECLARE (tcp_bind_writable_flags)
|
||||
TEST_DECLARE (tcp_bind_or_listen_error_after_close)
|
||||
TEST_DECLARE (tcp_listen_without_bind)
|
||||
TEST_DECLARE (tcp_connect_error_fault)
|
||||
TEST_DECLARE (tcp_connect_timeout)
|
||||
TEST_DECLARE (tcp_local_connect_timeout)
|
||||
TEST_DECLARE (tcp6_local_connect_timeout)
|
||||
TEST_DECLARE (tcp_close_while_connecting)
|
||||
TEST_DECLARE (tcp_close_after_read_timeout)
|
||||
TEST_DECLARE (tcp_close)
|
||||
TEST_DECLARE (tcp_close_reset_accepted)
|
||||
TEST_DECLARE (tcp_close_reset_accepted_after_shutdown)
|
||||
TEST_DECLARE (tcp_close_reset_accepted_after_socket_shutdown)
|
||||
TEST_DECLARE (tcp_close_reset_client)
|
||||
TEST_DECLARE (tcp_close_reset_client_after_shutdown)
|
||||
TEST_DECLARE (tcp_create_early)
|
||||
@ -147,6 +149,7 @@ TEST_DECLARE (tcp_write_to_half_open_connection)
|
||||
TEST_DECLARE (tcp_unexpected_read)
|
||||
TEST_DECLARE (tcp_read_stop)
|
||||
TEST_DECLARE (tcp_read_stop_start)
|
||||
TEST_DECLARE (tcp_rst)
|
||||
TEST_DECLARE (tcp_bind6_error_addrinuse)
|
||||
TEST_DECLARE (tcp_bind6_error_addrnotavail)
|
||||
TEST_DECLARE (tcp_bind6_error_fault)
|
||||
@ -191,6 +194,7 @@ TEST_DECLARE (pipe_bind_error_addrnotavail)
|
||||
TEST_DECLARE (pipe_bind_error_inval)
|
||||
TEST_DECLARE (pipe_connect_multiple)
|
||||
TEST_DECLARE (pipe_listen_without_bind)
|
||||
TEST_DECLARE (pipe_bind_or_listen_error_after_close)
|
||||
TEST_DECLARE (pipe_connect_bad_name)
|
||||
TEST_DECLARE (pipe_connect_to_file)
|
||||
TEST_DECLARE (pipe_connect_on_prepare)
|
||||
@ -224,6 +228,7 @@ TEST_DECLARE (timer_is_closing)
|
||||
TEST_DECLARE (timer_null_callback)
|
||||
TEST_DECLARE (timer_early_check)
|
||||
TEST_DECLARE (idle_starvation)
|
||||
TEST_DECLARE (idle_check)
|
||||
TEST_DECLARE (loop_handles)
|
||||
TEST_DECLARE (get_loadavg)
|
||||
TEST_DECLARE (walk_handles)
|
||||
@ -318,6 +323,7 @@ TEST_DECLARE (spawn_inherit_streams)
|
||||
TEST_DECLARE (spawn_quoted_path)
|
||||
TEST_DECLARE (spawn_tcp_server)
|
||||
TEST_DECLARE (spawn_exercise_sigchld_issue)
|
||||
TEST_DECLARE (spawn_relative_path)
|
||||
TEST_DECLARE (fs_poll)
|
||||
TEST_DECLARE (fs_poll_getpath)
|
||||
TEST_DECLARE (fs_poll_close_request)
|
||||
@ -386,6 +392,7 @@ TEST_DECLARE (fs_event_no_callback_after_close)
|
||||
TEST_DECLARE (fs_event_no_callback_on_close)
|
||||
TEST_DECLARE (fs_event_immediate_close)
|
||||
TEST_DECLARE (fs_event_close_with_pending_event)
|
||||
TEST_DECLARE (fs_event_close_with_pending_delete_event)
|
||||
TEST_DECLARE (fs_event_close_in_callback)
|
||||
TEST_DECLARE (fs_event_start_and_close)
|
||||
TEST_DECLARE (fs_event_error_reporting)
|
||||
@ -422,6 +429,7 @@ TEST_DECLARE (fs_invalid_mkdir_name)
|
||||
#endif
|
||||
TEST_DECLARE (fs_get_system_error)
|
||||
TEST_DECLARE (strscpy)
|
||||
TEST_DECLARE (strtok)
|
||||
TEST_DECLARE (threadpool_queue_work_simple)
|
||||
TEST_DECLARE (threadpool_queue_work_einval)
|
||||
TEST_DECLARE (threadpool_multiple_event_loops)
|
||||
@ -541,9 +549,6 @@ TEST_DECLARE (metrics_idle_time_zero)
|
||||
TASK_LIST_START
|
||||
TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000)
|
||||
|
||||
#if 0
|
||||
TEST_ENTRY (callback_order)
|
||||
#endif
|
||||
TEST_ENTRY (test_macros)
|
||||
TEST_ENTRY (close_order)
|
||||
TEST_ENTRY (run_once)
|
||||
@ -695,15 +700,18 @@ TASK_LIST_START
|
||||
TEST_ENTRY (tcp_bind_localhost_ok)
|
||||
TEST_ENTRY (tcp_bind_invalid_flags)
|
||||
TEST_ENTRY (tcp_bind_writable_flags)
|
||||
TEST_ENTRY (tcp_bind_or_listen_error_after_close)
|
||||
TEST_ENTRY (tcp_listen_without_bind)
|
||||
TEST_ENTRY (tcp_connect_error_fault)
|
||||
TEST_ENTRY (tcp_connect_timeout)
|
||||
TEST_ENTRY (tcp_local_connect_timeout)
|
||||
TEST_ENTRY (tcp6_local_connect_timeout)
|
||||
TEST_ENTRY (tcp_close_while_connecting)
|
||||
TEST_ENTRY (tcp_close_after_read_timeout)
|
||||
TEST_ENTRY (tcp_close)
|
||||
TEST_ENTRY (tcp_close_reset_accepted)
|
||||
TEST_ENTRY (tcp_close_reset_accepted_after_shutdown)
|
||||
TEST_ENTRY (tcp_close_reset_accepted_after_socket_shutdown)
|
||||
TEST_ENTRY (tcp_close_reset_client)
|
||||
TEST_ENTRY (tcp_close_reset_client_after_shutdown)
|
||||
TEST_ENTRY (tcp_create_early)
|
||||
@ -723,6 +731,9 @@ TASK_LIST_START
|
||||
|
||||
TEST_ENTRY (tcp_read_stop_start)
|
||||
|
||||
TEST_ENTRY (tcp_rst)
|
||||
TEST_HELPER (tcp_rst, tcp4_echo_server)
|
||||
|
||||
TEST_ENTRY (tcp_bind6_error_addrinuse)
|
||||
TEST_ENTRY (tcp_bind6_error_addrnotavail)
|
||||
TEST_ENTRY (tcp_bind6_error_fault)
|
||||
@ -769,6 +780,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (pipe_bind_error_inval)
|
||||
TEST_ENTRY (pipe_connect_multiple)
|
||||
TEST_ENTRY (pipe_listen_without_bind)
|
||||
TEST_ENTRY (pipe_bind_or_listen_error_after_close)
|
||||
TEST_ENTRY (pipe_getsockname)
|
||||
TEST_ENTRY (pipe_getsockname_abstract)
|
||||
TEST_ENTRY (pipe_getsockname_blocking)
|
||||
@ -814,6 +826,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (timer_early_check)
|
||||
|
||||
TEST_ENTRY (idle_starvation)
|
||||
TEST_ENTRY (idle_check)
|
||||
|
||||
TEST_ENTRY (ref)
|
||||
TEST_ENTRY (idle_ref)
|
||||
@ -946,6 +959,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (spawn_quoted_path)
|
||||
TEST_ENTRY (spawn_tcp_server)
|
||||
TEST_ENTRY (spawn_exercise_sigchld_issue)
|
||||
TEST_ENTRY (spawn_relative_path)
|
||||
TEST_ENTRY (fs_poll)
|
||||
TEST_ENTRY (fs_poll_getpath)
|
||||
TEST_ENTRY (fs_poll_close_request)
|
||||
@ -1048,6 +1062,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (fs_event_no_callback_on_close)
|
||||
TEST_ENTRY (fs_event_immediate_close)
|
||||
TEST_ENTRY (fs_event_close_with_pending_event)
|
||||
TEST_ENTRY (fs_event_close_with_pending_delete_event)
|
||||
TEST_ENTRY (fs_event_close_in_callback)
|
||||
TEST_ENTRY (fs_event_start_and_close)
|
||||
TEST_ENTRY_CUSTOM (fs_event_error_reporting, 0, 0, 60000)
|
||||
@ -1084,6 +1099,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (get_osfhandle_valid_handle)
|
||||
TEST_ENTRY (open_osfhandle_valid_handle)
|
||||
TEST_ENTRY (strscpy)
|
||||
TEST_ENTRY (strtok)
|
||||
TEST_ENTRY (threadpool_queue_work_simple)
|
||||
TEST_ENTRY (threadpool_queue_work_einval)
|
||||
TEST_ENTRY_CUSTOM (threadpool_multiple_event_loops, 0, 0, 60000)
|
||||
|
16
deps/libuv/test/test-pipe-bind-error.c
vendored
16
deps/libuv/test/test-pipe-bind-error.c
vendored
@ -137,3 +137,19 @@ TEST_IMPL(pipe_listen_without_bind) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(pipe_bind_or_listen_error_after_close) {
|
||||
uv_pipe_t server;
|
||||
|
||||
ASSERT_EQ(uv_pipe_init(uv_default_loop(), &server, 0), 0);
|
||||
uv_close((uv_handle_t*) &server, NULL);
|
||||
|
||||
ASSERT_EQ(uv_pipe_bind(&server, TEST_PIPENAME), UV_EINVAL);
|
||||
|
||||
ASSERT_EQ(uv_listen((uv_stream_t*) &server, SOMAXCONN, NULL), UV_EINVAL);
|
||||
|
||||
ASSERT_EQ(uv_run(uv_default_loop(), UV_RUN_DEFAULT), 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
3
deps/libuv/test/test-pipe-set-non-blocking.c
vendored
3
deps/libuv/test/test-pipe-set-non-blocking.c
vendored
@ -102,8 +102,7 @@ TEST_IMPL(pipe_set_non_blocking) {
|
||||
ASSERT(n == UV_EAGAIN); /* E_NOTIMPL */
|
||||
ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &pipe_handle, &buf, 1, write_cb));
|
||||
ASSERT_NOT_NULL(write_req.handle);
|
||||
ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* queue write_cb */
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* process write_cb */
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
|
||||
ASSERT_NULL(write_req.handle); /* check for signaled completion of write_cb */
|
||||
n = buf.len;
|
||||
#endif
|
||||
|
37
deps/libuv/test/test-spawn.c
vendored
37
deps/libuv/test/test-spawn.c
vendored
@ -1675,9 +1675,6 @@ TEST_IMPL(closed_fd_events) {
|
||||
ASSERT(req.result == 1);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
#ifdef _WIN32
|
||||
ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_ONCE));
|
||||
#endif
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
|
||||
|
||||
/* should have received just one byte */
|
||||
@ -1981,3 +1978,37 @@ void spawn_stdin_stdout(void) {
|
||||
}
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
TEST_IMPL(spawn_relative_path) {
|
||||
char* sep;
|
||||
|
||||
init_process_options("spawn_helper1", exit_cb);
|
||||
|
||||
exepath_size = sizeof(exepath) - 2;
|
||||
ASSERT_EQ(0, uv_exepath(exepath, &exepath_size));
|
||||
exepath[exepath_size] = '\0';
|
||||
|
||||
/* Poor man's basename(3). */
|
||||
sep = strrchr(exepath, '/');
|
||||
if (sep == NULL)
|
||||
sep = strrchr(exepath, '\\');
|
||||
ASSERT_NOT_NULL(sep);
|
||||
|
||||
/* Split into dirname and basename and make basename relative. */
|
||||
memmove(sep + 2, sep, 1 + strlen(sep));
|
||||
sep[0] = '\0';
|
||||
sep[1] = '.';
|
||||
sep[2] = '/';
|
||||
|
||||
options.cwd = exepath;
|
||||
options.file = options.args[0] = sep + 1;
|
||||
|
||||
ASSERT_EQ(0, uv_spawn(uv_default_loop(), &process, &options));
|
||||
ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
|
||||
ASSERT_EQ(1, exit_cb_called);
|
||||
ASSERT_EQ(1, close_cb_called);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
90
deps/libuv/test/test-strtok.c
vendored
Normal file
90
deps/libuv/test/test-strtok.c
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "../src/strtok.h"
|
||||
#include "../src/strtok.c"
|
||||
|
||||
struct strtok_test_case {
|
||||
const char* str;
|
||||
const char* sep;
|
||||
};
|
||||
|
||||
const char* tokens[] = {
|
||||
"abc",
|
||||
NULL,
|
||||
|
||||
"abc",
|
||||
"abf",
|
||||
NULL,
|
||||
|
||||
"This",
|
||||
"is.a",
|
||||
"test",
|
||||
"of",
|
||||
"the",
|
||||
"string",
|
||||
"tokenizer",
|
||||
"function.",
|
||||
NULL,
|
||||
|
||||
"Hello",
|
||||
"This-is-a-nice",
|
||||
"-string",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define ASSERT_STRCMP(x, y) \
|
||||
ASSERT((x != NULL && y != NULL && strcmp(x, y) == 0) || (x == y && x == NULL))
|
||||
|
||||
TEST_IMPL(strtok) {
|
||||
struct strtok_test_case tests[] = {
|
||||
{ "abc", "" },
|
||||
{ "abc.abf", "." },
|
||||
{ "This;is.a:test:of=the/string\\tokenizer-function.", "\\/:;=-" },
|
||||
{ "Hello This-is-a-nice.-string", " ." },
|
||||
};
|
||||
size_t tokens_len = ARRAY_SIZE(tokens);
|
||||
size_t tests_len = ARRAY_SIZE(tests);
|
||||
size_t i;
|
||||
size_t j;
|
||||
char* itr;
|
||||
char* tok_r;
|
||||
char current_test[2048];
|
||||
|
||||
for (i = 0, j = 0; i < tests_len; i += 1) {
|
||||
ASSERT(j < tokens_len);
|
||||
snprintf(current_test, sizeof(current_test), "%s", tests[i].str);
|
||||
tok_r = uv__strtok(current_test, tests[i].sep, &itr);
|
||||
ASSERT_STRCMP(tok_r, tokens[j]);
|
||||
j++;
|
||||
while (tok_r) {
|
||||
ASSERT(j < tokens_len);
|
||||
tok_r = uv__strtok(NULL, tests[i].sep, &itr);
|
||||
ASSERT_STRCMP(tok_r, tokens[j]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
18
deps/libuv/test/test-tcp-bind-error.c
vendored
18
deps/libuv/test/test-tcp-bind-error.c
vendored
@ -297,3 +297,21 @@ TEST_IMPL(tcp_bind_writable_flags) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(tcp_bind_or_listen_error_after_close) {
|
||||
uv_tcp_t tcp;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addr.sin_port = htons(9999);
|
||||
addr.sin_family = AF_INET;
|
||||
|
||||
ASSERT_EQ(uv_tcp_init(uv_default_loop(), &tcp), 0);
|
||||
uv_close((uv_handle_t*) &tcp, NULL);
|
||||
ASSERT_EQ(uv_tcp_bind(&tcp, (struct sockaddr*) &addr, 0), UV_EINVAL);
|
||||
ASSERT_EQ(uv_listen((uv_stream_t*) &tcp, 5, NULL), UV_EINVAL);
|
||||
ASSERT_EQ(uv_run(uv_default_loop(), UV_RUN_DEFAULT), 0);
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
183
deps/libuv/test/test-tcp-close-after-read-timeout.c
vendored
Normal file
183
deps/libuv/test/test-tcp-close-after-read-timeout.c
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
/* 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"
|
||||
|
||||
static uv_tcp_t client;
|
||||
static uv_tcp_t connection;
|
||||
static uv_connect_t connect_req;
|
||||
static uv_timer_t timer;
|
||||
|
||||
static int read_cb_called;
|
||||
static int on_close_called;
|
||||
|
||||
static void on_connection(uv_stream_t* server, int status);
|
||||
|
||||
static void on_client_connect(uv_connect_t* req, int status);
|
||||
static void on_client_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf);
|
||||
static void on_client_read(uv_stream_t* stream,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf);
|
||||
static void on_client_timeout(uv_timer_t* handle);
|
||||
|
||||
static void on_close(uv_handle_t* handle);
|
||||
|
||||
|
||||
static void on_client_connect(uv_connect_t* conn_req, int status) {
|
||||
int r;
|
||||
|
||||
r = uv_read_start((uv_stream_t*) &client, on_client_alloc, on_client_read);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_timer_start(&timer, on_client_timeout, 1000, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
}
|
||||
|
||||
|
||||
static void on_client_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
static char slab[8];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void on_client_read(uv_stream_t* stream, ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
ASSERT_LT(nread, 0);
|
||||
read_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void on_client_timeout(uv_timer_t* handle) {
|
||||
ASSERT_EQ(handle, &timer);
|
||||
ASSERT_EQ(read_cb_called, 0);
|
||||
uv_read_stop((uv_stream_t*) &client);
|
||||
uv_close((uv_handle_t*) &client, on_close);
|
||||
uv_close((uv_handle_t*) &timer, on_close);
|
||||
}
|
||||
|
||||
|
||||
static void on_connection_alloc(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
static char slab[8];
|
||||
buf->base = slab;
|
||||
buf->len = sizeof(slab);
|
||||
}
|
||||
|
||||
|
||||
static void on_connection_read(uv_stream_t* stream,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
ASSERT_EQ(nread, UV_EOF);
|
||||
read_cb_called++;
|
||||
uv_close((uv_handle_t*) stream, on_close);
|
||||
}
|
||||
|
||||
|
||||
static void on_connection(uv_stream_t* server, int status) {
|
||||
int r;
|
||||
|
||||
ASSERT_EQ(status, 0);
|
||||
ASSERT_EQ(uv_accept(server, (uv_stream_t*) &connection), 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*) &connection,
|
||||
on_connection_alloc,
|
||||
on_connection_read);
|
||||
ASSERT_EQ(r, 0);
|
||||
}
|
||||
|
||||
|
||||
static void on_close(uv_handle_t* handle) {
|
||||
ASSERT(handle == (uv_handle_t*) &client ||
|
||||
handle == (uv_handle_t*) &connection ||
|
||||
handle == (uv_handle_t*) &timer);
|
||||
on_close_called++;
|
||||
}
|
||||
|
||||
|
||||
static void start_server(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT_EQ(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr), 0);
|
||||
|
||||
r = uv_tcp_init(loop, handle);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_bind(handle, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*) handle, 128, on_connection);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_unref((uv_handle_t*) handle);
|
||||
}
|
||||
|
||||
|
||||
/* Check that pending write requests have their callbacks
|
||||
* invoked when the handle is closed.
|
||||
*/
|
||||
TEST_IMPL(tcp_close_after_read_timeout) {
|
||||
struct sockaddr_in addr;
|
||||
uv_tcp_t tcp_server;
|
||||
uv_loop_t* loop;
|
||||
int r;
|
||||
|
||||
ASSERT_EQ(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr), 0);
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
/* We can't use the echo server, it doesn't handle ECONNRESET. */
|
||||
start_server(loop, &tcp_server);
|
||||
|
||||
r = uv_tcp_init(loop, &client);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_connect(&connect_req,
|
||||
&client,
|
||||
(const struct sockaddr*) &addr,
|
||||
on_client_connect);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_init(loop, &connection);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(read_cb_called, 0);
|
||||
ASSERT_EQ(on_close_called, 0);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(read_cb_called, 1);
|
||||
ASSERT_EQ(on_close_called, 3);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
46
deps/libuv/test/test-tcp-close-reset.c
vendored
46
deps/libuv/test/test-tcp-close-reset.c
vendored
@ -25,6 +25,12 @@
|
||||
#include <errno.h>
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#ifdef _WIN32
|
||||
# define INVALID_FD (INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
# define INVALID_FD (-1)
|
||||
#endif
|
||||
|
||||
static uv_loop_t* loop;
|
||||
static uv_tcp_t tcp_server;
|
||||
static uv_tcp_t tcp_client;
|
||||
@ -62,9 +68,22 @@ static void do_write(uv_tcp_t* handle) {
|
||||
|
||||
|
||||
static void do_close(uv_tcp_t* handle) {
|
||||
uv_os_fd_t fd;
|
||||
int r;
|
||||
|
||||
if (shutdown_before_close == 1) {
|
||||
ASSERT(0 == uv_shutdown(&shutdown_req, (uv_stream_t*) handle, shutdown_cb));
|
||||
ASSERT(UV_EINVAL == uv_tcp_close_reset(handle, close_cb));
|
||||
} else if (shutdown_before_close == 2) {
|
||||
r = uv_fileno((const uv_handle_t*) handle, &fd);
|
||||
ASSERT_EQ(r, 0);
|
||||
ASSERT_NE(fd, INVALID_FD);
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(0, shutdown(fd, SD_BOTH));
|
||||
#else
|
||||
ASSERT_EQ(0, shutdown(fd, SHUT_RDWR));
|
||||
#endif
|
||||
ASSERT_EQ(0, uv_tcp_close_reset(handle, close_cb));
|
||||
} else {
|
||||
ASSERT(0 == uv_tcp_close_reset(handle, close_cb));
|
||||
ASSERT(UV_ENOTCONN == uv_shutdown(&shutdown_req, (uv_stream_t*) handle, shutdown_cb));
|
||||
@ -288,3 +307,30 @@ TEST_IMPL(tcp_close_reset_accepted_after_shutdown) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(tcp_close_reset_accepted_after_socket_shutdown) {
|
||||
int r;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
start_server(loop, &tcp_server);
|
||||
|
||||
client_close = 0;
|
||||
shutdown_before_close = 2;
|
||||
|
||||
do_connect(loop, &tcp_client);
|
||||
|
||||
ASSERT_EQ(write_cb_called, 0);
|
||||
ASSERT_EQ(close_cb_called, 0);
|
||||
ASSERT_EQ(shutdown_cb_called, 0);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
ASSERT_EQ(write_cb_called, 4);
|
||||
ASSERT_EQ(close_cb_called, 1);
|
||||
ASSERT_EQ(shutdown_cb_called, 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
107
deps/libuv/test/test-tcp-rst.c
vendored
Normal file
107
deps/libuv/test/test-tcp-rst.c
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/* 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"
|
||||
|
||||
static uv_tcp_t tcp;
|
||||
static uv_connect_t connect_req;
|
||||
static uv_buf_t qbuf;
|
||||
static int called_alloc_cb;
|
||||
static int called_connect_cb;
|
||||
static int called_close_cb;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle == (uv_handle_t*) &tcp);
|
||||
called_close_cb++;
|
||||
}
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
buf->base = malloc(size);
|
||||
buf->len = size;
|
||||
called_alloc_cb++;
|
||||
}
|
||||
|
||||
|
||||
static void read_cb(uv_stream_t* t, ssize_t nread, const uv_buf_t* buf) {
|
||||
ASSERT_PTR_EQ((uv_tcp_t*) t, &tcp);
|
||||
ASSERT_EQ(nread, UV_ECONNRESET);
|
||||
|
||||
int fd;
|
||||
ASSERT_EQ(0, uv_fileno((uv_handle_t*) t, &fd));
|
||||
uv_handle_type type = uv_guess_handle(fd);
|
||||
ASSERT_EQ(type, UV_TCP);
|
||||
|
||||
uv_close((uv_handle_t *) t, close_cb);
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t *req, int status) {
|
||||
ASSERT_EQ(status, 0);
|
||||
ASSERT_PTR_EQ(req, &connect_req);
|
||||
|
||||
/* Start reading from the connection so we receive the RST in uv__read. */
|
||||
ASSERT_EQ(0, uv_read_start((uv_stream_t*) &tcp, alloc_cb, read_cb));
|
||||
|
||||
/* Write 'QSH' to receive RST from the echo server. */
|
||||
ASSERT_EQ(qbuf.len, uv_try_write((uv_stream_t*) &tcp, &qbuf, 1));
|
||||
|
||||
called_connect_cb++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This test has a client which connects to the echo_server and receives TCP
|
||||
* RST. Test checks that uv_guess_handle still works on a reset TCP handle.
|
||||
*/
|
||||
TEST_IMPL(tcp_rst) {
|
||||
#ifndef _WIN32
|
||||
struct sockaddr_in server_addr;
|
||||
int r;
|
||||
|
||||
qbuf.base = "QSH";
|
||||
qbuf.len = 3;
|
||||
|
||||
ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
r = uv_tcp_connect(&connect_req,
|
||||
&tcp,
|
||||
(const struct sockaddr*) &server_addr,
|
||||
connect_cb);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT_EQ(called_alloc_cb, 1);
|
||||
ASSERT_EQ(called_connect_cb, 1);
|
||||
ASSERT_EQ(called_close_cb, 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
#else
|
||||
RETURN_SKIP("Unix only test");
|
||||
#endif
|
||||
}
|
27
deps/libuv/test/test-timer.c
vendored
27
deps/libuv/test/test-timer.c
vendored
@ -25,6 +25,8 @@
|
||||
|
||||
static int once_cb_called = 0;
|
||||
static int once_close_cb_called = 0;
|
||||
static int twice_cb_called = 0;
|
||||
static int twice_close_cb_called = 0;
|
||||
static int repeat_cb_called = 0;
|
||||
static int repeat_close_cb_called = 0;
|
||||
static int order_cb_called = 0;
|
||||
@ -58,6 +60,27 @@ static void once_cb(uv_timer_t* handle) {
|
||||
uv_update_time(uv_default_loop());
|
||||
}
|
||||
|
||||
static void twice_close_cb(uv_handle_t* handle) {
|
||||
printf("TWICE_CLOSE_CB\n");
|
||||
|
||||
ASSERT_NOT_NULL(handle);
|
||||
ASSERT(0 == uv_is_active(handle));
|
||||
|
||||
twice_close_cb_called++;
|
||||
}
|
||||
|
||||
static void twice_cb(uv_timer_t* handle) {
|
||||
printf("TWICE_CB %d\n", twice_cb_called);
|
||||
|
||||
ASSERT_NOT_NULL(handle);
|
||||
ASSERT(0 == uv_is_active((uv_handle_t*) handle));
|
||||
|
||||
twice_cb_called++;
|
||||
|
||||
uv_close((uv_handle_t*)handle, twice_close_cb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void repeat_close_cb(uv_handle_t* handle) {
|
||||
printf("REPEAT_CLOSE_CB\n");
|
||||
@ -144,12 +167,12 @@ TEST_IMPL(timer_start_twice) {
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_start(&once, never_cb, 86400 * 1000, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_start(&once, once_cb, 10, 0);
|
||||
r = uv_timer_start(&once, twice_cb, 10, 0);
|
||||
ASSERT(r == 0);
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(once_cb_called == 1);
|
||||
ASSERT(twice_cb_called == 1);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
|
4
deps/libuv/test/test-udp-connect.c
vendored
4
deps/libuv/test/test-udp-connect.c
vendored
@ -98,10 +98,6 @@ static void sv_recv_cb(uv_udp_t* handle,
|
||||
|
||||
|
||||
TEST_IMPL(udp_connect) {
|
||||
#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_in ext_addr;
|
||||
struct sockaddr_in tmp_addr;
|
||||
|
4
deps/libuv/test/test-udp-connect6.c
vendored
4
deps/libuv/test/test-udp-connect6.c
vendored
@ -98,10 +98,6 @@ static void sv_recv_cb(uv_udp_t* handle,
|
||||
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user