mirror of
https://gitee.com/openharmony/third_party_libuv
synced 2025-01-13 16:21:48 +00:00
libuv升级1.44.1
Signed-off-by: kangchongtao <kangchongtao@huawei.com>
This commit is contained in:
parent
678a8063d9
commit
e1f9253c81
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@ -2,7 +2,7 @@
|
||||
If you want to report a bug, you are in the right place!
|
||||
|
||||
If you need help or have a question, go here:
|
||||
https://github.com/libuv/help/issues/new
|
||||
https://github.com/libuv/libuv/discussions
|
||||
|
||||
If you are reporting a libuv test failure, please ensure that you are not
|
||||
running the test as root.
|
||||
|
7
.github/stale.yml
vendored
7
.github/stale.yml
vendored
@ -1,9 +1,9 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 21
|
||||
daysUntilStale: 28
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
# Set to false to disable. If disabled, issues still need to be closed
|
||||
# manually, but will remain marked as stale.
|
||||
daysUntilClose: 120
|
||||
daysUntilClose: false
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- v2
|
||||
@ -18,7 +18,6 @@ staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
recent activity. Thank you for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
|
118
.github/workflows/CI.yml
vendored
Normal file
118
.github/workflows/CI.yml
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: windows-${{ matrix.config.server }}
|
||||
name: build-${{ matrix.config.toolchain}}-${{ matrix.config.arch}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {toolchain: Visual Studio 15 2017, arch: Win32, server: 2016}
|
||||
- {toolchain: Visual Studio 15 2017, arch: x64, server: 2016}
|
||||
- {toolchain: Visual Studio 16 2019, arch: Win32, server: 2019}
|
||||
- {toolchain: Visual Studio 16 2019, arch: x64, server: 2019}
|
||||
- {toolchain: Visual Studio 17 2022, arch: Win32, server: 2022}
|
||||
- {toolchain: Visual Studio 17 2022, arch: x64, server: 2022}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DBUILD_TESTING=ON -G "${{ matrix.config.toolchain }}" -A ${{ matrix.config.arch }}
|
||||
cmake --build .
|
||||
- name: Test
|
||||
shell: cmd
|
||||
run: |
|
||||
cd build
|
||||
ctest -C Debug --output-on-failure
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
container: reactnativecommunity/react-native-android:2020-5-20
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Build 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 ..
|
||||
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake --build .
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-10.15
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Setup
|
||||
run: |
|
||||
brew install ninja
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build && cmake .. -DBUILD_TESTING=ON -G Ninja
|
||||
cmake --build .
|
||||
ls -lh
|
||||
- name: Test
|
||||
run: |
|
||||
cd build && ctest -V
|
||||
|
||||
build-cross-qemu:
|
||||
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: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build && cmake .. -DBUILD_TESTING=ON -DQEMU=ON -DCMAKE_C_COMPILER=${{ matrix.config.cc }}
|
||||
cmake --build .
|
||||
ls -lh
|
||||
- name: Test
|
||||
run: |
|
||||
${{ matrix.config.qemu }} build/uv_run_tests_a
|
26
.github/workflows/sanitizer.yml
vendored
Normal file
26
.github/workflows/sanitizer.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: Sanitizer checks
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
sanitizers:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup
|
||||
run: |
|
||||
sudo apt-get install ninja-build
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: TSAN
|
||||
run: |
|
||||
mkdir build-tsan
|
||||
(cd build-tsan && cmake .. -G Ninja -DBUILD_TESTING=ON -DTSAN=ON -DCMAKE_BUILD_TYPE=Release)
|
||||
cmake --build build-tsan
|
||||
./build-tsan/uv_run_tests_a || true # currently permit failures
|
||||
- name: ASAN
|
||||
run: |
|
||||
mkdir build-asan
|
||||
(cd build-asan && cmake .. -G Ninja -DBUILD_TESTING=ON -DASAN=ON -DCMAKE_BUILD_TYPE=Debug)
|
||||
cmake --build build-asan
|
||||
./build-asan/uv_run_tests_a
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -37,11 +37,6 @@ vgcore.*
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
||||
# Generated by gyp for android
|
||||
*.target.mk
|
||||
/android-toolchain
|
||||
|
||||
/out/
|
||||
/build/
|
||||
|
||||
/test/.libs/
|
||||
@ -72,6 +67,7 @@ ipch
|
||||
|
||||
# Clion / IntelliJ project files
|
||||
/.idea/
|
||||
cmake-build-debug/
|
||||
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
||||
|
14
.mailmap
14
.mailmap
@ -1,7 +1,9 @@
|
||||
A. Hauptmann <andreashauptmann@t-online.de>
|
||||
AJ Heller <aj@drfloob.com> <hork@google.com>
|
||||
Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
|
||||
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
|
||||
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
|
||||
Andy Fiddaman <andy@omniosce.org> <omnios@citrus-it.co.uk>
|
||||
Bert Belder <bertbelder@gmail.com> <i@bertbelder.com>
|
||||
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
|
||||
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
|
||||
@ -10,6 +12,9 @@ Brian White <mscdex@mscdex.net>
|
||||
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
|
||||
Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr>
|
||||
Christoph Iserlohn <christoph.iserlohn@innoq.com>
|
||||
Darshan Sen <raisinten@gmail.com>
|
||||
Darshan Sen <raisinten@gmail.com> <darshan.sen@postman.com>
|
||||
David Carlier <devnexen@gmail.com>
|
||||
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
|
||||
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
|
||||
Frank Denis <github@pureftpd.org>
|
||||
@ -17,6 +22,8 @@ Imran Iqbal <imrani@ca.ibm.com> <imran@imraniqbal.org>
|
||||
Isaac Z. Schlueter <i@izs.me>
|
||||
Jason Williams <necmon@yahoo.com>
|
||||
Jesse Gorzinski <jgorzinski@gmail.com>
|
||||
Jesse Gorzinski <jgorzinski@gmail.com> <jgorzins@us.ibm.com>
|
||||
Juan José Arboleda <soyjuanarbol@gmail.com>
|
||||
Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
|
||||
@ -26,10 +33,12 @@ Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
|
||||
Michael <michael_dawson@ca.ibm.com>
|
||||
Michael Neumann <mneumann@think.localnet> <mneumann@ntecs.de>
|
||||
Michael Penick <michael.penick@datastax.com> <mpenick@users.noreply.github.com>
|
||||
Nicholas Vavilov <vvnicholas@gmail.com>
|
||||
Nick Logan <ugexe@cpan.org> <nlogan@gmail.com>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
|
||||
Richard Lau <rlau@redhat.com> <riclau@uk.ibm.com>
|
||||
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
|
||||
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
|
||||
Ryan Emery <seebees@gmail.com>
|
||||
@ -40,11 +49,16 @@ Santiago Gimeno <santiago.gimeno@quantion.es> <santiago.gimeno@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com> <s@saghul.net>
|
||||
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
|
||||
Shuowang (Wayne) Zhang <shuowang.zhang@ibm.com>
|
||||
TK-one <tk5641@naver.com>
|
||||
Timothy J. Fontaine <tjfontaine@gmail.com>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Yazhong Liu <yorkiefixer@gmail.com>
|
||||
Yuki Okumura <mjt@cltn.org>
|
||||
cjihrig <cjihrig@gmail.com>
|
||||
gengjiawen <technicalcute@gmail.com>
|
||||
jBarz <jBarz@users.noreply.github.com> <jbarboza@ca.ibm.com>
|
||||
jBarz <jBarz@users.noreply.github.com> <jbarz@users.noreply.github.com>
|
||||
ptlomholt <pt@lomholt.com>
|
||||
tjarlama <59913901+tjarlama@users.noreply.github.com> <tjarlama@gmail.com>
|
||||
zlargon <zlargon1988@gmail.com>
|
||||
|
11
.readthedocs.yaml
Normal file
11
.readthedocs.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
version: 2
|
||||
|
||||
sphinx:
|
||||
builder: html
|
||||
configuration: null
|
||||
fail_on_warning: false
|
||||
|
||||
python:
|
||||
version: 3.8
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
96
AUTHORS
96
AUTHORS
@ -114,7 +114,6 @@ Dylan Cali <calid1984@gmail.com>
|
||||
Austin Foxley <austinf@cetoncorp.com>
|
||||
Benjamin Saunders <ben.e.saunders@gmail.com>
|
||||
Geoffry Song <goffrie@gmail.com>
|
||||
Rasmus Christian Pedersen <ruysch@outlook.com>
|
||||
William Light <wrl@illest.net>
|
||||
Oleg Efimov <o.efimov@corp.badoo.com>
|
||||
Lars Gierth <larsg@systemli.org>
|
||||
@ -123,7 +122,6 @@ Justin Venus <justin.venus@gmail.com>
|
||||
Kristian Evensen <kristian.evensen@gmail.com>
|
||||
Linus Mårtensson <linus.martensson@sonymobile.com>
|
||||
Navaneeth Kedaram Nambiathan <navaneethkn@gmail.com>
|
||||
Yorkie <yorkiefixer@gmail.com>
|
||||
StarWing <weasley.wx@gmail.com>
|
||||
thierry-FreeBSD <thierry@FreeBSD.org>
|
||||
Isaiah Norton <isaiah.norton@gmail.com>
|
||||
@ -212,7 +210,7 @@ guworks <ground.up.works@gmail.com>
|
||||
RossBencina <rossb@audiomulch.com>
|
||||
Roger A. Light <roger@atchoo.org>
|
||||
chenttuuvv <chenttuuvv@yahoo.com>
|
||||
Richard Lau <riclau@uk.ibm.com>
|
||||
Richard Lau <rlau@redhat.com>
|
||||
ronkorving <rkorving@wizcorp.jp>
|
||||
Corbin Simpson <MostAwesomeDude@gmail.com>
|
||||
Zachary Hamm <zsh@imipolexg.org>
|
||||
@ -418,3 +416,95 @@ Dominique Dumont <dod@debian.org>
|
||||
Manuel BACHMANN <tarnyko@tarnyko.net>
|
||||
Marek Vavrusa <marek@vavrusa.com>
|
||||
TK-one <tk5641@naver.com>
|
||||
Irek Fakhrutdinov <ifakhrutdinov@rocketsoftware.com>
|
||||
Lin Zhang <linroid@gmail.com>
|
||||
毛毛 <srayuws@users.noreply.github.com>
|
||||
Sk Sajidul Kadir <sheikh.sajid522@gmail.com>
|
||||
twosee <twose@qq.com>
|
||||
Rikard Falkeborn <rikard.falkeborn@gmail.com>
|
||||
Yash Ladha <yashladhapankajladha123@gmail.com>
|
||||
James Ross <git@james-ross.co.uk>
|
||||
Colin Finck <colin@reactos.org>
|
||||
Shohei YOSHIDA <syohex@gmail.com>
|
||||
Philip Chimento <philip.chimento@gmail.com>
|
||||
Michal Artazov <michal@artazov.cz>
|
||||
Jeroen Roovers <jer@gentoo.org>
|
||||
MasterDuke17 <MasterDuke17@users.noreply.github.com>
|
||||
Alexander Tokmakov <avtokmakov@yandex-team.ru>
|
||||
Arenoros <arenoros@gmail.com>
|
||||
lander0s <dh.landeros08@gmail.com>
|
||||
Turbinya <wownucleos@gmail.com>
|
||||
OleksandrKvl <oleksandrdvl@gmail.com>
|
||||
Carter Li <carter.li@eoitek.com>
|
||||
Juan Sebastian velez Posada <jvelezpo@users.noreply.github.com>
|
||||
escherstair <ernestviga@gmail.com>
|
||||
Evan Lucas <evanlucas@me.com>
|
||||
tjarlama <59913901+tjarlama@users.noreply.github.com>
|
||||
司徒玟琅 <sanjusss@qq.com>
|
||||
YuMeiJie <yumeijie@huawei.com>
|
||||
Aleksej Lebedev <root@zta.lk>
|
||||
Nikolay Mitev <github@hmel.org>
|
||||
Ulrik Strid <ulrik.strid@outlook.com>
|
||||
Elad Lahav <elahav@qnx.com>
|
||||
Elad Nachmias <eladn@pazam.net>
|
||||
Darshan Sen <raisinten@gmail.com>
|
||||
Simon Kadisch <simon.kadisch@k13-engineering.at>
|
||||
Momtchil Momtchev <momtchil@momtchev.com>
|
||||
Ethel Weston <66453757+ethelweston@users.noreply.github.com>
|
||||
Drew DeVault <sir@cmpwn.com>
|
||||
Mark Klein <klein@cscs.ch>
|
||||
schamberg97 <50446906+schamberg97@users.noreply.github.com>
|
||||
Bob Weinand <bobwei9@hotmail.com>
|
||||
Issam E. Maghni <issam.e.maghni@mailbox.org>
|
||||
Juan Pablo Canepa <jpcanepa@gmail.com>
|
||||
Shuowang (Wayne) Zhang <shuowang.zhang@ibm.com>
|
||||
Ondřej Surý <ondrej@sury.org>
|
||||
Juan José Arboleda <soyjuanarbol@gmail.com>
|
||||
Zhao Zhili <zhilizhao@tencent.com>
|
||||
Brandon Cheng <brandon.cheng@protonmail.com>
|
||||
Matvii Hodovaniuk <matvii@hodovani.uk>
|
||||
Hayden <me@diatr.us>
|
||||
yiyuaner <yguoaz@gmail.com>
|
||||
bbara <bbara93@gmail.com>
|
||||
SeverinLeonhardt <Severin.Leonhardt@teamviewer.com>
|
||||
Andy Fiddaman <andy@omniosce.org>
|
||||
Romain Roffé <rofferom@gmail.com>
|
||||
Eagle Liang <eagleliang@gmail.com>
|
||||
Ricky Zhou <ives199511@gmail.com>
|
||||
Simon Kissane <skissane@gmail.com>
|
||||
James M Snell <jasnell@gmail.com>
|
||||
Ali Mohammad Pur <Ali.mpfard@gmail.com>
|
||||
Erkhes N <71805796+rexes-ND@users.noreply.github.com>
|
||||
Joshua M. Clulow <josh@sysmgr.org>
|
||||
Guilherme Íscaro <cabelitostos@gmail.com>
|
||||
Martin Storsjö <martin@martin.st>
|
||||
Claes Nästén <pekdon@gmail.com>
|
||||
Mohamed Edrah <43171151+MSE99@users.noreply.github.com>
|
||||
Supragya Raj <supragyaraj@gmail.com>
|
||||
Ikko Ashimine <eltociear@gmail.com>
|
||||
Sylvain Corlay <sylvain.corlay@gmail.com>
|
||||
earnal <etienne.arnal@gmail.com>
|
||||
YAKSH BARIYA <yakshbari4@gmail.com>
|
||||
Ofek Lev <ofekmeister@gmail.com>
|
||||
~locpyl-tidnyd <81016946+locpyl-tidnyd@users.noreply.github.com>
|
||||
Evan Miller <emmiller@gmail.com>
|
||||
Petr Menšík <pemensik@redhat.com>
|
||||
Nicolas Noble <nicolasnoble@users.noreply.github.com>
|
||||
AJ Heller <aj@drfloob.com>
|
||||
Stacey Marshall <stacey.marshall@gmail.com>
|
||||
Jesper Storm Bache <jsbache@users.noreply.github.com>
|
||||
Campbell He <duskmoon314@users.noreply.github.com>
|
||||
Andrey Hohutkin <andrey.hohutkin@gmail.com>
|
||||
deal <halx99@live.com>
|
||||
David Machaj <46852402+dmachaj@users.noreply.github.com>
|
||||
Jessica Clarke <jrtc27@jrtc27.com>
|
||||
Jeremy Rose <nornagon@nornagon.net>
|
||||
woclass <git@wo-class.cn>
|
||||
Luca Adrian L <info@lucalindhorst.de>
|
||||
WenTao Ou <owt5008137@live.com>
|
||||
jonilaitinen <joni.laitinen@iki.fi>
|
||||
UMU <UMU618@users.noreply.github.com>
|
||||
Paul Evans <leonerd@leonerd.org.uk>
|
||||
wyckster <wyckster@hotmail.com>
|
||||
Vittore F. Scolari <vittore.scolari@gmail.com>
|
||||
roflcopter4 <15476346+roflcopter4@users.noreply.github.com>
|
||||
|
5
BUILD.gn
5
BUILD.gn
@ -92,6 +92,7 @@ if (defined(ohos_lite)) {
|
||||
"src/unix/async.c",
|
||||
"src/unix/core.c",
|
||||
"src/unix/dl.c",
|
||||
"src/unix/epoll.c",
|
||||
"src/unix/fs.c",
|
||||
"src/unix/getaddrinfo.c",
|
||||
"src/unix/getnameinfo.c",
|
||||
@ -143,6 +144,7 @@ if (defined(ohos_lite)) {
|
||||
]
|
||||
if (!is_mingw && !is_win) {
|
||||
nonwin_srcs = [
|
||||
"src/unix/epoll.c",
|
||||
"src/unix/async.c",
|
||||
"src/unix/core.c",
|
||||
"src/unix/dl.c",
|
||||
@ -242,7 +244,9 @@ if (defined(ohos_lite)) {
|
||||
"src/unix/darwin-proctitle.c",
|
||||
"src/unix/darwin.c",
|
||||
"src/unix/fsevents.c",
|
||||
"src/unix/os390-proctitle.c",
|
||||
]
|
||||
sources -= [ "src/unix/epoll.c" ]
|
||||
} else if (is_mingw || is_win) {
|
||||
sources += [
|
||||
"src/win/async.c",
|
||||
@ -345,7 +349,6 @@ ohos_ndk_headers("libuv_uv_header") {
|
||||
dest_dir = "$ndk_headers_out_dir/uv"
|
||||
sources = [
|
||||
"include/uv/aix.h",
|
||||
"include/uv/android-ifaddrs.h",
|
||||
"include/uv/bsd.h",
|
||||
"include/uv/darwin.h",
|
||||
"include/uv/errno.h",
|
||||
|
334
CMakeLists.txt
334
CMakeLists.txt
@ -1,4 +1,3 @@
|
||||
# TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390".
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
project(libuv LANGUAGES C)
|
||||
|
||||
@ -25,6 +24,33 @@ cmake_dependent_option(LIBUV_BUILD_BENCH
|
||||
"Build the benchmarks when building unit tests and we are the root project" ON
|
||||
"LIBUV_BUILD_TESTS" OFF)
|
||||
|
||||
# Qemu Build
|
||||
option(QEMU "build for qemu" OFF)
|
||||
if(QEMU)
|
||||
add_definitions(-D__QEMU__=1)
|
||||
endif()
|
||||
|
||||
option(ASAN "Enable AddressSanitizer (ASan)" OFF)
|
||||
option(TSAN "Enable ThreadSanitizer (TSan)" OFF)
|
||||
|
||||
if((ASAN OR TSAN) AND NOT (CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang"))
|
||||
message(SEND_ERROR "Sanitizer support requires clang or gcc. Try again with -DCMAKE_C_COMPILER.")
|
||||
endif()
|
||||
|
||||
if(ASAN)
|
||||
add_definitions(-D__ASAN__=1)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
|
||||
endif()
|
||||
|
||||
if(TSAN)
|
||||
add_definitions(-D__TSAN__=1)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
endif()
|
||||
|
||||
# Compiler check
|
||||
string(CONCAT is-msvc $<OR:
|
||||
$<C_COMPILER_ID:MSVC>,
|
||||
@ -32,6 +58,18 @@ string(CONCAT is-msvc $<OR:
|
||||
>)
|
||||
|
||||
check_c_compiler_flag(/W4 UV_LINT_W4)
|
||||
check_c_compiler_flag(/wd4100 UV_LINT_NO_UNUSED_PARAMETER_MSVC)
|
||||
check_c_compiler_flag(/wd4127 UV_LINT_NO_CONDITIONAL_CONSTANT_MSVC)
|
||||
check_c_compiler_flag(/wd4201 UV_LINT_NO_NONSTANDARD_MSVC)
|
||||
check_c_compiler_flag(/wd4206 UV_LINT_NO_NONSTANDARD_EMPTY_TU_MSVC)
|
||||
check_c_compiler_flag(/wd4210 UV_LINT_NO_NONSTANDARD_FILE_SCOPE_MSVC)
|
||||
check_c_compiler_flag(/wd4232 UV_LINT_NO_NONSTANDARD_NONSTATIC_DLIMPORT_MSVC)
|
||||
check_c_compiler_flag(/wd4456 UV_LINT_NO_HIDES_LOCAL)
|
||||
check_c_compiler_flag(/wd4457 UV_LINT_NO_HIDES_PARAM)
|
||||
check_c_compiler_flag(/wd4459 UV_LINT_NO_HIDES_GLOBAL)
|
||||
check_c_compiler_flag(/wd4706 UV_LINT_NO_CONDITIONAL_ASSIGNMENT_MSVC)
|
||||
check_c_compiler_flag(/wd4996 UV_LINT_NO_UNSAFE_MSVC)
|
||||
|
||||
check_c_compiler_flag(-Wall UV_LINT_WALL) # DO NOT use this under MSVC
|
||||
|
||||
# TODO: Place these into its own function
|
||||
@ -39,18 +77,47 @@ check_c_compiler_flag(-Wno-unused-parameter UV_LINT_NO_UNUSED_PARAMETER)
|
||||
check_c_compiler_flag(-Wstrict-prototypes UV_LINT_STRICT_PROTOTYPES)
|
||||
check_c_compiler_flag(-Wextra UV_LINT_EXTRA)
|
||||
|
||||
set(lint-no-unused-parameter $<$<BOOL:${UV_LINT_NO_UNUSED_PARAMETER}>:-Wno-unused-parameter>)
|
||||
check_c_compiler_flag(/utf-8 UV_LINT_UTF8_MSVC)
|
||||
|
||||
set(lint-no-unused-parameter $<$<BOOL:${UV_LINT_NO_UNUSED_PARAMETER}>:-Wno-unused-parameter>)
|
||||
set(lint-strict-prototypes $<$<BOOL:${UV_LINT_STRICT_PROTOTYPES}>:-Wstrict-prototypes>)
|
||||
set(lint-extra $<$<BOOL:${UV_LINT_EXTRA}>:-Wextra>)
|
||||
set(lint-w4 $<$<BOOL:${UV_LINT_W4}>:/W4>)
|
||||
set(lint-no-unused-parameter-msvc $<$<BOOL:${UV_LINT_NO_UNUSED_PARAMETER_MSVC}>:/wd4100>)
|
||||
set(lint-no-conditional-constant-msvc $<$<BOOL:${UV_LINT_NO_CONDITIONAL_CONSTANT_MSVC}>:/wd4127>)
|
||||
set(lint-no-nonstandard-msvc $<$<BOOL:${UV_LINT_NO_NONSTANDARD_MSVC}>:/wd4201>)
|
||||
set(lint-no-nonstandard-empty-tu-msvc $<$<BOOL:${UV_LINT_NO_NONSTANDARD_EMPTY_TU_MSVC}>:/wd4206>)
|
||||
set(lint-no-nonstandard-file-scope-msvc $<$<BOOL:${UV_LINT_NO_NONSTANDARD_FILE_SCOPE_MSVC}>:/wd4210>)
|
||||
set(lint-no-nonstandard-nonstatic-dlimport-msvc $<$<BOOL:${UV_LINT_NO_NONSTANDARD_NONSTATIC_DLIMPORT_MSVC}>:/wd4232>)
|
||||
set(lint-no-hides-local-msvc $<$<BOOL:${UV_LINT_NO_HIDES_LOCAL}>:/wd4456>)
|
||||
set(lint-no-hides-param-msvc $<$<BOOL:${UV_LINT_NO_HIDES_PARAM}>:/wd4457>)
|
||||
set(lint-no-hides-global-msvc $<$<BOOL:${UV_LINT_NO_HIDES_GLOBAL}>:/wd4459>)
|
||||
set(lint-no-conditional-assignment-msvc $<$<BOOL:${UV_LINT_NO_CONDITIONAL_ASSIGNMENT_MSVC}>:/wd4706>)
|
||||
set(lint-no-unsafe-msvc $<$<BOOL:${UV_LINT_NO_UNSAFE_MSVC}>:/wd4996>)
|
||||
# Unfortunately, this one is complicated because MSVC and clang-cl support -Wall
|
||||
# but using it is like calling -Weverything
|
||||
string(CONCAT lint-default $<
|
||||
$<AND:$<BOOL:${UV_LINT_WALL}>,$<NOT:${is-msvc}>>:-Wall
|
||||
>)
|
||||
set(lint-utf8-msvc $<$<BOOL:${UV_LINT_UTF8_MSVC}>:/utf-8>)
|
||||
|
||||
list(APPEND uv_cflags ${lint-strict-prototypes} ${lint-extra} ${lint-default} ${lint-w4})
|
||||
list(APPEND uv_cflags ${lint-no-unused-parameter})
|
||||
list(APPEND uv_cflags ${lint-no-unused-parameter-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-conditional-constant-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-nonstandard-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-nonstandard-empty-tu-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-nonstandard-file-scope-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-nonstandard-nonstatic-dlimport-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-hides-local-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-hides-param-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-hides-global-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-conditional-assignment-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-unsafe-msvc})
|
||||
list(APPEND uv_cflags ${lint-utf8-msvc} )
|
||||
|
||||
check_c_compiler_flag(-fno-strict-aliasing UV_F_STRICT_ALIASING)
|
||||
list(APPEND uv_cflags $<$<BOOL:${UV_F_STRICT_ALIASING}>:-fno-strict-aliasing>)
|
||||
|
||||
set(uv_sources
|
||||
src/fs-poll.c
|
||||
@ -65,22 +132,11 @@ set(uv_sources
|
||||
src/version.c)
|
||||
|
||||
if(WIN32)
|
||||
if (CMAKE_SYSTEM_VERSION VERSION_GREATER 10) # Windows 10
|
||||
set(windows-version 0x0A00)
|
||||
elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.3) # Windows 8.1
|
||||
set(windows-version 0x0603)
|
||||
elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.2) # Windows 8
|
||||
set(windows-version 0x0602)
|
||||
elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.1) # Windows 7
|
||||
set(windows-version 0x0601)
|
||||
elseif (CMAKE_SYSTEM_VERSION VERSION_GREATER 6.0) # Windows Vista
|
||||
set(windows-version 0x0600)
|
||||
else()
|
||||
message(FATAL_ERROR "Windows Vista is the minimum version supported")
|
||||
endif()
|
||||
list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=${windows-version})
|
||||
list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602)
|
||||
list(APPEND uv_libraries
|
||||
$<$<STREQUAL:${windows-version},0x0600>:psapi>
|
||||
psapi
|
||||
user32
|
||||
advapi32
|
||||
iphlpapi
|
||||
userenv
|
||||
ws2_32)
|
||||
@ -114,7 +170,7 @@ if(WIN32)
|
||||
list(APPEND uv_test_sources src/win/snprintf.c test/runner-win.c)
|
||||
else()
|
||||
list(APPEND uv_defines _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE)
|
||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
if(NOT CMAKE_SYSTEM_NAME MATCHES "Android|OS390|QNX")
|
||||
# TODO: This should be replaced with find_package(Threads) if possible
|
||||
# Android has pthread as part of its c library, not as a separate
|
||||
# libpthread.so.
|
||||
@ -147,15 +203,18 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
|
||||
_ALL_SOURCE
|
||||
_LINUX_SOURCE_COMPAT
|
||||
_THREAD_SAFE
|
||||
_XOPEN_SOURCE=500)
|
||||
_XOPEN_SOURCE=500
|
||||
HAVE_SYS_AHAFS_EVPRODS_H)
|
||||
list(APPEND uv_libraries perfstat)
|
||||
list(APPEND uv_sources src/unix/aix.c)
|
||||
list(APPEND uv_sources
|
||||
src/unix/aix.c
|
||||
src/unix/aix-common.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
list(APPEND uv_libs dl)
|
||||
list(APPEND uv_defines _GNU_SOURCE)
|
||||
list(APPEND uv_libraries dl)
|
||||
list(APPEND uv_sources
|
||||
src/unix/android-ifaddrs.c
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
@ -164,10 +223,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
src/unix/random-getentropy.c
|
||||
src/unix/random-getrandom.c
|
||||
src/unix/random-sysctl-linux.c
|
||||
src/unix/sysinfo-loadavg.c)
|
||||
src/unix/epoll.c)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS/390")
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux")
|
||||
list(APPEND uv_sources src/unix/proctitle.c)
|
||||
endif()
|
||||
|
||||
@ -177,7 +236,6 @@ endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
|
||||
list(APPEND uv_sources src/unix/posix-hrtime.c src/unix/bsd-proctitle.c)
|
||||
list(APPEND uv_libraries kvm)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
|
||||
@ -200,6 +258,17 @@ if(APPLE)
|
||||
src/unix/fsevents.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "GNU")
|
||||
list(APPEND uv_libraries dl)
|
||||
list(APPEND uv_sources
|
||||
src/unix/bsd-ifaddrs.c
|
||||
src/unix/no-fsevents.c
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/posix-hrtime.c
|
||||
src/unix/posix-poll.c
|
||||
src/unix/hurd.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112)
|
||||
list(APPEND uv_libraries dl rt)
|
||||
@ -210,21 +279,25 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/random-getrandom.c
|
||||
src/unix/random-sysctl-linux.c
|
||||
src/unix/sysinfo-loadavg.c)
|
||||
src/unix/epoll.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
|
||||
list(APPEND uv_sources src/unix/netbsd.c)
|
||||
list(APPEND uv_libraries kvm)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
|
||||
list(APPEND uv_sources src/unix/openbsd.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS/390")
|
||||
list(APPEND uv_defines PATH_MAX=255)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
enable_language(CXX)
|
||||
list(APPEND uv_defines PATH_MAX=1024)
|
||||
list(APPEND uv_defines _AE_BIMODAL)
|
||||
list(APPEND uv_defines _ALL_SOURCE)
|
||||
list(APPEND uv_defines _ENHANCED_ASCII_EXT=0xFFFFFFFF)
|
||||
list(APPEND uv_defines _ISOC99_SOURCE)
|
||||
list(APPEND uv_defines _LARGE_TIME_API)
|
||||
list(APPEND uv_defines _OPEN_MSGQ_EXT)
|
||||
list(APPEND uv_defines _OPEN_SYS_FILE_EXT)
|
||||
@ -234,18 +307,75 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS/390")
|
||||
list(APPEND uv_defines _UNIX03_SOURCE)
|
||||
list(APPEND uv_defines _UNIX03_THREADS)
|
||||
list(APPEND uv_defines _UNIX03_WITHDRAWN)
|
||||
list(APPEND uv_defines _XOPEN_SOURCE=600)
|
||||
list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED)
|
||||
list(APPEND uv_sources
|
||||
src/unix/pthread-fixes.c
|
||||
src/unix/pthread-barrier.c
|
||||
src/unix/os390.c
|
||||
src/unix/os390-syscalls.c)
|
||||
src/unix/os390-syscalls.c
|
||||
src/unix/os390-proctitle.c)
|
||||
list(APPEND uv_cflags
|
||||
-q64
|
||||
-qascii
|
||||
-qexportall
|
||||
-qgonumber
|
||||
-qlongname
|
||||
-qlibansi
|
||||
-qfloat=IEEE
|
||||
-qtune=10
|
||||
-qarch=10
|
||||
-qasm
|
||||
-qasmlib=sys1.maclib:sys1.modgen)
|
||||
find_library(ZOSLIB
|
||||
NAMES zoslib
|
||||
PATHS ${ZOSLIB_DIR}
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
list(APPEND uv_libraries ${ZOSLIB})
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS400")
|
||||
list(APPEND uv_defines
|
||||
_ALL_SOURCE
|
||||
_LINUX_SOURCE_COMPAT
|
||||
_THREAD_SAFE
|
||||
_XOPEN_SOURCE=500)
|
||||
list(APPEND uv_sources
|
||||
src/unix/aix-common.c
|
||||
src/unix/ibmi.c
|
||||
src/unix/no-fsevents.c
|
||||
src/unix/posix-poll.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500)
|
||||
list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500 _REENTRANT)
|
||||
list(APPEND uv_libraries kstat nsl sendfile socket)
|
||||
list(APPEND uv_sources src/unix/no-proctitle.c src/unix/sunos.c)
|
||||
list(APPEND uv_sources
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/sunos.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
|
||||
list(APPEND uv_defines _BSD_SOURCE)
|
||||
list(APPEND uv_libraries bsd network)
|
||||
list(APPEND uv_sources
|
||||
src/unix/haiku.c
|
||||
src/unix/bsd-ifaddrs.c
|
||||
src/unix/no-fsevents.c
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/posix-hrtime.c
|
||||
src/unix/posix-poll.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
||||
list(APPEND uv_sources
|
||||
src/unix/posix-hrtime.c
|
||||
src/unix/posix-poll.c
|
||||
src/unix/qnx.c
|
||||
src/unix/bsd-ifaddrs.c
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/no-fsevents.c)
|
||||
list(APPEND uv_libraries socket)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD")
|
||||
@ -266,6 +396,10 @@ target_include_directories(uv
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
target_include_directories(uv PUBLIC $<BUILD_INTERFACE:${ZOSLIB_DIR}/include>)
|
||||
set_target_properties(uv PROPERTIES LINKER_LANGUAGE CXX)
|
||||
endif()
|
||||
target_link_libraries(uv ${uv_libraries})
|
||||
|
||||
add_library(uv_a STATIC ${uv_sources})
|
||||
@ -277,9 +411,44 @@ target_include_directories(uv_a
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
target_include_directories(uv_a PUBLIC $<BUILD_INTERFACE:${ZOSLIB_DIR}/include>)
|
||||
set_target_properties(uv_a PROPERTIES LINKER_LANGUAGE CXX)
|
||||
endif()
|
||||
target_link_libraries(uv_a ${uv_libraries})
|
||||
|
||||
if(LIBUV_BUILD_TESTS)
|
||||
# Small hack: use ${uv_test_sources} now to get the runner skeleton,
|
||||
# before the actual tests are added.
|
||||
add_executable(
|
||||
uv_run_benchmarks_a
|
||||
${uv_test_sources}
|
||||
test/benchmark-async-pummel.c
|
||||
test/benchmark-async.c
|
||||
test/benchmark-fs-stat.c
|
||||
test/benchmark-getaddrinfo.c
|
||||
test/benchmark-loop-count.c
|
||||
test/benchmark-queue-work.c
|
||||
test/benchmark-million-async.c
|
||||
test/benchmark-million-timers.c
|
||||
test/benchmark-multi-accept.c
|
||||
test/benchmark-ping-pongs.c
|
||||
test/benchmark-ping-udp.c
|
||||
test/benchmark-pound.c
|
||||
test/benchmark-pump.c
|
||||
test/benchmark-sizes.c
|
||||
test/benchmark-spawn.c
|
||||
test/benchmark-tcp-write-batch.c
|
||||
test/benchmark-thread.c
|
||||
test/benchmark-udp-pummel.c
|
||||
test/blackhole-server.c
|
||||
test/echo-server.c
|
||||
test/run-benchmarks.c
|
||||
test/runner.c)
|
||||
target_compile_definitions(uv_run_benchmarks_a PRIVATE ${uv_defines})
|
||||
target_compile_options(uv_run_benchmarks_a PRIVATE ${uv_cflags})
|
||||
target_link_libraries(uv_run_benchmarks_a uv_a ${uv_test_libraries})
|
||||
|
||||
list(APPEND uv_test_sources
|
||||
test/blackhole-server.c
|
||||
test/echo-server.c
|
||||
@ -331,6 +500,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-idna.c
|
||||
test/test-ip4-addr.c
|
||||
test/test-ip6-addr.c
|
||||
test/test-ip-name.c
|
||||
test/test-ipc-heavy-traffic-deadlock-bug.c
|
||||
test/test-ipc-send-recv.c
|
||||
test/test-ipc.c
|
||||
@ -340,8 +510,11 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-loop-handles.c
|
||||
test/test-loop-stop.c
|
||||
test/test-loop-time.c
|
||||
test/test-metrics.c
|
||||
test/test-multiple-listen.c
|
||||
test/test-mutexes.c
|
||||
test/test-not-readable-nor-writable-on-read-error.c
|
||||
test/test-not-writable-after-shutdown.c
|
||||
test/test-osx-select.c
|
||||
test/test-pass-always.c
|
||||
test/test-ping-pong.c
|
||||
@ -360,6 +533,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-poll-close-doesnt-corrupt-stack.c
|
||||
test/test-poll-close.c
|
||||
test/test-poll-closesocket.c
|
||||
test/test-poll-multiple-handles.c
|
||||
test/test-poll-oob.c
|
||||
test/test-poll.c
|
||||
test/test-process-priority.c
|
||||
@ -367,12 +541,14 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-process-title.c
|
||||
test/test-queue-foreach-delete.c
|
||||
test/test-random.c
|
||||
test/test-readable-on-eof.c
|
||||
test/test-ref.c
|
||||
test/test-run-nowait.c
|
||||
test/test-run-once.c
|
||||
test/test-semaphore.c
|
||||
test/test-shutdown-close.c
|
||||
test/test-shutdown-eof.c
|
||||
test/test-shutdown-simultaneous.c
|
||||
test/test-shutdown-twice.c
|
||||
test/test-signal-multiple-loops.c
|
||||
test/test-signal-pending-on-close.c
|
||||
@ -397,6 +573,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-tcp-oob.c
|
||||
test/test-tcp-open.c
|
||||
test/test-tcp-read-stop.c
|
||||
test/test-tcp-read-stop-start.c
|
||||
test/test-tcp-shutdown-after-write.c
|
||||
test/test-tcp-try-write.c
|
||||
test/test-tcp-try-write-error.c
|
||||
@ -406,6 +583,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-tcp-write-queue-order.c
|
||||
test/test-tcp-write-to-half-open-connection.c
|
||||
test/test-tcp-writealot.c
|
||||
test/test-test-macros.c
|
||||
test/test-thread-equal.c
|
||||
test/test-thread.c
|
||||
test/test-threadpool-cancel.c
|
||||
@ -420,9 +598,11 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-udp-alloc-cb-fail.c
|
||||
test/test-udp-bind.c
|
||||
test/test-udp-connect.c
|
||||
test/test-udp-connect6.c
|
||||
test/test-udp-create-socket-early.c
|
||||
test/test-udp-dgram-too-big.c
|
||||
test/test-udp-ipv6.c
|
||||
test/test-udp-mmsg.c
|
||||
test/test-udp-multicast-interface.c
|
||||
test/test-udp-multicast-interface6.c
|
||||
test/test-udp-multicast-join.c
|
||||
@ -433,13 +613,14 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-udp-send-and-recv.c
|
||||
test/test-udp-send-hang-loop.c
|
||||
test/test-udp-send-immediate.c
|
||||
test/test-udp-sendmmsg-error.c
|
||||
test/test-udp-send-unreachable.c
|
||||
test/test-udp-try-send.c
|
||||
test/test-uname.c
|
||||
test/test-walk-handles.c
|
||||
test/test-watcher-cross-stop.c)
|
||||
|
||||
add_executable(uv_run_tests ${uv_test_sources})
|
||||
add_executable(uv_run_tests ${uv_test_sources} uv_win_longpath.manifest)
|
||||
target_compile_definitions(uv_run_tests
|
||||
PRIVATE ${uv_defines} USING_UV_SHARED=1)
|
||||
target_compile_options(uv_run_tests PRIVATE ${uv_cflags})
|
||||
@ -447,46 +628,67 @@ if(LIBUV_BUILD_TESTS)
|
||||
add_test(NAME uv_test
|
||||
COMMAND uv_run_tests
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_executable(uv_run_tests_a ${uv_test_sources})
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
set_tests_properties(uv_test PROPERTIES ENVIRONMENT
|
||||
"LIBPATH=${CMAKE_BINARY_DIR}:$ENV{LIBPATH}")
|
||||
endif()
|
||||
add_executable(uv_run_tests_a ${uv_test_sources} uv_win_longpath.manifest)
|
||||
target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines})
|
||||
target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags})
|
||||
target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries})
|
||||
if(QEMU)
|
||||
target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries} -static)
|
||||
else()
|
||||
target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries})
|
||||
endif()
|
||||
add_test(NAME uv_test_a
|
||||
COMMAND uv_run_tests_a
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
set_target_properties(uv_run_benchmarks_a PROPERTIES LINKER_LANGUAGE CXX)
|
||||
set_target_properties(uv_run_tests PROPERTIES LINKER_LANGUAGE CXX)
|
||||
set_target_properties(uv_run_tests_a PROPERTIES LINKER_LANGUAGE CXX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
# Now for some gibbering horrors from beyond the stars...
|
||||
foreach(lib IN LISTS uv_libraries)
|
||||
list(APPEND LIBS "-l${lib}")
|
||||
endforeach()
|
||||
string(REPLACE ";" " " LIBS "${LIBS}")
|
||||
# Consider setting project version via project() call?
|
||||
file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
|
||||
string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}")
|
||||
set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
# The version in the filename is mirroring the behaviour of autotools.
|
||||
set_target_properties(uv PROPERTIES
|
||||
VERSION ${UV_VERSION_MAJOR}.0.0
|
||||
SOVERSION ${UV_VERSION_MAJOR})
|
||||
set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
configure_file(libuv.pc.in libuv.pc @ONLY)
|
||||
# Now for some gibbering horrors from beyond the stars...
|
||||
foreach(lib IN LISTS uv_libraries)
|
||||
list(APPEND LIBS "-l${lib}")
|
||||
endforeach()
|
||||
string(REPLACE ";" " " LIBS "${LIBS}")
|
||||
# Consider setting project version via project() call?
|
||||
file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
|
||||
string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}")
|
||||
set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
# The version in the filename is mirroring the behaviour of autotools.
|
||||
set_target_properties(uv PROPERTIES
|
||||
VERSION ${UV_VERSION_MAJOR}.0.0
|
||||
SOVERSION ${UV_VERSION_MAJOR})
|
||||
set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
configure_file(libuv.pc.in libuv.pc @ONLY)
|
||||
configure_file(libuv-static.pc.in libuv-static.pc @ONLY)
|
||||
|
||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv.pc ${PROJECT_BINARY_DIR}/libuv-static.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(TARGETS uv EXPORT libuvConfig
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(TARGETS uv_a EXPORT libuvConfig
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(EXPORT libuvConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libuv)
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX d)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
install(DIRECTORY include/ DESTINATION include)
|
||||
install(FILES LICENSE DESTINATION .)
|
||||
install(TARGETS uv uv_a
|
||||
RUNTIME DESTINATION lib/$<CONFIG>
|
||||
ARCHIVE DESTINATION lib/$<CONFIG>)
|
||||
endif()
|
||||
message(STATUS "summary of build options:
|
||||
Install prefix: ${CMAKE_INSTALL_PREFIX}
|
||||
Target system: ${CMAKE_SYSTEM_NAME}
|
||||
Compiler:
|
||||
C compiler: ${CMAKE_C_COMPILER} (${CMAKE_C_COMPILER_ID})
|
||||
CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
|
||||
")
|
||||
|
@ -23,11 +23,11 @@ The stable branch is effectively frozen; patches that change the libuv
|
||||
API/ABI or affect the run-time behavior of applications get rejected.
|
||||
|
||||
In case of doubt, open an issue in the [issue tracker][], post your question
|
||||
to the [libuv mailing list], or contact one of [project maintainers][] on [IRC][].
|
||||
to the [libuv discussions forum], or message the [libuv mailing list].
|
||||
|
||||
Especially do so if you plan to work on something big. Nothing is more
|
||||
frustrating than seeing your hard work go to waste because your vision
|
||||
does not align with that of a project maintainers.
|
||||
Especially do so if you plan to work on something big. Nothing is more
|
||||
frustrating than seeing your hard work go to waste because your vision does not
|
||||
align with that of the [project maintainers].
|
||||
|
||||
|
||||
### BRANCH
|
||||
@ -142,7 +142,6 @@ Bug fixes and features should come with tests. Add your tests in the
|
||||
If you add a new test file, it needs to be registered in three places:
|
||||
- `CMakeLists.txt`: add the file's name to the `uv_test_sources` list.
|
||||
- `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list.
|
||||
- `uv.gyp`: add the file's name to the `sources` list in the `run-tests` target.
|
||||
|
||||
Look at other tests to see how they should be structured (license boilerplate,
|
||||
the way entry points are declared, etc.).
|
||||
@ -167,6 +166,6 @@ not send out notifications when you add commits.
|
||||
|
||||
[issue tracker]: https://github.com/libuv/libuv/issues
|
||||
[libuv mailing list]: http://groups.google.com/group/libuv
|
||||
[IRC]: http://webchat.freenode.net/?channels=libuv
|
||||
[libuv discussions forum]: https://github.com/libuv/libuv/discussions
|
||||
[Google C/C++ style guide]: https://google.github.io/styleguide/cppguide.html
|
||||
[project maintainers]: https://github.com/libuv/libuv/blob/master/MAINTAINERS.md
|
||||
|
750
ChangeLog
750
ChangeLog
@ -1,4 +1,752 @@
|
||||
2020.03.12, Version 1.35.0 (Stable)
|
||||
2022.03.09, Version 1.44.1 (Stable)
|
||||
|
||||
Changes since version 1.44.0:
|
||||
|
||||
* process: simplify uv__write_int calls (Jameson Nash)
|
||||
|
||||
* macos: don't use thread-unsafe strtok() (Ben Noordhuis)
|
||||
|
||||
* process: fix hang after NOTE_EXIT (Jameson Nash)
|
||||
|
||||
|
||||
2022.03.07, Version 1.44.0 (Stable), d2bff508457336d808ba7148b33088f6acbfe0a6
|
||||
|
||||
Changes since version 1.43.0:
|
||||
|
||||
* darwin: remove EPROTOTYPE error workaround (Ben Noordhuis)
|
||||
|
||||
* doc: fix v1.43.0 changelog entries (cjihrig)
|
||||
|
||||
* win: replace CRITICAL_SECTION+Semaphore with SRWLock (David Machaj)
|
||||
|
||||
* darwin: translate EPROTOTYPE to ECONNRESET (Ben Noordhuis)
|
||||
|
||||
* android: use libc getifaddrs() (Ben Noordhuis)
|
||||
|
||||
* unix: fix STATIC_ASSERT to check what it means to check (Jessica Clarke)
|
||||
|
||||
* unix: ensure struct msghdr is zeroed in recvmmsg (Ondřej Surý)
|
||||
|
||||
* test: test with maximum recvmmsg buffer (Ondřej Surý)
|
||||
|
||||
* unix: don't allow too small thread stack size (Ben Noordhuis)
|
||||
|
||||
* bsd: ensure mutex is initialized (Ben Noordhuis)
|
||||
|
||||
* doc: add gengjiawen as maintainer (gengjiawen)
|
||||
|
||||
* process: monitor for exit with kqueue on BSDs (Jeremy Rose)
|
||||
|
||||
* test: fix flaky uv_fs_lutime test (Momtchil Momtchev)
|
||||
|
||||
* build: fix cmake install locations (Jameson Nash)
|
||||
|
||||
* thread,win: fix C90 style nit (ssrlive)
|
||||
|
||||
* build: rename CFLAGS to AM_CFLAGS (Jameson Nash)
|
||||
|
||||
* doc/guide: update content and sample code (woclass)
|
||||
|
||||
* process,bsd: handle kevent NOTE_EXIT failure (Jameson Nash)
|
||||
|
||||
* test: remove flaky test ipc_closed_handle (Ben Noordhuis)
|
||||
|
||||
* darwin: bump minimum supported version to 10.15 (Ben Noordhuis)
|
||||
|
||||
* win: return fractional seconds in uv_uptime() (Luca Adrian L)
|
||||
|
||||
* build: export uv_a for cmake (WenTao Ou)
|
||||
|
||||
* loop: add pending work to loop-alive check (Jameson Nash)
|
||||
|
||||
* win: use GetTickCount64 for uptime again (Jameson Nash)
|
||||
|
||||
* win: restrict system DLL load paths (jonilaitinen)
|
||||
|
||||
* win,errors: remap ERROR_ACCESS_DENIED to UV_EACCES (Darshan Sen)
|
||||
|
||||
* bench: add `uv_queue_work` ping-pong measurement (Momtchil Momtchev)
|
||||
|
||||
* build: fix error C4146 on MSVC (UMU)
|
||||
|
||||
* test: fix benchmark-ping-udp (Ryan Liptak)
|
||||
|
||||
* win,fs: consider broken pipe error a normal EOF (Momtchil Momtchev)
|
||||
|
||||
* document the values of enum uv_stdio_flags (Paul Evans)
|
||||
|
||||
* win,loop: add missing uv_update_time (twosee)
|
||||
|
||||
* win,fs: avoid closing an invalid handle (Jameson Nash)
|
||||
|
||||
* fix oopsie from
|
||||
|
||||
* doc: clarify android api level (Ben Noordhuis)
|
||||
|
||||
* win: fix style nits [NFC] (Jameson Nash)
|
||||
|
||||
* test: fix flaky udp_mmsg test (Santiago Gimeno)
|
||||
|
||||
* test: fix ipc_send_recv_pipe flakiness (Ben Noordhuis)
|
||||
|
||||
* doc: checkout -> check out (wyckster)
|
||||
|
||||
* core: change uv_get_password uid/gid to unsigned (Jameson Nash)
|
||||
|
||||
* hurd: unbreak build on GNU/Hurd (Vittore F. Scolari)
|
||||
|
||||
* freebsd: use copy_file_range() in uv_fs_sendfile() (David Carlier)
|
||||
|
||||
* test: use closefd in runner-unix.c (Guilherme Íscaro)
|
||||
|
||||
* Reland "macos: use posix_spawn instead of fork" (Jameson Nash)
|
||||
|
||||
* android: fix build error when no ifaddrs.h (ssrlive)
|
||||
|
||||
* unix,win: add uv_available_parallelism() (Ben Noordhuis)
|
||||
|
||||
* process: remove OpenBSD from kevent list (Jameson Nash)
|
||||
|
||||
* zos: fix build breakage (Ben Noordhuis)
|
||||
|
||||
* process: only use F_DUPFD_CLOEXEC if it is defined (Jameson Nash)
|
||||
|
||||
* win,poll: add the MSAFD GUID for AF_UNIX (roflcopter4)
|
||||
|
||||
* unix: simplify uv__cloexec_fcntl() (Ben Noordhuis)
|
||||
|
||||
* doc: add secondary GPG ID for vtjnash (Jameson Nash)
|
||||
|
||||
* unix: remove uv__cloexec_ioctl() (Jameson Nash)
|
||||
|
||||
|
||||
2022.01.05, Version 1.43.0 (Stable), 988f2bfc4defb9a85a536a3e645834c161143ee0
|
||||
|
||||
Changes since version 1.42.0:
|
||||
|
||||
* run test named ip6_sin6_len (Jameson Nash)
|
||||
|
||||
* docs: fix wrong information about scheduling (Mohamed Edrah)
|
||||
|
||||
* unix: protect fork in uv_spawn from signals (Jameson Nash)
|
||||
|
||||
* drop only successfully sent packets post sendmmsg (Supragya Raj)
|
||||
|
||||
* test: fix typo in test-tty-escape-sequence-processing.c (Ikko Ashimine)
|
||||
|
||||
* cmake: use standard installation layout always (Sylvain Corlay)
|
||||
|
||||
* win,spawn: allow UNC path with forward slash (earnal)
|
||||
|
||||
* win,fsevent: fix uv_fs_event_stop() assert (Ben Noordhuis)
|
||||
|
||||
* unix: remove redundant include in unix.h (Juan José Arboleda)
|
||||
|
||||
* doc: mark SmartOS as Tier 3 support (Ben Noordhuis)
|
||||
|
||||
* doc: fix broken links for netbsd's sysctl manpage (YAKSH BARIYA)
|
||||
|
||||
* misc: adjust stalebot deadline (Ben Noordhuis)
|
||||
|
||||
* test: remove `dns-server.c` as it is not used anywhere (Darshan Sen)
|
||||
|
||||
* build: fix non-cmake android builds (YAKSH BARIYA)
|
||||
|
||||
* doc: replace pyuv with uvloop (Ofek Lev)
|
||||
|
||||
* asan: fix some tests (Jameson Nash)
|
||||
|
||||
* build: add experimental TSAN configuration (Jameson Nash)
|
||||
|
||||
* pipe: remove useless assertion (~locpyl-tidnyd)
|
||||
|
||||
* bsd: destroy mutex in uv__process_title_cleanup() (Darshan Sen)
|
||||
|
||||
* build: add windows build to CI (Darshan Sen)
|
||||
|
||||
* win,fs: fix error code in uv_fs_read() and uv_fs_write() (Darshan Sen)
|
||||
|
||||
* build: add macos-latest to ci matrix (Ben Noordhuis)
|
||||
|
||||
* udp: fix &/&& typo in macro condition (Evan Miller)
|
||||
|
||||
* build: install cmake package module (Petr Menšík)
|
||||
|
||||
* win: fix build for mingw32 (Nicolas Noble)
|
||||
|
||||
* build: fix build failures with MinGW new headers (erw7)
|
||||
|
||||
* build: fix win build with cmake versions before v3.14 (AJ Heller)
|
||||
|
||||
* unix: support aarch64 in uv_cpu_info() (Juan José Arboleda)
|
||||
|
||||
* linux: work around CIFS EPERM bug (Ben Noordhuis)
|
||||
|
||||
* sunos: Oracle Developer Studio support (Stacey Marshall)
|
||||
|
||||
* Revert "sunos: Oracle Developer Studio support (cjihrig)
|
||||
|
||||
* sunos: Oracle Developer Studio support (Stacey Marshall)
|
||||
|
||||
* stream: permit read after seeing EOF (Jameson Nash)
|
||||
|
||||
* thread: initialize uv_thread_self for all threads (Jameson Nash)
|
||||
|
||||
* kqueue: ignore write-end closed notifications (Jameson Nash)
|
||||
|
||||
* macos: fix the cfdata length in uv__get_cpu_speed (Jesper Storm Bache)
|
||||
|
||||
* unix,win: add uv_ip_name to get name from sockaddr (Campbell He)
|
||||
|
||||
* win,test: fix a few typos (AJ Heller)
|
||||
|
||||
* zos: use destructor for uv__threadpool_cleanup() (Wayne Zhang)
|
||||
|
||||
* linux: use MemAvailable instead of MemFree (Andrey Hohutkin)
|
||||
|
||||
* freebsd: call dlerror() only if necessary (Jameson Nash)
|
||||
|
||||
* bsd,windows,zos: fix udp disconnect EINVAL (deal)
|
||||
|
||||
|
||||
2021.07.21, Version 1.42.0 (Stable), 6ce14710da7079eb248868171f6343bc409ea3a4
|
||||
|
||||
Changes since version 1.41.0:
|
||||
|
||||
* doc: fix code highlighting (Darshan Sen)
|
||||
|
||||
* test: move to ASSERT_NULL and ASSERT_NOT_NULL test macros (tjarlama)
|
||||
|
||||
* zos: build in ascii code page (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: don't use nanosecond timestamp fields (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: introduce zoslib (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: use strnlen() from zoslib (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: use nanosleep() from zoslib (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: use __getargv() from zoslib to get exe path (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: treat __rfim_utok as binary (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: use execvpe() to set environ explictly (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: use custom proctitle implementation (Shuowang (Wayne) Zhang)
|
||||
|
||||
* doc: add instructions for building on z/OS (Shuowang (Wayne) Zhang)
|
||||
|
||||
* linux,udp: enable full ICMP error reporting (Ondřej Surý)
|
||||
|
||||
* test: fix test-udp-send-unreachable (Ondřej Surý)
|
||||
|
||||
* include: fix typo in documentation (Tobias Nießen)
|
||||
|
||||
* chore: use for(;;) instead of while (Yash Ladha)
|
||||
|
||||
* test: remove string + int warning on udp-pummel (Juan José Arboleda)
|
||||
|
||||
* cmake: fix linker flags (Zhao Zhili)
|
||||
|
||||
* test: fix stack-use-after-scope (Zhao Zhili)
|
||||
|
||||
* unix: expose thread_stack_size() internally (Brandon Cheng)
|
||||
|
||||
* darwin: use RLIMIT_STACK for fsevents pthread (Brandon Cheng)
|
||||
|
||||
* darwin: abort on pthread_attr_init fail (Brandon Cheng)
|
||||
|
||||
* benchmark: remove unreachable code (Matvii Hodovaniuk)
|
||||
|
||||
* macos: fix memleaks in uv__get_cpu_speed (George Zhao)
|
||||
|
||||
* Make Thread Sanitizer aware of file descriptor close in uv__close() (Ondřej
|
||||
Surý)
|
||||
|
||||
* darwin: fix iOS compilation and functionality (Hayden)
|
||||
|
||||
* linux: work around copy_file_range() cephfs bug (Ben Noordhuis)
|
||||
|
||||
* zos: implement uv_get_constrained_memory() (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: fix uv_get_free_memory() (Shuowang (Wayne) Zhang)
|
||||
|
||||
* zos: use CVTRLSTG to get total memory accurately (Shuowang (Wayne) Zhang)
|
||||
|
||||
* ibmi: Handle interface names longer than 10 chars (Kevin Adler)
|
||||
|
||||
* docs: update read-the-docs version of sphinx (Jameson Nash)
|
||||
|
||||
* unix: refactor uv_try_write (twosee)
|
||||
|
||||
* linux-core: add proper divide by zero assert (yiyuaner)
|
||||
|
||||
* misc: remove unnecessary _GNU_SOURCE macros (Darshan Sen)
|
||||
|
||||
* test: log to stdout to conform TAP spec (bbara)
|
||||
|
||||
* win,fs: fix C4090 warning with MSVC (SeverinLeonhardt)
|
||||
|
||||
* build: some systems provide dlopen() in libc (Andy Fiddaman)
|
||||
|
||||
* include: add EOVERFLOW status code mapping (Darshan Sen)
|
||||
|
||||
* unix,fs: use uv__load_relaxed and uv__store_relaxed (Darshan Sen)
|
||||
|
||||
* win: fix string encoding issue of uv_os_gethostname (Eagle Liang)
|
||||
|
||||
* unix,process: add uv__write_errno helper function (Ricky Zhou)
|
||||
|
||||
* Re-merge "unix,stream: clear read/write states on close/eof" (Jameson Nash)
|
||||
|
||||
* unix,core: fix errno handling in uv__getpwuid_r (Darshan Sen)
|
||||
|
||||
* errors: map ESOCKTNOSUPPORT errno (Ryan Liptak)
|
||||
|
||||
* doc: uv_read_stop always succeeds (Simon Kissane)
|
||||
|
||||
* inet: fix inconsistent return value of inet_ntop6 (twosee)
|
||||
|
||||
* darwin: fix -Wsometimes-uninitialized warning (twosee)
|
||||
|
||||
* stream: introduce uv_try_write2 function (twosee)
|
||||
|
||||
* poll,win: UV_PRIORITIZED option should not assert (twosee)
|
||||
|
||||
* src: DragonFlyBSD has mmsghdr struct too (David Carlier)
|
||||
|
||||
* cleanup,win: Remove _WIN32 guards on threadpool (James M Snell)
|
||||
|
||||
* freebsd: fix an incompatible pointer type warning (Darshan Sen)
|
||||
|
||||
* core: Correct the conditionals for {cloexec,nonblock}_ioctl (Ali Mohammad
|
||||
Pur)
|
||||
|
||||
* win,tcp: make uv_close work more like unix (Jameson Nash)
|
||||
|
||||
* doc: more accurate list of valid send_handle's (twosee)
|
||||
|
||||
* win,tcp: translate system errors correctly (twosee)
|
||||
|
||||
* unix: implement cpu_relax() on ppc64 (Ben Noordhuis)
|
||||
|
||||
* docs: move list of project links under PR control (Jameson Nash)
|
||||
|
||||
* test: wrong pointer arithmetic multiplier (Erkhes N)
|
||||
|
||||
* doc: switch discussion forum to github (Jameson Nash)
|
||||
|
||||
* idna: fix OOB read in punycode decoder (Ben Noordhuis)
|
||||
|
||||
* build: make sure -fvisibility=hidden is set (Santiago Gimeno)
|
||||
|
||||
* illumos: event ports to epoll (tjarlama)
|
||||
|
||||
* illumos,tty: UV_TTY_MODE_IO waits for 4 bytes (Joshua M. Clulow)
|
||||
|
||||
* doc: add vtjnash GPG ID (Jameson Nash)
|
||||
|
||||
* linux: read CPU model information on ppc (Richard Lau)
|
||||
|
||||
* darwin: fix uv_barrier race condition (Guilherme Íscaro)
|
||||
|
||||
* unix,stream: fix loop hang after uv_shutdown (Jameson Nash)
|
||||
|
||||
* doc,udp: note that suggested_size is 1 max-sized dgram (Ryan Liptak)
|
||||
|
||||
* mingw: fix building for ARM/AArch64 (Martin Storsjö)
|
||||
|
||||
* unix: strnlen is not available on Solaris 10 (Claes Nästén)
|
||||
|
||||
* sunos: restore use of event ports (Andy Fiddaman)
|
||||
|
||||
* sunos,cmake: use thread-safe errno (Andy Fiddaman)
|
||||
|
||||
|
||||
2021.02.14, Version 1.41.0 (Stable), 1dff88e5161cba5c59276d2070d2e304e4dcb242
|
||||
|
||||
Changes since version 1.40.0:
|
||||
|
||||
* mailmap: update contact information for richardlau (Richard Lau)
|
||||
|
||||
* build: add asan checks (gengjiawen)
|
||||
|
||||
* unix: report bind error in uv_tcp_connect() (Ben Noordhuis)
|
||||
|
||||
* doc: uv_tcp_bind() never returns UV_EADDRINUSE (Ben Noordhuis)
|
||||
|
||||
* test: fix pump and tcp_write_batch benchmarks (Santiago Gimeno)
|
||||
|
||||
* doc: mark IBM i as Tier 2 support (Jesse Gorzinski)
|
||||
|
||||
* doc,poll: add notes (repeated cb & cancel pending cb) (Elad Nachmias)
|
||||
|
||||
* linux: fix -Wincompatible-pointer-types warning (Ben Noordhuis)
|
||||
|
||||
* linux: fix -Wsign-compare warning (Ben Noordhuis)
|
||||
|
||||
* android: add system call api guards (Ben Noordhuis)
|
||||
|
||||
* unix,win: harmonize uv_read_start() error handling (Ben Noordhuis)
|
||||
|
||||
* unix,win: more uv_read_start() argument validation (Ben Noordhuis)
|
||||
|
||||
* build: turn on -fno-strict-aliasing (Ben Noordhuis)
|
||||
|
||||
* stream: add uv_pipe and uv_socketpair to the API (Jameson Nash)
|
||||
|
||||
* unix,win: initialize timer `timeout` field (Ben Noordhuis)
|
||||
|
||||
* bsd-ifaddrs: improve comments (Darshan Sen)
|
||||
|
||||
* test: remove unnecessary uv_fs_stat() calls (Ben Noordhuis)
|
||||
|
||||
* fs: fix utime/futime timestamp rounding errors (Ben Noordhuis)
|
||||
|
||||
* test: ensure reliable floating point comparison (Jameson Nash)
|
||||
|
||||
* unix,fs: fix uv_fs_sendfile() (Santiago Gimeno)
|
||||
|
||||
* unix: fix uv_fs_stat when using statx (Simon Kadisch)
|
||||
|
||||
* linux,macos: fix uv_set_process_title regression (Momtchil Momtchev)
|
||||
|
||||
* doc: clarify UDP errors and recvmmsg (Ethel Weston)
|
||||
|
||||
* test-getaddrinfo: use example.invalid (Drew DeVault)
|
||||
|
||||
* Revert "build: fix android autotools build" (Bernardo Ramos)
|
||||
|
||||
* unix,fs: on DVS fs, statx returns EOPNOTSUPP (Mark Klein)
|
||||
|
||||
* win, fs: mkdir really return UV_EINVAL for invalid names (Nicholas Vavilov)
|
||||
|
||||
* tools: migrate tools/make_dist_html.py to python3 (Dominique Dumont)
|
||||
|
||||
* unix: fix uv_uptime() on linux (schamberg97)
|
||||
|
||||
* unix: check for partial copy_file_range support (Momtchil Momtchev)
|
||||
|
||||
* win: bump minimum supported version to windows 8 (Ben Noordhuis)
|
||||
|
||||
* poll,unix: ensure safety of rapid fd reuse (Bob Weinand)
|
||||
|
||||
* test: fix some warnings (Issam E. Maghni)
|
||||
|
||||
* unix: fix uv_uptime() regression (Santiago Gimeno)
|
||||
|
||||
* doc: fix versionadded metadata (cjihrig)
|
||||
|
||||
* test: fix 'incompatible pointer types' warnings (cjihrig)
|
||||
|
||||
* unix: check for EXDEV in uv__fs_sendfile() (Darshan Sen)
|
||||
|
||||
|
||||
2020.09.26, Version 1.40.0 (Stable), 4e69e333252693bd82d6338d6124f0416538dbfc
|
||||
|
||||
Changes since version 1.39.0:
|
||||
|
||||
* udp: add UV_UDP_MMSG_FREE recv_cb flag (Ryan Liptak)
|
||||
|
||||
* include: re-map UV__EPROTO from 4046 to -4046 (YuMeiJie)
|
||||
|
||||
* doc: correct UV_UDP_MMSG_FREE version added (cjihrig)
|
||||
|
||||
* doc: add uv_metrics_idle_time() version metadata (Ryan Liptak)
|
||||
|
||||
* win,tty: pass through utf-16 surrogate pairs (Mustafa M)
|
||||
|
||||
* unix: fix DragonFly BSD build (Aleksej Lebedev)
|
||||
|
||||
* win,udp: fix error code returned by connect() (Santiago Gimeno)
|
||||
|
||||
* src: suppress user_timeout maybe-uninitialized (Daniel Bevenius)
|
||||
|
||||
* test: fix compiler warning (Vladimír Čunát)
|
||||
|
||||
* build: fix the Haiku cmake build (David Carlier)
|
||||
|
||||
* linux: fix i386 sendmmsg/recvmmsg support (Ben Noordhuis)
|
||||
|
||||
* build: add libuv-static pkg-config file (Nikolay Mitev)
|
||||
|
||||
* unix,win: add uv_timer_get_due_in() (Ulrik Strid)
|
||||
|
||||
* build,unix: add QNX support (Elad Lahav)
|
||||
|
||||
* include: remove incorrect UV__ERR() for EPROTO (cjihrig)
|
||||
|
||||
|
||||
2020.08.26, Version 1.39.0 (Stable), 25f4b8b8a3c0f934158cd37a37b0525d75ca488e
|
||||
|
||||
Changes since version 1.38.1:
|
||||
|
||||
* unix: use relaxed loads/stores for clock id (Ben Noordhuis)
|
||||
|
||||
* build,win: link to user32.lib and advapi32.lib (George Zhao)
|
||||
|
||||
* unix: squelch harmless valgrind warning (ssrlive)
|
||||
|
||||
* include: fx c++ style comments warnings (Turbinya)
|
||||
|
||||
* build,cmake: Change installation location on MinGW (erw7)
|
||||
|
||||
* linux: use copy_file_range for uv_fs_copyfile when possible (Carter Li)
|
||||
|
||||
* win,tcp: avoid reinserting a pending request (
|
||||
|
||||
* docs: improve the descriptions for get memory info (Juan Sebastian velez
|
||||
Posada)
|
||||
|
||||
* test: add udp-mmsg test (Ryan Liptak)
|
||||
|
||||
* udp: add uv_udp_using_recvmmsg query (Ryan Liptak)
|
||||
|
||||
* doc: add more error constants (TK-one)
|
||||
|
||||
* zos: fix potential event loop stall (Trevor Norris)
|
||||
|
||||
* include: add internal fields struct to uv_loop_t (Trevor Norris)
|
||||
|
||||
* core: add API to measure event loop idle time (Trevor Norris)
|
||||
|
||||
* win,fs: use CreateDirectoryW instead of _wmkdir (Mustafa M)
|
||||
|
||||
* win,nfc: fix integer comparison signedness (escherstair)
|
||||
|
||||
* win,nfc: use
|
||||
|
||||
* win,nfc: removed some unused variables (escherstair)
|
||||
|
||||
* win,nfc: add missing return statement (escherstair)
|
||||
|
||||
* win,nfc: disable clang-format for
|
||||
|
||||
* darwin: use IOKit for uv_cpu_info (Evan Lucas)
|
||||
|
||||
* test: fix thread race in process_title_threadsafe (Ben Noordhuis)
|
||||
|
||||
* win,fs: avoid implicit access to _doserrno (Jameson Nash)
|
||||
|
||||
* test: give hrtime test a custom 20s timeout (Jameson Nash)
|
||||
|
||||
* build: add more failed test, for qemu version bump (gengjiawen)
|
||||
|
||||
* unix: handle src, dest same in uv_fs_copyfile() (cjihrig)
|
||||
|
||||
* unix: error when uv_setup_args() is not called (Ryan Liptak)
|
||||
|
||||
* aix: protect uv_exepath() from uv_set_process_title() (Richard Lau)
|
||||
|
||||
* fs: clobber req->path on uv_fs_mkstemp() error (tjarlama)
|
||||
|
||||
* cmake: fix compile error C2001 on Chinese Windows (司徒玟琅)
|
||||
|
||||
* test: avoid double evaluation in ASSERT_BASE macro (tjarlama)
|
||||
|
||||
* tcp: fail instantly if local port is unbound (Bartosz Sosnowski)
|
||||
|
||||
* doc: fix most sphinx warnings (Jameson Nash)
|
||||
|
||||
* nfci: address some style nits (Jameson Nash)
|
||||
|
||||
* unix: don't use _POSIX_PATH_MAX (Ben Noordhuis)
|
||||
|
||||
|
||||
2020.07.04, Version 1.38.1 (Stable), e8b989ea1f7f9d4083511a2caec7791e9abd1871
|
||||
|
||||
Changes since version 1.38.0:
|
||||
|
||||
* test: use last matching qemu version (cjihrig)
|
||||
|
||||
* win, util: rearrange uv_hrtime (Bartosz Sosnowski)
|
||||
|
||||
* test: skip signal_multiple_loops test on QEMU (gengjiawen)
|
||||
|
||||
* build: add android build to CI (gengjiawen)
|
||||
|
||||
* test: extend fs_event_error_reporting timeout (cjihrig)
|
||||
|
||||
* build: link libkvm on netbsd only (Alexander Tokmakov)
|
||||
|
||||
* linux: refactor /proc file reader logic (Ben Noordhuis)
|
||||
|
||||
* linux: read load average from /proc/loadavg (Ben Noordhuis)
|
||||
|
||||
* android: remove patch code for below 21 (gengjiawen)
|
||||
|
||||
* win: fix visual studio 2008 build (Arenoros)
|
||||
|
||||
* win,tty: fix deadlock caused by inconsistent state (lander0s)
|
||||
|
||||
* unix: use relaxed loads/stores for feature checks (Ben Noordhuis)
|
||||
|
||||
* build: don't .gitignore m4/ax_pthread.m4 (Ben Noordhuis)
|
||||
|
||||
* unix: fix gcc atomics feature check (Ben Noordhuis)
|
||||
|
||||
* darwin: work around clock jumping back in time (Ben Noordhuis)
|
||||
|
||||
* udp: fix write_queue cleanup on sendmmsg error (Santiago Gimeno)
|
||||
|
||||
* src: build fix for Android (David Carlier)
|
||||
|
||||
|
||||
2020.05.18, Version 1.38.0 (Stable), 1ab9ea3790378f9f25c4e78e9e2b511c75f9c9ed
|
||||
|
||||
Changes since version 1.37.0:
|
||||
|
||||
* test: skip poll_duplex and poll_unidirectional on PASE (Xu Meng)
|
||||
|
||||
* linux: make cpu_times consistently be milliseconds (James Ross)
|
||||
|
||||
* win: DRY uv_poll_start() and uv_poll_stop() (Ben Noordhuis)
|
||||
|
||||
* win: DRY uv_poll_close() (Ben Noordhuis)
|
||||
|
||||
* unix,win: add uv_library_shutdown() (Ben Noordhuis)
|
||||
|
||||
* unix: yield cpu when spinlocking on async handle (Ben Noordhuis)
|
||||
|
||||
* win: remove dep on GetQueuedCompletionStatusEx (Colin Finck)
|
||||
|
||||
* doc: correct source lines (Shohei YOSHIDA)
|
||||
|
||||
* build,android: fix typo (twosee)
|
||||
|
||||
* doc: uv_cancel() handles uv_random_t requests (Philip Chimento)
|
||||
|
||||
* doc: fix unescaped character (Philip Chimento)
|
||||
|
||||
* build,cmake: fix compilation on old MinGW (erw7)
|
||||
|
||||
* build: remove unnessesary MSVC warnings (Bartosz Sosnowski)
|
||||
|
||||
* win: make uv_udp_init_ex() accept UV_UDP_RECVMMSG (Ben Noordhuis)
|
||||
|
||||
* unix: simplify uv__udp_init_ex() (Ben Noordhuis)
|
||||
|
||||
* win: remove MAX_PATH limitations (Bartosz Sosnowski)
|
||||
|
||||
* build, win: add long path aware manifest (Bartosz Sosnowski)
|
||||
|
||||
* doc: check/idle/prepare functions always succeed (Ben Noordhuis)
|
||||
|
||||
* darwin: fix build with non-apple compilers (Ben Noordhuis)
|
||||
|
||||
* win: support environment variables > 32767 chars (Ben Noordhuis)
|
||||
|
||||
* unix: fully initialize struct msghdr (Ben Noordhuis)
|
||||
|
||||
* doc: add uv_replace_allocator thread safety warning (twosee)
|
||||
|
||||
* unix: fix int overflow when copying large files (Michal Artazov)
|
||||
|
||||
* fs: report original error (Bartosz Sosnowski)
|
||||
|
||||
* win, fs: add IO_REPARSE_TAG_APPEXECLINK support (Bartosz Sosnowski)
|
||||
|
||||
* doc: fix formatting (Ben Noordhuis)
|
||||
|
||||
* unix: fix memory leak when uv_loop_init() fails (Anna Henningsen)
|
||||
|
||||
* unix: shrink uv_udp_set_source_membership() stack (Ben Noordhuis)
|
||||
|
||||
* unix,win: fix wrong sizeof argument to memcpy() (Ben Noordhuis)
|
||||
|
||||
* build: check for libraries not provided by libc (Jeroen Roovers)
|
||||
|
||||
* doc: fix the order of arguments to calloc() (MasterDuke17)
|
||||
|
||||
* unix: don't abort when getrlimit() fails (Ben Noordhuis)
|
||||
|
||||
* test: support common user profile on IBMi (Xu Meng)
|
||||
|
||||
* build: test on more platforms via QEMU in CI (gengjiawen)
|
||||
|
||||
|
||||
2020.04.20, Version 1.37.0 (Stable), 02a9e1be252b623ee032a3137c0b0c94afbe6809
|
||||
|
||||
Changes since version 1.36.0:
|
||||
|
||||
* timer: remove redundant check in heap compare (Yash Ladha)
|
||||
|
||||
* udp: add flag to enable recvmmsg(2) explicitly (Saúl Ibarra Corretgé)
|
||||
|
||||
|
||||
2020.04.16, Version 1.36.0 (Stable), 533b738838ad8407032e14b6772b29ef9af63cfa
|
||||
|
||||
Changes since version 1.35.0:
|
||||
|
||||
* build: add aix-common.c for AIX cmake build (Jesse Gorzinski)
|
||||
|
||||
* zos: explicitly mark message queue events (Irek Fakhrutdinov)
|
||||
|
||||
* zos: move mq check out of loop to save cpu cycles (Irek Fakhrutdinov)
|
||||
|
||||
* zos: add checks to ensure behavior of epoll_wait (Irek Fakhrutdinov)
|
||||
|
||||
* src: add uv__reallocf() (Ben Noordhuis)
|
||||
|
||||
* build: ibmi support for cmake (Jesse Gorzinski)
|
||||
|
||||
* build: fix gyp build for Android API >= 28 (Lin Zhang)
|
||||
|
||||
* udp: return recvmmsg-ed datagrams in order (Saúl Ibarra Corretgé)
|
||||
|
||||
* zos,test: fix spawn_empty_env for shared library build (Richard Lau)
|
||||
|
||||
* zos: fix non-Release builds (Richard Lau)
|
||||
|
||||
* zos: fix return value on expired nanosleep() call (Richard Lau)
|
||||
|
||||
* build: fix z/OS cmake build (Richard Lau)
|
||||
|
||||
* test: add a bunch of ASSERT macros (Santiago Gimeno)
|
||||
|
||||
* test: remove unused extern declaration (Ben Noordhuis)
|
||||
|
||||
* test: canonicalize argv[0] in exepath test (Ben Noordhuis)
|
||||
|
||||
* test: simplify platform_init() (Ben Noordhuis)
|
||||
|
||||
* ibmi: Fix isatty EBADF handling and refactor (Kevin Adler)
|
||||
|
||||
* test: Test EBADF tty handling (Kevin Adler)
|
||||
|
||||
* build: make cmake build benchmarks (Ben Noordhuis)
|
||||
|
||||
* win: use RtlGenRandom from advapi32.dll directly (Ben Noordhuis)
|
||||
|
||||
* android: fix OOB write in uv_interface_addresses() (Lin Zhang)
|
||||
|
||||
* test: pass test when hostname is single character (毛毛)
|
||||
|
||||
* ibmi: set the highest process priority to -10 (Xu Meng)
|
||||
|
||||
* build: remove support for gyp (Ben Noordhuis)
|
||||
|
||||
* doc: add note to README on cross-compiling (Ben Noordhuis)
|
||||
|
||||
* fs: add uv_fs_lutime() (Sk Sajidul Kadir)
|
||||
|
||||
* unix: implement cpu_relax() for arm (David Carlier)
|
||||
|
||||
* linux: fix uv__accept4() (twosee)
|
||||
|
||||
* win: handle file paths in uv_fs_statfs() (erw7)
|
||||
|
||||
* unix: fix uv_os_environ() null pointer check (Rikard Falkeborn)
|
||||
|
||||
* win: fix uv_os_environ() null pointer check (Rikard Falkeborn)
|
||||
|
||||
* unix: fix compilation on macOS 32-bit architectures (Brad King)
|
||||
|
||||
* win: replace alloca() with stack-based array (Ben Noordhuis)
|
||||
|
||||
|
||||
2020.03.12, Version 1.35.0 (Stable), e45f1ec38db882f8dc17b51f51a6684027034609
|
||||
|
||||
Changes since version 1.34.2:
|
||||
|
||||
|
4
LICENSE
4
LICENSE
@ -64,7 +64,3 @@ The externally maintained libraries used by libuv are:
|
||||
|
||||
- pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
|
||||
Three clause BSD license.
|
||||
|
||||
- android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design
|
||||
Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement
|
||||
n° 289016). Three clause BSD license.
|
||||
|
101
LINKS.md
Normal file
101
LINKS.md
Normal file
@ -0,0 +1,101 @@
|
||||
### Apps / VM
|
||||
* [BIND 9](https://bind.isc.org/): DNS software system including an authoritative server, a recursive resolver and related utilities.
|
||||
* [cjdns](https://github.com/cjdelisle/cjdns): Encrypted self-configuring network/VPN routing engine
|
||||
* [clearskies_core](https://github.com/larroy/clearskies_core): Clearskies file synchronization program. (C++11)
|
||||
* [CMake](https://cmake.org) open-source, cross-platform family of tools designed to build, test and package software
|
||||
* [Coherence](https://github.com/liesware/coherence/): Cryptographic server for modern web apps.
|
||||
* [DPS-For-IoT](https://github.com/intel/dps-for-iot/wiki): Fully distributed publish/subscribe protocol.
|
||||
* [HashLink](https://github.com/HaxeFoundation/hashlink): Haxe run-time with libuv support included.
|
||||
* [Haywire](https://github.com/kellabyte/Haywire): Asynchronous HTTP server.
|
||||
* [H2O](https://github.com/h2o/h2o): An optimized HTTP server with support for HTTP/1.x and HTTP/2.
|
||||
* [Igropyr](https://github.com/guenchi/Igropyr): a async Scheme http server base on libuv.
|
||||
* [Julia](http://julialang.org/): Scientific computing programming language
|
||||
* [Kestrel](https://github.com/aspnet/AspNetCore/tree/master/src/Servers/Kestrel): web server (C# + libuv + [ASP.NET Core](http://github.com/aspnet))
|
||||
* [Knot DNS Resolver](https://www.knot-resolver.cz/): A minimalistic DNS caching resolver
|
||||
* [Lever](http://leverlanguage.com): runtime, libuv at the 0.9.0 release
|
||||
* [libnode](https://github.com/plenluno/libnode): C++ implementation of Node.js
|
||||
* [libstorj](https://github.com/Storj/libstorj): Library for interacting with Storj network
|
||||
* [libuv_message_framing](https://github.com/litesync/libuv_message_framing) Message-based communication for libuv
|
||||
* [luaw](https://github.com/raksoras/luaw): Lua web server backed by libuv
|
||||
* [Luvit](http://luvit.io): Node.JS for the Lua Inventor
|
||||
* [mo](https://github.com/wehu/mo): Scheme (guile) + libuv runtime
|
||||
* [MoarVM](https://github.com/MoarVM/MoarVM): a VM for [Rakudo](http://rakudo.org/) [Raku](http://raku.org)
|
||||
* [Mysocks](https://github.com/zhou0/mysocks): a cross-platform [Shadowsocks](https://shadowsocks.org) client
|
||||
* [mediasoup](http://mediasoup.org): Powerful WebRTC SFU for Node.js
|
||||
* [Neovim](https://neovim.io/): A major refactor of Vim.
|
||||
* [node9](https://github.com/jvburnes/node9): A portable, hybrid, distributed OS based on Inferno, LuaJIT and Libuv
|
||||
* [node.js](http://www.nodejs.org/): Javascript (using Google's V8) + libuv
|
||||
* [node.native](https://github.com/d5/node.native): node.js-like API for C++11
|
||||
* [nodeuv](https://github.com/nodeuv): An organization with several c++ wrappers for libs which are used in node.js.
|
||||
* [phastlight](https://github.com/phastlight/phastlight): Command line tool and web server written in PHP 5.3+ inspired by Node.js
|
||||
* [pilight](https://www.pilight.org/): home automation ("domotica")
|
||||
* [pixie](https://github.com/pixie-lang/pixie): clojure-inspired lisp with a tracing JIT
|
||||
* [potion](https://github.com/perl11/potion)/[p2](https://github.com/perl11/p2): runtime
|
||||
* [racer](https://libraries.io/rubygems/racer): Ruby web server written as an C extension
|
||||
* [spider-gazelle](https://github.com/cotag/spider-gazelle): Ruby web server using libuv bindings
|
||||
* [Suave](http://suave.io/): A simple web development F# library providing a lightweight web server and a set of combinators to manipulate route flow and task composition
|
||||
* [Swish](https://github.com/becls/swish/): Concurrency engine with Erlang-like concepts. Includes a web server.
|
||||
* [Trevi](https://github.com/Yoseob/Trevi): A powerful Swift Web Application Server Framework Project
|
||||
* [Urbit](http://urbit.org): runtime
|
||||
* [uv_callback](https://github.com/litesync/uv_callback) libuv thread communication
|
||||
* [uvloop](https://github.com/MagicStack/uvloop): Ultra fast implementation of python's asyncio event loop on top of libuv
|
||||
* [Wren CLI](https://github.com/wren-lang/wren-cli): For io, process, scheduler and timer modules
|
||||
|
||||
### Other
|
||||
* [libtuv](https://github.com/Samsung/libtuv): libuv fork for IoT and embedded systems
|
||||
|
||||
### Bindings
|
||||
* [Ring](http://ring-lang.net)
|
||||
* [RingLibuv](http://ring-lang.sourceforge.net/doc1.7/libuv.html)
|
||||
* Ruby
|
||||
* [libuv](https://github.com/cotag/libuv)
|
||||
* [uvrb](https://github.com/avalanche123/uvrb)
|
||||
* [ruv](https://github.com/aq1018/ruv)
|
||||
* [rbuv](https://github.com/rbuv/rbuv)
|
||||
* [mruby-uv](https://github.com/mattn/mruby-uv): mruby binding
|
||||
* Lua
|
||||
* [luv](https://github.com/creationix/luv)
|
||||
* [lev](https://github.com/connectFree/lev)
|
||||
* [lluv](https://github.com/moteus/lua-lluv)
|
||||
* C++11
|
||||
* [uvpp](https://github.com/larroy/uvpp) - Not complete, exposes very few aspects of `libuv`
|
||||
* C++17
|
||||
* [uvw](https://github.com/skypjack/uvw) - Header-only, event based, tiny and easy to use *libuv* wrapper in modern C++.
|
||||
* Python
|
||||
* [Pyuv](https://github.com/saghul/pyuv)
|
||||
* [uvloop](https://github.com/MagicStack/uvloop) - Ultra fast asyncio event loop.
|
||||
* [gevent](http://www.gevent.org) - Coroutine-based concurrency library for Python
|
||||
* C#
|
||||
* [NetUV](http://github.com/StormHub/NetUV)
|
||||
* [LibuvSharp](http://github.com/txdv/LibuvSharp)
|
||||
* Perl 5
|
||||
* [UV](https://metacpan.org/pod/UV)
|
||||
* [Raku](https://raku.org/)
|
||||
* [MoarVM](https://github.com/MoarVM/MoarVM) [uses](http://6guts.wordpress.com/2013/05/31/moarvm-a-virtual-machine-for-nqp-and-rakudo/) libuv
|
||||
* PHP
|
||||
* [php-uv](https://github.com/bwoebi/php-uv)
|
||||
* Go
|
||||
* [go-uv](https://github.com/mattn/go-uv)
|
||||
* OCaml
|
||||
* [luv](https://github.com/aantron/luv)
|
||||
* [uwt](https://github.com/fdopen/uwt)
|
||||
* ooc
|
||||
* [ooc-uv](https://github.com/nddrylliog/ooc-uv)
|
||||
* dylan
|
||||
* [uv-dylan](https://github.com/waywardmonkeys/uv-dylan)
|
||||
* R
|
||||
* [httpuv](https://github.com/rstudio/httpuv): HTTP and WebSocket server library for R
|
||||
* [fs](https://fs.r-lib.org/): Cross-platform file system operations
|
||||
* Java
|
||||
* [libuv-java](https://java.net/projects/avatar-js/sources/libuv-java/show): Java bindings
|
||||
* Nim
|
||||
* [nimuv](https://github.com/2vg/nimuv): Nim bindings
|
||||
* Lisp
|
||||
* [cl-libuv](https://github.com/orthecreedence/cl-libuv) Common Lisp bindings
|
||||
* [cl-async](https://github.com/orthecreedence/cl-async) Common Lisp async abstraction on top of cl-libuv
|
||||
* [Céu](http://www.ceu-lang.org)
|
||||
* [Céu-libuv](https://github.com/fsantanna/ceu-libuv)
|
||||
* Delphi
|
||||
* [node.pas](https://github.com/vovach777/node.pas) NodeJS-like ecosystem
|
||||
* Haskell
|
||||
* [Z.Haskell](https://z.haskell.world)
|
@ -16,6 +16,9 @@ libuv is currently managed by the following individuals:
|
||||
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
|
||||
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
|
||||
* **Jameson Nash** ([@vtjnash](https://github.com/vtjnash))
|
||||
- GPG key: AEAD 0A4B 6867 6775 1A0E 4AEF 34A2 5FB1 2824 6514 (pubkey-vtjnash)
|
||||
- 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)
|
||||
|
63
Makefile.am
63
Makefile.am
@ -27,8 +27,8 @@ uvinclude_HEADERS = include/uv/errno.h \
|
||||
CLEANFILES =
|
||||
|
||||
lib_LTLIBRARIES = libuv.la
|
||||
libuv_la_CFLAGS = @CFLAGS@
|
||||
libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0
|
||||
libuv_la_CFLAGS = $(AM_CFLAGS)
|
||||
libuv_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 1:0:0
|
||||
libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/heap-inl.h \
|
||||
src/idna.c \
|
||||
@ -56,7 +56,7 @@ if WINNT
|
||||
uvinclude_HEADERS += include/uv/win.h include/uv/tree.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
|
||||
-DWIN32_LEAN_AND_MEAN \
|
||||
-D_WIN32_WINNT=0x0600
|
||||
-D_WIN32_WINNT=0x0602
|
||||
libuv_la_SOURCES += src/win/async.c \
|
||||
src/win/atomicops-inl.h \
|
||||
src/win/core.c \
|
||||
@ -123,23 +123,15 @@ EXTRA_DIST = test/fixtures/empty_file \
|
||||
include \
|
||||
docs \
|
||||
img \
|
||||
android-configure-arm \
|
||||
android-configure-arm64 \
|
||||
android-configure-x86 \
|
||||
android-configure-x86_64 \
|
||||
CONTRIBUTING.md \
|
||||
LICENSE \
|
||||
README.md \
|
||||
vcbuild.bat \
|
||||
common.gypi \
|
||||
gyp_uv.py \
|
||||
uv.gyp
|
||||
README.md
|
||||
|
||||
|
||||
|
||||
TESTS = test/run-tests
|
||||
check_PROGRAMS = test/run-tests
|
||||
test_run_tests_CFLAGS =
|
||||
test_run_tests_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
if SUNOS
|
||||
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
|
||||
@ -147,9 +139,8 @@ if SUNOS
|
||||
test_run_tests_CFLAGS += -pthreads
|
||||
endif
|
||||
|
||||
test_run_tests_LDFLAGS =
|
||||
test_run_tests_LDFLAGS = $(AM_LDFLAGS)
|
||||
test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/dns-server.c \
|
||||
test/echo-server.c \
|
||||
test/run-tests.c \
|
||||
test/runner.c \
|
||||
@ -201,6 +192,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-idna.c \
|
||||
test/test-ip4-addr.c \
|
||||
test/test-ip6-addr.c \
|
||||
test/test-ip-name.c \
|
||||
test/test-ipc-heavy-traffic-deadlock-bug.c \
|
||||
test/test-ipc-send-recv.c \
|
||||
test/test-ipc.c \
|
||||
@ -211,8 +203,11 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-loop-stop.c \
|
||||
test/test-loop-time.c \
|
||||
test/test-loop-configure.c \
|
||||
test/test-metrics.c \
|
||||
test/test-multiple-listen.c \
|
||||
test/test-mutexes.c \
|
||||
test/test-not-readable-nor-writable-on-read-error.c \
|
||||
test/test-not-writable-after-shutdown.c \
|
||||
test/test-osx-select.c \
|
||||
test/test-pass-always.c \
|
||||
test/test-ping-pong.c \
|
||||
@ -232,18 +227,21 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-poll-close.c \
|
||||
test/test-poll-close-doesnt-corrupt-stack.c \
|
||||
test/test-poll-closesocket.c \
|
||||
test/test-poll-multiple-handles.c \
|
||||
test/test-poll-oob.c \
|
||||
test/test-process-priority.c \
|
||||
test/test-process-title.c \
|
||||
test/test-process-title-threadsafe.c \
|
||||
test/test-queue-foreach-delete.c \
|
||||
test/test-random.c \
|
||||
test/test-readable-on-eof.c \
|
||||
test/test-ref.c \
|
||||
test/test-run-nowait.c \
|
||||
test/test-run-once.c \
|
||||
test/test-semaphore.c \
|
||||
test/test-shutdown-close.c \
|
||||
test/test-shutdown-eof.c \
|
||||
test/test-shutdown-simultaneous.c \
|
||||
test/test-shutdown-twice.c \
|
||||
test/test-signal-multiple-loops.c \
|
||||
test/test-signal-pending-on-close.c \
|
||||
@ -267,6 +265,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-tcp-flags.c \
|
||||
test/test-tcp-open.c \
|
||||
test/test-tcp-read-stop.c \
|
||||
test/test-tcp-read-stop-start.c \
|
||||
test/test-tcp-shutdown-after-write.c \
|
||||
test/test-tcp-unexpected-read.c \
|
||||
test/test-tcp-oob.c \
|
||||
@ -277,6 +276,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-tcp-try-write.c \
|
||||
test/test-tcp-try-write-error.c \
|
||||
test/test-tcp-write-queue-order.c \
|
||||
test/test-test-macros.c \
|
||||
test/test-thread-equal.c \
|
||||
test/test-thread.c \
|
||||
test/test-threadpool-cancel.c \
|
||||
@ -291,9 +291,11 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-udp-alloc-cb-fail.c \
|
||||
test/test-udp-bind.c \
|
||||
test/test-udp-connect.c \
|
||||
test/test-udp-connect6.c \
|
||||
test/test-udp-create-socket-early.c \
|
||||
test/test-udp-dgram-too-big.c \
|
||||
test/test-udp-ipv6.c \
|
||||
test/test-udp-mmsg.c \
|
||||
test/test-udp-multicast-interface.c \
|
||||
test/test-udp-multicast-interface6.c \
|
||||
test/test-udp-multicast-join.c \
|
||||
@ -304,6 +306,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-udp-send-and-recv.c \
|
||||
test/test-udp-send-hang-loop.c \
|
||||
test/test-udp-send-immediate.c \
|
||||
test/test-udp-sendmmsg-error.c \
|
||||
test/test-udp-send-unreachable.c \
|
||||
test/test-udp-try-send.c \
|
||||
test/test-uname.c \
|
||||
@ -346,7 +349,8 @@ test_run_tests_CFLAGS += -D__EXTENSIONS__ \
|
||||
endif
|
||||
|
||||
if OS390
|
||||
test_run_tests_CFLAGS += -D_UNIX03_THREADS \
|
||||
test_run_tests_CFLAGS += -D_ISOC99_SOURCE \
|
||||
-D_UNIX03_THREADS \
|
||||
-D_UNIX03_SOURCE \
|
||||
-D_OPEN_SYS_IF_EXT=1 \
|
||||
-D_OPEN_SYS_SOCK_IPV6 \
|
||||
@ -380,21 +384,12 @@ uvinclude_HEADERS += include/uv/posix.h
|
||||
libuv_la_SOURCES += src/unix/aix-common.c \
|
||||
src/unix/ibmi.c \
|
||||
src/unix/posix-poll.c \
|
||||
src/unix/no-fsevents.c \
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/no-fsevents.c
|
||||
endif
|
||||
|
||||
if ANDROID
|
||||
uvinclude_HEADERS += include/uv/android-ifaddrs.h
|
||||
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
|
||||
src/unix/linux-core.c \
|
||||
src/unix/linux-inotify.c \
|
||||
src/unix/linux-syscalls.c \
|
||||
src/unix/procfs-exepath.c \
|
||||
src/unix/pthread-fixes.c \
|
||||
src/unix/random-getrandom.c \
|
||||
src/unix/random-sysctl-linux.c \
|
||||
src/unix/sysinfo-loadavg.c
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/pthread-fixes.c
|
||||
endif
|
||||
|
||||
if CYGWIN
|
||||
@ -416,8 +411,9 @@ uvinclude_HEADERS += include/uv/darwin.h
|
||||
libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1
|
||||
libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/darwin.c \
|
||||
src/unix/darwin-proctitle.c \
|
||||
src/unix/darwin-stub.h \
|
||||
src/unix/darwin.c \
|
||||
src/unix/fsevents.c \
|
||||
src/unix/kqueue.c \
|
||||
src/unix/proctitle.c \
|
||||
@ -459,9 +455,12 @@ endif
|
||||
|
||||
if HURD
|
||||
uvinclude_HEADERS += include/uv/posix.h
|
||||
libuv_la_SOURCES += src/unix/no-fsevents.c \
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/no-fsevents.c \
|
||||
src/unix/no-proctitle.c \
|
||||
src/unix/posix-hrtime.c \
|
||||
src/unix/posix-poll.c
|
||||
src/unix/posix-poll.c \
|
||||
src/unix/hurd.c
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
@ -475,7 +474,7 @@ libuv_la_SOURCES += src/unix/linux-core.c \
|
||||
src/unix/proctitle.c \
|
||||
src/unix/random-getrandom.c \
|
||||
src/unix/random-sysctl-linux.c \
|
||||
src/unix/sysinfo-loadavg.c
|
||||
src/unix/epoll.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"Name": "libuv",
|
||||
"License": "MIT License",
|
||||
"License File": "LICENSE",
|
||||
"Version Number": "v1.35.0",
|
||||
"Version Number": "v1.44.1",
|
||||
"Owner": "sunbingxin@huawei.com",
|
||||
"Upstream URL": "https://github.com/libuv/libuv",
|
||||
"Description": "libuv is a multi-platform support library with a focus on asynchronous I/O."
|
||||
|
239
README.md
239
README.md
@ -5,7 +5,7 @@
|
||||
libuv is a multi-platform support library with a focus on asynchronous I/O. It
|
||||
was primarily developed for use by [Node.js][], but it's also
|
||||
used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/),
|
||||
[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/wiki/Projects-that-use-libuv).
|
||||
[uvloop](https://github.com/MagicStack/uvloop), and [others](https://github.com/libuv/libuv/blob/v1.x/LINKS.md).
|
||||
|
||||
## Feature highlights
|
||||
|
||||
@ -48,9 +48,8 @@ The documentation is licensed under the CC BY 4.0 license. Check the [LICENSE-do
|
||||
|
||||
## Community
|
||||
|
||||
* [Support](https://github.com/libuv/help)
|
||||
* [Support](https://github.com/libuv/libuv/discussions)
|
||||
* [Mailing list](http://groups.google.com/group/libuv)
|
||||
* [IRC chatroom (#libuv@irc.freenode.org)](http://webchat.freenode.net?channels=libuv&uio=d4)
|
||||
|
||||
## Documentation
|
||||
|
||||
@ -152,47 +151,14 @@ $ gpg --verify libuv-1.7.0.tar.gz.sign
|
||||
|
||||
## Build Instructions
|
||||
|
||||
For GCC there are two build methods: via autotools or via [GYP][].
|
||||
GYP is a meta-build system which can generate MSVS, Makefile, and XCode
|
||||
backends. It is best used for integration into other projects.
|
||||
For UNIX-like platforms, including macOS, there are two build methods:
|
||||
autotools or [CMake][].
|
||||
|
||||
To build with autotools:
|
||||
For Windows, [CMake][] is the only supported build method and has the
|
||||
following prerequisites:
|
||||
|
||||
```bash
|
||||
$ sh autogen.sh
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
```
|
||||
<details>
|
||||
|
||||
To build with [CMake](https://cmake.org/):
|
||||
|
||||
```bash
|
||||
$ mkdir -p out/cmake ; cd out/cmake # create build directory
|
||||
$ cmake ../.. -DBUILD_TESTING=ON # generate project with test
|
||||
$ cmake --build . # build
|
||||
$ ctest -C Debug --output-on-failure # run tests
|
||||
|
||||
# Or manually run tests:
|
||||
$ ./out/cmake/uv_run_tests # shared library build
|
||||
$ ./out/cmake/uv_run_tests_a # static library build
|
||||
```
|
||||
|
||||
To build with GYP, first run:
|
||||
|
||||
```bash
|
||||
$ git clone https://chromium.googlesource.com/external/gyp build/gyp
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
Prerequisites:
|
||||
|
||||
* [Python 2.6 or 2.7][] as it is required
|
||||
by [GYP][].
|
||||
If python is not in your path, set the environment variable `PYTHON` to its
|
||||
location. For example: `set PYTHON=C:\Python27\python.exe`
|
||||
* One of:
|
||||
* [Visual C++ Build Tools][]
|
||||
* [Visual Studio 2015 Update 3][], all editions
|
||||
@ -205,67 +171,44 @@ Prerequisites:
|
||||
[Git for Windows][] includes Git Bash
|
||||
and tools which can be included in the global `PATH`.
|
||||
|
||||
To build, launch a git shell (e.g. Cmd or PowerShell), run `vcbuild.bat`
|
||||
(to build with VS2017 you need to explicitly add a `vs2017` argument),
|
||||
which will checkout the GYP code into `build/gyp`, generate `uv.sln`
|
||||
as well as the necesery related project files, and start building.
|
||||
</details>
|
||||
|
||||
```console
|
||||
> vcbuild
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```console
|
||||
> vcbuild vs2017
|
||||
```
|
||||
|
||||
To run the tests:
|
||||
|
||||
```console
|
||||
> vcbuild test
|
||||
```
|
||||
|
||||
To see all the options that could passed to `vcbuild`:
|
||||
|
||||
```console
|
||||
> vcbuild help
|
||||
vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild] [vs2017] [x86/x64] [static/shared]
|
||||
Examples:
|
||||
vcbuild.bat : builds debug build
|
||||
vcbuild.bat test : builds debug build and runs tests
|
||||
vcbuild.bat release bench: builds release build and runs benchmarks
|
||||
```
|
||||
|
||||
|
||||
### Unix
|
||||
|
||||
For Debug builds (recommended) run:
|
||||
To build with autotools:
|
||||
|
||||
```bash
|
||||
$ ./gyp_uv.py -f make
|
||||
$ make -C out
|
||||
$ sh autogen.sh
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
```
|
||||
|
||||
For Release builds run:
|
||||
To build with [CMake][]:
|
||||
|
||||
```bash
|
||||
$ ./gyp_uv.py -f make
|
||||
$ BUILDTYPE=Release make -C out
|
||||
$ mkdir -p build
|
||||
|
||||
$ (cd build && cmake .. -DBUILD_TESTING=ON) # generate project with tests
|
||||
$ cmake --build build # add `-j <n>` with cmake >= 3.12
|
||||
|
||||
# Run tests:
|
||||
$ (cd build && ctest -C Debug --output-on-failure)
|
||||
|
||||
# Or manually run tests:
|
||||
$ build/uv_run_tests # shared library build
|
||||
$ build/uv_run_tests_a # static library build
|
||||
```
|
||||
|
||||
Run `./gyp_uv.py -f make -Dtarget_arch=x32` to build [x32][] binaries.
|
||||
|
||||
### OS X
|
||||
|
||||
Run:
|
||||
To cross-compile with [CMake][] (unsupported but generally works):
|
||||
|
||||
```bash
|
||||
$ ./gyp_uv.py -f xcode
|
||||
$ xcodebuild -ARCHS="x86_64" -project out/uv.xcodeproj -configuration Release -alltargets
|
||||
$ cmake ../.. \
|
||||
-DCMAKE_SYSTEM_NAME=Windows \
|
||||
-DCMAKE_SYSTEM_VERSION=6.1 \
|
||||
-DCMAKE_C_COMPILER=i686-w64-mingw32-gcc
|
||||
```
|
||||
|
||||
Using Homebrew:
|
||||
### Install with Homebrew
|
||||
|
||||
```bash
|
||||
$ brew install --HEAD libuv
|
||||
@ -277,110 +220,48 @@ Make sure that you specify the architecture you wish to build for in the
|
||||
"ARCHS" flag. You can specify more than one by delimiting with a space
|
||||
(e.g. "x86_64 i386").
|
||||
|
||||
### Android
|
||||
|
||||
Run:
|
||||
|
||||
For arm
|
||||
|
||||
```bash
|
||||
$ source ./android-configure-arm NDK_PATH gyp [API_LEVEL]
|
||||
$ make -C out
|
||||
```
|
||||
|
||||
or for arm64
|
||||
|
||||
```bash
|
||||
$ source ./android-configure-arm64 NDK_PATH gyp [API_LEVEL]
|
||||
$ make -C out
|
||||
```
|
||||
|
||||
or for x86
|
||||
|
||||
```bash
|
||||
$ source ./android-configure-x86 NDK_PATH gyp [API_LEVEL]
|
||||
$ make -C out
|
||||
```
|
||||
|
||||
or for x86_64
|
||||
|
||||
```bash
|
||||
$ source ./android-configure-x86_64 NDK_PATH gyp [API_LEVEL]
|
||||
$ make -C out
|
||||
```
|
||||
|
||||
The default API level is 24, but a different one can be selected as follows:
|
||||
|
||||
```bash
|
||||
$ source ./android-configure-arm ~/android-ndk-r15b gyp 21
|
||||
$ make -C out
|
||||
```
|
||||
|
||||
Note for UNIX users: compile your project with `-D_LARGEFILE_SOURCE` and
|
||||
`-D_FILE_OFFSET_BITS=64`. GYP builds take care of that automatically.
|
||||
|
||||
### Using Ninja
|
||||
|
||||
To use ninja for build on ninja supported platforms, run:
|
||||
|
||||
```bash
|
||||
$ ./gyp_uv.py -f ninja
|
||||
$ ninja -C out/Debug #for debug build OR
|
||||
$ ninja -C out/Release
|
||||
```
|
||||
|
||||
|
||||
### Running tests
|
||||
|
||||
#### Build
|
||||
|
||||
Build (includes tests):
|
||||
|
||||
```bash
|
||||
$ ./gyp_uv.py -f make
|
||||
$ make -C out
|
||||
```
|
||||
|
||||
#### Run all tests
|
||||
|
||||
```bash
|
||||
$ ./out/Debug/run-tests
|
||||
```
|
||||
|
||||
Some tests are timing sensitive. Relaxing test timeouts may be necessary
|
||||
on slow or overloaded machines:
|
||||
|
||||
```bash
|
||||
$ env UV_TEST_TIMEOUT_MULTIPLIER=2 ./out/Debug/run-tests # 10s instead of 5s
|
||||
$ env UV_TEST_TIMEOUT_MULTIPLIER=2 build/uv_run_tests # 10s instead of 5s
|
||||
```
|
||||
|
||||
#### Run one test
|
||||
|
||||
The list of all tests is in `test/test-list.h`.
|
||||
|
||||
This invocation will cause the `run-tests` driver to fork and execute `TEST_NAME` in a child process:
|
||||
This invocation will cause the test driver to fork and execute `TEST_NAME` in
|
||||
a child process:
|
||||
|
||||
```bash
|
||||
$ ./out/Debug/run-tests TEST_NAME
|
||||
$ build/uv_run_tests_a TEST_NAME
|
||||
```
|
||||
|
||||
This invocation will cause the `run-tests` driver to execute the test within the `run-tests` process:
|
||||
This invocation will cause the test driver to execute the test in
|
||||
the same process:
|
||||
|
||||
```bash
|
||||
$ ./out/Debug/run-tests TEST_NAME TEST_NAME
|
||||
$ build/uv_run_tests_a TEST_NAME TEST_NAME
|
||||
```
|
||||
|
||||
#### Debugging tools
|
||||
|
||||
When running the test from within the `run-tests` process (`run-tests TEST_NAME TEST_NAME`), tools like gdb and valgrind work normally.
|
||||
When running the test from a child of the `run-tests` process (`run-tests TEST_NAME`), use these tools in a fork-aware manner.
|
||||
When running the test from within the test driver process
|
||||
(`build/uv_run_tests_a TEST_NAME TEST_NAME`), tools like gdb and valgrind
|
||||
work normally.
|
||||
|
||||
When running the test from a child of the test driver process
|
||||
(`build/uv_run_tests_a TEST_NAME`), use these tools in a fork-aware manner.
|
||||
|
||||
##### Fork-aware gdb
|
||||
|
||||
Use the [follow-fork-mode](https://sourceware.org/gdb/onlinedocs/gdb/Forks.html) setting:
|
||||
|
||||
```
|
||||
$ gdb --args out/Debug/run-tests TEST_NAME
|
||||
$ gdb --args build/uv_run_tests_a TEST_NAME
|
||||
|
||||
(gdb) set follow-fork-mode child
|
||||
...
|
||||
@ -391,18 +272,29 @@ $ gdb --args out/Debug/run-tests TEST_NAME
|
||||
Use the `--trace-children=yes` parameter:
|
||||
|
||||
```bash
|
||||
$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck-%p.log out/Debug/run-tests TEST_NAME
|
||||
$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck-%p.log build/uv_run_tests_a TEST_NAME
|
||||
```
|
||||
|
||||
### Running benchmarks
|
||||
|
||||
See the section on running tests.
|
||||
The benchmark driver is `out/Debug/run-benchmarks` and the benchmarks are listed in `test/benchmark-list.h`.
|
||||
The benchmark driver is `./uv_run_benchmarks_a` and the benchmarks are
|
||||
listed in `test/benchmark-list.h`.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
Check the [SUPPORTED_PLATFORMS file](SUPPORTED_PLATFORMS.md).
|
||||
|
||||
### `-fno-strict-aliasing`
|
||||
|
||||
It is recommended to turn on the `-fno-strict-aliasing` compiler flag in
|
||||
projects that use libuv. The use of ad hoc "inheritance" in the libuv API
|
||||
may not be safe in the presence of compiler optimizations that depend on
|
||||
strict aliasing.
|
||||
|
||||
MSVC does not have an equivalent flag but it also does not appear to need it
|
||||
at the time of writing (December 2019.)
|
||||
|
||||
### AIX Notes
|
||||
|
||||
AIX compilation using IBM XL C/C++ requires version 12.1 or greater.
|
||||
@ -413,10 +305,15 @@ that is detected by `autoconf`.
|
||||
[IBM documentation](http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/)
|
||||
describes the package in more detail.
|
||||
|
||||
AIX support for filesystem events is not compiled when building with `gyp`.
|
||||
|
||||
### z/OS Notes
|
||||
|
||||
z/OS compilation requires [ZOSLIB](https://github.com/ibmruntimes/zoslib) to be installed. When building with [CMake][], use the flag `-DZOSLIB_DIR` to specify the path to [ZOSLIB](https://github.com/ibmruntimes/zoslib):
|
||||
|
||||
```bash
|
||||
$ (cd build && cmake .. -DBUILD_TESTING=ON -DZOSLIB_DIR=/path/to/zoslib)
|
||||
$ cmake --build build
|
||||
```
|
||||
|
||||
z/OS creates System V semaphores and message queues. These persist on the system
|
||||
after the process terminates unless the event loop is closed.
|
||||
|
||||
@ -426,12 +323,10 @@ Use the `ipcrm` command to manually clear up System V resources.
|
||||
|
||||
See the [guidelines for contributing][].
|
||||
|
||||
[CMake]: https://cmake.org/
|
||||
[node.js]: http://nodejs.org/
|
||||
[GYP]: http://code.google.com/p/gyp/
|
||||
[guidelines for contributing]: https://github.com/libuv/libuv/blob/master/CONTRIBUTING.md
|
||||
[libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png
|
||||
[x32]: https://en.wikipedia.org/wiki/X32_ABI
|
||||
[Python 2.6 or 2.7]: https://www.python.org/downloads/
|
||||
[Visual C++ Build Tools]: https://visualstudio.microsoft.com/visual-cpp-build-tools/
|
||||
[Visual Studio 2015 Update 3]: https://www.visualstudio.com/vs/older-downloads/
|
||||
[Visual Studio 2017]: https://www.visualstudio.com/downloads/
|
||||
|
@ -3,15 +3,15 @@
|
||||
| System | Support type | Supported versions | Notes |
|
||||
|---|---|---|---|
|
||||
| GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | |
|
||||
| macOS | Tier 1 | macOS >= 10.7 | |
|
||||
| Windows | Tier 1 | >= Windows 7 | MSVC 2008 and later are supported |
|
||||
| macOS | Tier 1 | macOS >= 10.15 | Current and previous macOS release |
|
||||
| Windows | Tier 1 | >= Windows 8 | VS 2015 and later are supported |
|
||||
| FreeBSD | Tier 1 | >= 10 | |
|
||||
| AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix |
|
||||
| IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
|
||||
| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos |
|
||||
| Linux with musl | Tier 2 | musl >= 1.0 | |
|
||||
| SmartOS | Tier 2 | >= 14.4 | Maintainers: @libuv/smartos |
|
||||
| Android | Tier 3 | NDK >= r15b | |
|
||||
| IBM i | Tier 3 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
|
||||
| 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 | |
|
||||
| Other | Tier 3 | N/A | |
|
||||
@ -47,8 +47,9 @@ All functionality related to the new platform must be implemented in its own
|
||||
file inside ``src/unix/`` unless it's already done in a common file, in which
|
||||
case adding an `ifdef` is fine.
|
||||
|
||||
Two build systems are supported: autotools and GYP. Ideally both need to be
|
||||
supported, but if GYP does not support the new platform it can be left out.
|
||||
Two build systems are supported: autotools and cmake. Ideally both need to be
|
||||
supported, but if one of the two does not support the new platform it can be
|
||||
left out.
|
||||
|
||||
### Windows
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export TOOLCHAIN=$PWD/android-toolchain-arm
|
||||
mkdir -p $TOOLCHAIN
|
||||
API=${3:-24}
|
||||
$1/build/tools/make-standalone-toolchain.sh \
|
||||
--toolchain=arm-linux-androideabi-4.9 \
|
||||
--arch=arm \
|
||||
--install-dir=$TOOLCHAIN \
|
||||
--platform=android-$API \
|
||||
--force
|
||||
export PATH=$TOOLCHAIN/bin:$PATH
|
||||
export AR=arm-linux-androideabi-ar
|
||||
export CC=arm-linux-androideabi-gcc
|
||||
export CXX=arm-linux-androideabi-g++
|
||||
export LINK=arm-linux-androideabi-g++
|
||||
export PLATFORM=android
|
||||
export CFLAGS="-D__ANDROID_API__=$API"
|
||||
|
||||
if [[ $2 == 'gyp' ]]
|
||||
then
|
||||
./gyp_uv.py -Dtarget_arch=arm -DOS=android -f make-android
|
||||
fi
|
@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export TOOLCHAIN=$PWD/android-toolchain-arm64
|
||||
mkdir -p $TOOLCHAIN
|
||||
API=${3:-24}
|
||||
$1/build/tools/make-standalone-toolchain.sh \
|
||||
--toolchain=aarch64-linux-android-4.9 \
|
||||
--arch=arm64 \
|
||||
--install-dir=$TOOLCHAIN \
|
||||
--platform=android-$API \
|
||||
--force
|
||||
export PATH=$TOOLCHAIN/bin:$PATH
|
||||
export AR=aarch64-linux-android-ar
|
||||
export CC=aarch64-linux-android-gcc
|
||||
export CXX=aarch64-linux-android-g++
|
||||
export LINK=aarch64-linux-android-g++
|
||||
export PLATFORM=android
|
||||
export CFLAGS="-D__ANDROID_API__=$API"
|
||||
|
||||
if [[ $2 == 'gyp' ]]
|
||||
then
|
||||
./gyp_uv.py -Dtarget_arch=arm64 -DOS=android -f make-android
|
||||
fi
|
@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export TOOLCHAIN=$PWD/android-toolchain-x86
|
||||
mkdir -p $TOOLCHAIN
|
||||
API=${3:-24}
|
||||
$1/build/tools/make-standalone-toolchain.sh \
|
||||
--toolchain=x86-4.9 \
|
||||
--arch=x86 \
|
||||
--install-dir=$TOOLCHAIN \
|
||||
--platform=android-$API \
|
||||
--force
|
||||
export PATH=$TOOLCHAIN/bin:$PATH
|
||||
export AR=i686-linux-android-ar
|
||||
export CC=i686-linux-android-gcc
|
||||
export CXX=i686-linux-android-g++
|
||||
export LINK=i686-linux-android-g++
|
||||
export PLATFORM=android
|
||||
export CFLAGS="-D__ANDROID_API__=$API"
|
||||
|
||||
if [[ $2 == 'gyp' ]]
|
||||
then
|
||||
./gyp_uv.py -Dtarget_arch=x86 -DOS=android -f make-android
|
||||
fi
|
@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export TOOLCHAIN=$PWD/android-toolchain-x86_64
|
||||
mkdir -p $TOOLCHAIN
|
||||
API=${3:-24}
|
||||
$1/build/tools/make-standalone-toolchain.sh \
|
||||
--toolchain=x86_64-4.9 \
|
||||
--arch=x86_64 \
|
||||
--install-dir=$TOOLCHAIN \
|
||||
--platform=android-$API \
|
||||
--force
|
||||
export PATH=$TOOLCHAIN/bin:$PATH
|
||||
export AR=x86_64-linux-android-ar
|
||||
export CC=x86_64-linux-android-gcc
|
||||
export CXX=x86_64-linux-android-g++
|
||||
export LINK=x86_64-linux-android-g++
|
||||
export PLATFORM=android
|
||||
export CFLAGS="-D__ANDROID_API__=$API -fPIC"
|
||||
export CXXFLAGS="-D__ANDROID_API__=$API -fPIC"
|
||||
export LDFLAGS="-fPIC"
|
||||
|
||||
if [[ $2 == 'gyp' ]]
|
||||
then
|
||||
./gyp_uv.py -Dtarget_arch=x86_64 -DOS=android -f make-android
|
||||
fi
|
32
appveyor.yml
32
appveyor.yml
@ -1,32 +0,0 @@
|
||||
version: v1.18.0.build{build}
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf true
|
||||
|
||||
install:
|
||||
- cinst -y nsis
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- platform: x86
|
||||
configuration: Release
|
||||
- platform: x64
|
||||
configuration: Release
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
||||
build_script:
|
||||
# Fixed tag version number if using a tag.
|
||||
- cmd: if "%APPVEYOR_REPO_TAG%" == "true" set APPVEYOR_BUILD_VERSION=%APPVEYOR_REPO_TAG_NAME%
|
||||
# vcbuild overwrites the platform variable.
|
||||
- cmd: set ARCH=%platform%
|
||||
- cmd: vcbuild.bat release %ARCH% shared
|
||||
|
||||
cache:
|
||||
- C:\projects\libuv\build\gyp
|
213
common.gypi
213
common.gypi
@ -1,213 +0,0 @@
|
||||
{
|
||||
'variables': {
|
||||
'target_arch%': 'ia32', # set v8's target architecture
|
||||
'host_arch%': 'ia32', # set v8's host architecture
|
||||
'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds
|
||||
'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way
|
||||
},
|
||||
|
||||
'target_defaults': {
|
||||
'default_configuration': 'Debug',
|
||||
'configurations': {
|
||||
'Debug': {
|
||||
'defines': [ 'DEBUG', '_DEBUG' ],
|
||||
'cflags': [ '-g' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'target_conditions': [
|
||||
['uv_library=="static_library"', {
|
||||
'RuntimeLibrary': 1, # /MTd static debug
|
||||
}, {
|
||||
'RuntimeLibrary': 3, # /MDd DLL debug
|
||||
}],
|
||||
],
|
||||
'Optimization': 0, # /Od, no optimization
|
||||
'MinimalRebuild': 'false',
|
||||
'OmitFramePointers': 'false',
|
||||
'BasicRuntimeChecks': 3, # /RTC1
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'LinkIncremental': 2, # enable incremental linking
|
||||
},
|
||||
},
|
||||
'xcode_settings': {
|
||||
'GCC_OPTIMIZATION_LEVEL': '0',
|
||||
},
|
||||
'conditions': [
|
||||
['OS != "zos"', {
|
||||
'cflags': [ '-O0', '-fno-common', '-fwrapv' ]
|
||||
}],
|
||||
['OS == "android"', {
|
||||
'cflags': [ '-fPIE' ],
|
||||
'ldflags': [ '-fPIE', '-pie' ]
|
||||
}]
|
||||
]
|
||||
},
|
||||
'Release': {
|
||||
'defines': [ 'NDEBUG' ],
|
||||
'cflags': [
|
||||
'-O3',
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'target_conditions': [
|
||||
['uv_library=="static_library"', {
|
||||
'RuntimeLibrary': 0, # /MT static release
|
||||
}, {
|
||||
'RuntimeLibrary': 2, # /MD DLL release
|
||||
}],
|
||||
],
|
||||
'Optimization': 3, # /Ox, full optimization
|
||||
'FavorSizeOrSpeed': 1, # /Ot, favour speed over size
|
||||
'InlineFunctionExpansion': 2, # /Ob2, inline anything eligible
|
||||
'WholeProgramOptimization': 'true', # /GL, whole program optimization, needed for LTCG
|
||||
'OmitFramePointers': 'true',
|
||||
'EnableFunctionLevelLinking': 'true',
|
||||
'EnableIntrinsicFunctions': 'true',
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
'AdditionalOptions': [
|
||||
'/LTCG', # link time code generation
|
||||
],
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'LinkTimeCodeGeneration': 1, # link-time code generation
|
||||
'OptimizeReferences': 2, # /OPT:REF
|
||||
'EnableCOMDATFolding': 2, # /OPT:ICF
|
||||
'LinkIncremental': 1, # disable incremental linking
|
||||
},
|
||||
},
|
||||
'conditions': [
|
||||
['OS != "zos"', {
|
||||
'cflags': [
|
||||
'-fdata-sections',
|
||||
'-ffunction-sections',
|
||||
'-fno-common',
|
||||
'-fomit-frame-pointer',
|
||||
],
|
||||
}],
|
||||
]
|
||||
}
|
||||
},
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'StringPooling': 'true', # pool string literals
|
||||
'DebugInformationFormat': 3, # Generate a PDB
|
||||
'WarningLevel': 3,
|
||||
'BufferSecurityCheck': 'true',
|
||||
'ExceptionHandling': 1, # /EHsc
|
||||
'SuppressStartupBanner': 'true',
|
||||
'WarnAsError': 'false',
|
||||
'AdditionalOptions': [
|
||||
'/MP', # compile across multiple CPUs
|
||||
],
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'GenerateDebugInformation': 'true',
|
||||
'RandomizedBaseAddress': 2, # enable ASLR
|
||||
'DataExecutionPrevention': 2, # enable DEP
|
||||
'AllowIsolation': 'true',
|
||||
'SuppressStartupBanner': 'true',
|
||||
'target_conditions': [
|
||||
['_type=="executable"', {
|
||||
'SubSystem': 1, # console executable
|
||||
}],
|
||||
],
|
||||
},
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "win"', {
|
||||
'msvs_cygwin_shell': 0, # prevent actions from trying to use cygwin
|
||||
'defines': [
|
||||
'WIN32',
|
||||
# we don't really want VC++ warning us about
|
||||
# how dangerous C functions are...
|
||||
'_CRT_SECURE_NO_DEPRECATE',
|
||||
# ... or that C implementations shouldn't use
|
||||
# POSIX names
|
||||
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||
],
|
||||
'target_conditions': [
|
||||
['target_arch=="x64"', {
|
||||
'msvs_configuration_platform': 'x64'
|
||||
}]
|
||||
]
|
||||
}],
|
||||
['OS in "freebsd dragonflybsd linux openbsd solaris android aix"', {
|
||||
'cflags': [ '-Wall' ],
|
||||
'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ],
|
||||
'target_conditions': [
|
||||
['_type=="static_library"', {
|
||||
'standalone_static_library': 1, # disable thin archive which needs binutils >= 2.19
|
||||
}],
|
||||
],
|
||||
'conditions': [
|
||||
[ 'host_arch != target_arch and target_arch=="ia32"', {
|
||||
'cflags': [ '-m32' ],
|
||||
'ldflags': [ '-m32' ],
|
||||
}],
|
||||
[ 'target_arch=="x32"', {
|
||||
'cflags': [ '-mx32' ],
|
||||
'ldflags': [ '-mx32' ],
|
||||
}],
|
||||
[ 'OS=="linux"', {
|
||||
'cflags': [ '-ansi' ],
|
||||
}],
|
||||
[ 'OS=="solaris"', {
|
||||
'cflags': [ '-pthreads' ],
|
||||
'ldflags': [ '-pthreads' ],
|
||||
}],
|
||||
[ 'OS not in "solaris android zos"', {
|
||||
'cflags': [ '-pthread' ],
|
||||
'ldflags': [ '-pthread' ],
|
||||
}],
|
||||
[ 'OS=="aix" and target_arch=="ppc64"', {
|
||||
'cflags': [ '-maix64' ],
|
||||
'ldflags': [ '-maix64' ],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
'xcode_settings': {
|
||||
'ALWAYS_SEARCH_USER_PATHS': 'NO',
|
||||
'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks
|
||||
'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic
|
||||
# (Equivalent to -fPIC)
|
||||
'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions
|
||||
'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti
|
||||
'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings
|
||||
'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
|
||||
'PREBINDING': 'NO', # No -Wl,-prebind
|
||||
'USE_HEADERMAP': 'NO',
|
||||
'WARNING_CFLAGS': [
|
||||
'-Wall',
|
||||
'-Wendif-labels',
|
||||
'-W',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wstrict-prototypes',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
['target_arch=="ia32"', {
|
||||
'xcode_settings': {'ARCHS': ['i386']},
|
||||
}],
|
||||
['target_arch=="x64"', {
|
||||
'xcode_settings': {'ARCHS': ['x86_64']},
|
||||
}],
|
||||
],
|
||||
'target_conditions': [
|
||||
['_type!="static_library"', {
|
||||
'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
|
||||
}],
|
||||
],
|
||||
}],
|
||||
['OS=="solaris"', {
|
||||
'cflags': [ '-fno-omit-frame-pointer' ],
|
||||
# pull in V8's postmortem metadata
|
||||
'ldflags': [ '-Wl,-z,allextract' ]
|
||||
}],
|
||||
],
|
||||
},
|
||||
}
|
28
configure.ac
28
configure.ac
@ -13,7 +13,7 @@
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([libuv], [1.35.0], [https://github.com/libuv/libuv/issues])
|
||||
AC_INIT([libuv], [1.44.1], [https://github.com/libuv/libuv/issues])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
m4_include([m4/libuv-extra-automake-flags.m4])
|
||||
m4_include([m4/as_case.m4])
|
||||
@ -24,7 +24,11 @@ AC_ENABLE_SHARED
|
||||
AC_ENABLE_STATIC
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
CC_FLAG_VISIBILITY #[-fvisibility=hidden]
|
||||
|
||||
CC_ATTRIBUTE_VISIBILITY([default], [
|
||||
CC_FLAG_VISIBILITY([CFLAGS="${CFLAGS} -fvisibility=hidden"])
|
||||
])
|
||||
CC_CHECK_CFLAGS_APPEND([-fno-strict-aliasing])
|
||||
CC_CHECK_CFLAGS_APPEND([-g])
|
||||
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wall])
|
||||
@ -38,15 +42,17 @@ m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
AC_PROG_LIBTOOL
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
LT_INIT
|
||||
# TODO(bnoordhuis) Check for -pthread vs. -pthreads
|
||||
AC_CHECK_LIB([dl], [dlopen])
|
||||
AC_CHECK_LIB([kstat], [kstat_lookup])
|
||||
AC_CHECK_LIB([nsl], [gethostbyname])
|
||||
AC_CHECK_LIB([perfstat], [perfstat_cpu])
|
||||
AC_CHECK_LIB([pthread], [pthread_mutex_init])
|
||||
AC_CHECK_LIB([rt], [clock_gettime])
|
||||
AC_CHECK_LIB([sendfile], [sendfile])
|
||||
AC_CHECK_LIB([socket], [socket])
|
||||
AX_PTHREAD([
|
||||
LIBS="$LIBS $PTHREAD_LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
])
|
||||
AC_SEARCH_LIBS([dlopen], [dl])
|
||||
AC_SEARCH_LIBS([kstat_lookup], [kstat])
|
||||
AC_SEARCH_LIBS([gethostbyname], [nsl])
|
||||
AC_SEARCH_LIBS([perfstat_cpu], [perfstat])
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
AC_SEARCH_LIBS([sendfile], [sendfile])
|
||||
AC_SEARCH_LIBS([socket], [socket])
|
||||
AC_SYS_LARGEFILE
|
||||
AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])])
|
||||
AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])])
|
||||
|
3
docs/code/.gitignore
vendored
Normal file
3
docs/code/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*/*
|
||||
!*.c
|
||||
!*.h
|
12
docs/code/default-loop/main.c
Normal file
12
docs/code/default-loop/main.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <uv.h>
|
||||
|
||||
int main() {
|
||||
uv_loop_t *loop = uv_default_loop();
|
||||
|
||||
printf("Default loop.\n");
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
uv_loop_close(loop);
|
||||
return 0;
|
||||
}
|
@ -69,8 +69,8 @@ int main() {
|
||||
hints.ai_flags = 0;
|
||||
|
||||
uv_getaddrinfo_t resolver;
|
||||
fprintf(stderr, "irc.freenode.net is... ");
|
||||
int r = uv_getaddrinfo(loop, &resolver, on_resolved, "irc.freenode.net", "6667", &hints);
|
||||
fprintf(stderr, "irc.libera.chat is... ");
|
||||
int r = uv_getaddrinfo(loop, &resolver, on_resolved, "irc.libera.chat", "6667", &hints);
|
||||
|
||||
if (r) {
|
||||
fprintf(stderr, "getaddrinfo call error %s\n", uv_err_name(r));
|
||||
|
@ -70,7 +70,7 @@ void setup_workers() {
|
||||
|
||||
child_worker_count = cpu_count;
|
||||
|
||||
workers = calloc(sizeof(struct child_worker), cpu_count);
|
||||
workers = calloc(cpu_count, sizeof(struct child_worker));
|
||||
while (cpu_count--) {
|
||||
struct child_worker *worker = &workers[cpu_count];
|
||||
uv_pipe_init(loop, &worker->pipe, 1);
|
||||
|
42
docs/requirements.txt
Normal file
42
docs/requirements.txt
Normal file
@ -0,0 +1,42 @@
|
||||
# primary
|
||||
Sphinx==3.5.4
|
||||
|
||||
# dependencies
|
||||
alabaster==0.7.12
|
||||
appdirs==1.4.3
|
||||
Babel==2.9.0
|
||||
CacheControl==0.12.6
|
||||
certifi==2019.11.28
|
||||
chardet==3.0.4
|
||||
colorama==0.4.3
|
||||
contextlib2==0.6.0
|
||||
distlib==0.3.0
|
||||
distro==1.4.0
|
||||
docutils==0.16
|
||||
html5lib==1.0.1
|
||||
idna==2.8
|
||||
imagesize==1.2.0
|
||||
ipaddr==2.2.0
|
||||
Jinja2==2.11.3
|
||||
lockfile==0.12.2
|
||||
MarkupSafe==1.1.1
|
||||
msgpack==0.6.2
|
||||
packaging==20.3
|
||||
pep517==0.8.2
|
||||
progress==1.5
|
||||
Pygments==2.8.1
|
||||
pyparsing==2.4.6
|
||||
pytoml==0.1.21
|
||||
pytz==2021.1
|
||||
requests==2.22.0
|
||||
retrying==1.3.3
|
||||
six==1.14.0
|
||||
snowballstemmer==2.1.0
|
||||
sphinxcontrib-applehelp==1.0.2
|
||||
sphinxcontrib-devhelp==1.0.2
|
||||
sphinxcontrib-htmlhelp==1.0.3
|
||||
sphinxcontrib-jsmath==1.0.1
|
||||
sphinxcontrib-qthelp==1.0.3
|
||||
sphinxcontrib-serializinghtml==1.1.4
|
||||
urllib3==1.25.8
|
||||
webencodings==0.5.1
|
@ -32,4 +32,5 @@ API documentation
|
||||
dll
|
||||
threading
|
||||
misc
|
||||
metrics
|
||||
|
||||
|
@ -51,7 +51,7 @@ API
|
||||
loop thread.
|
||||
|
||||
.. note::
|
||||
:c:func:`uv_async_send` is `async-signal-safe <http://man7.org/linux/man-pages/man7/signal-safety.7.html>`_.
|
||||
:c:func:`uv_async_send` is `async-signal-safe <https://man7.org/linux/man-pages/man7/signal-safety.7.html>`_.
|
||||
It's safe to call this function from a signal handler.
|
||||
|
||||
.. warning::
|
||||
|
@ -33,14 +33,22 @@ API
|
||||
|
||||
.. c:function:: int uv_check_init(uv_loop_t* loop, uv_check_t* check)
|
||||
|
||||
Initialize the handle.
|
||||
Initialize the handle. This function always succeeds.
|
||||
|
||||
:returns: 0
|
||||
|
||||
.. c:function:: int uv_check_start(uv_check_t* check, uv_check_cb cb)
|
||||
|
||||
Start the handle with the given callback.
|
||||
Start the handle with the given callback. This function always succeeds,
|
||||
except when `cb` is `NULL`.
|
||||
|
||||
:returns: 0 on success, or `UV_EINVAL` when `cb == NULL`.
|
||||
|
||||
.. c:function:: int uv_check_stop(uv_check_t* check)
|
||||
|
||||
Stop the handle, the callback will no longer be called.
|
||||
This function always succeeds.
|
||||
|
||||
:returns: 0
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
|
@ -125,7 +125,7 @@ File I/O
|
||||
Unlike network I/O, there are no platform-specific file I/O primitives libuv could rely on,
|
||||
so the current approach is to run blocking file I/O operations in a thread pool.
|
||||
|
||||
For a thorough explanation of the cross-platform file I/O landscape, checkout
|
||||
For a thorough explanation of the cross-platform file I/O landscape, check out
|
||||
`this post <https://blog.libtorrent.org/2012/10/asynchronous-disk-io/>`_.
|
||||
|
||||
libuv currently uses a global thread pool on which all loops can queue work. 3 types of
|
||||
|
@ -251,6 +251,10 @@ Error constants
|
||||
|
||||
operation not supported on socket
|
||||
|
||||
.. c:macro:: UV_EOVERFLOW
|
||||
|
||||
value too large for defined data type
|
||||
|
||||
.. c:macro:: UV_EPERM
|
||||
|
||||
operation not permitted
|
||||
@ -319,11 +323,27 @@ Error constants
|
||||
|
||||
too many links
|
||||
|
||||
.. c:macro:: UV_ENOTTY
|
||||
|
||||
inappropriate ioctl for device
|
||||
|
||||
.. c:macro:: UV_EFTYPE
|
||||
|
||||
inappropriate file type or format
|
||||
|
||||
.. c:macro:: UV_EILSEQ
|
||||
|
||||
illegal byte sequence
|
||||
|
||||
.. c:macro:: UV_ESOCKTNOSUPPORT
|
||||
|
||||
socket type not supported
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: UV_ERRNO_MAP(iter_macro)
|
||||
.. c:macro:: UV_ERRNO_MAP(iter_macro)
|
||||
|
||||
Macro that expands to a series of invocations of `iter_macro` for
|
||||
each of the error constants above. `iter_macro` is invoked with two
|
||||
|
@ -58,7 +58,7 @@ Data types
|
||||
uv_timespec_t st_birthtim;
|
||||
} uv_stat_t;
|
||||
|
||||
.. c:type:: uv_fs_type
|
||||
.. c:enum:: uv_fs_type
|
||||
|
||||
File system request type.
|
||||
|
||||
@ -100,7 +100,8 @@ Data types
|
||||
UV_FS_OPENDIR,
|
||||
UV_FS_READDIR,
|
||||
UV_FS_CLOSEDIR,
|
||||
UV_FS_MKSTEMP
|
||||
UV_FS_MKSTEMP,
|
||||
UV_FS_LUTIME
|
||||
} uv_fs_type;
|
||||
|
||||
.. c:type:: uv_statfs_t
|
||||
@ -121,7 +122,7 @@ Data types
|
||||
uint64_t f_spare[4];
|
||||
} uv_statfs_t;
|
||||
|
||||
.. c:type:: uv_dirent_t
|
||||
.. c:enum:: uv_dirent_t
|
||||
|
||||
Cross platform (reduced) equivalent of ``struct dirent``.
|
||||
Used in :c:func:`uv_fs_scandir_next`.
|
||||
@ -402,12 +403,17 @@ API
|
||||
|
||||
.. c:function:: int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`utime(2)` and :man:`futimes(3)` respectively.
|
||||
Equivalent to :man:`utime(2)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively.
|
||||
|
||||
.. note::
|
||||
AIX: This function only works for AIX 7.1 and newer. It can still be called on older
|
||||
versions but will return ``UV_ENOSYS``.
|
||||
z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return
|
||||
``UV_ENOSYS``.
|
||||
|
||||
.. note::
|
||||
AIX: `uv_fs_futime()` and `uv_fs_lutime()` functions only work for AIX 7.1 and newer.
|
||||
They can still be called on older versions but will return ``UV_ENOSYS``.
|
||||
|
||||
.. versionchanged:: 1.10.0 sub-second precission is supported on Windows
|
||||
|
||||
@ -486,6 +492,13 @@ API
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: int uv_fs_get_system_error(const uv_fs_t* req)
|
||||
|
||||
Returns the platform specific error code - `GetLastError()` value on Windows
|
||||
and `-(req->result)` on other platforms.
|
||||
|
||||
.. versionadded:: 1.38.0
|
||||
|
||||
.. c:function:: void* uv_fs_get_ptr(const uv_fs_t* req)
|
||||
|
||||
Returns `req->ptr`.
|
||||
@ -522,8 +535,8 @@ Helper functions
|
||||
|
||||
For a OS-dependent handle, get the file descriptor in the C runtime.
|
||||
On UNIX, returns the ``os_fd`` intact. On Windows, this calls `_open_osfhandle <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/open-osfhandle?view=vs-2019>`_.
|
||||
Note that the return value is still owned by the CRT,
|
||||
any attempts to close it or to use it after closing the handle may lead to malfunction.
|
||||
Note that this consumes the argument, any attempts to close it or to use it
|
||||
after closing the return value may lead to malfunction.
|
||||
|
||||
.. versionadded:: 1.23.0
|
||||
|
||||
|
@ -42,7 +42,7 @@ as other activities and other I/O operations are kept waiting.
|
||||
|
||||
One of the standard solutions is to use threads. Each blocking I/O operation is
|
||||
started in a separate thread (or in a thread pool). When the blocking function
|
||||
gets invoked in the thread, the processor can schedule another thread to run,
|
||||
gets invoked in the thread, the operating system can schedule another thread to run,
|
||||
which actually needs the CPU.
|
||||
|
||||
The approach followed by libuv uses another style, which is the **asynchronous,
|
||||
@ -71,7 +71,7 @@ architecture of libuv and its background. If you have no prior experience with
|
||||
either libuv or libev, it is a quick, useful watch.
|
||||
|
||||
libuv's event loop is explained in more detail in the `documentation
|
||||
<http://docs.libuv.org/en/v1.x/design.html#the-i-o-loop>`_.
|
||||
<https://docs.libuv.org/en/v1.x/design.html#the-i-o-loop>`_.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@ -87,6 +87,7 @@ nothing, except start a loop which will exit immediately.
|
||||
|
||||
.. rubric:: helloworld/main.c
|
||||
.. literalinclude:: ../../code/helloworld/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
|
||||
This program quits immediately because it has no events to process. A libuv
|
||||
@ -108,6 +109,11 @@ A default loop is provided by libuv and can be accessed using
|
||||
``uv_default_loop()``. You should use this loop if you only want a single
|
||||
loop.
|
||||
|
||||
.. rubric:: default-loop/main.c
|
||||
.. literalinclude:: ../../code/default-loop/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
|
||||
.. note::
|
||||
|
||||
node.js uses the default loop as its main loop. If you are writing bindings
|
||||
@ -118,9 +124,9 @@ loop.
|
||||
Error handling
|
||||
--------------
|
||||
|
||||
Initialization functions or synchronous functions which may fail return a negative number on error. Async functions that may fail will pass a status parameter to their callbacks. The error messages are defined as ``UV_E*`` `constants`_.
|
||||
Initialization functions or synchronous functions which may fail return a negative number on error. Async functions that may fail will pass a status parameter to their callbacks. The error messages are defined as ``UV_E*`` `constants`_.
|
||||
|
||||
.. _constants: http://docs.libuv.org/en/v1.x/errors.html#error-constants
|
||||
.. _constants: https://docs.libuv.org/en/v1.x/errors.html#error-constants
|
||||
|
||||
You can use the ``uv_strerror(int)`` and ``uv_err_name(int)`` functions
|
||||
to get a ``const char *`` describing the error or the error name respectively.
|
||||
@ -133,7 +139,7 @@ Handles and Requests
|
||||
libuv works by the user expressing interest in particular events. This is
|
||||
usually done by creating a **handle** to an I/O device, timer or process.
|
||||
Handles are opaque structs named as ``uv_TYPE_t`` where type signifies what the
|
||||
handle is used for.
|
||||
handle is used for.
|
||||
|
||||
.. rubric:: libuv watchers
|
||||
.. code-block:: c
|
||||
@ -168,6 +174,16 @@ handle is used for.
|
||||
typedef struct uv_udp_send_s uv_udp_send_t;
|
||||
typedef struct uv_fs_s uv_fs_t;
|
||||
typedef struct uv_work_s uv_work_t;
|
||||
typedef struct uv_random_s uv_random_t;
|
||||
|
||||
/* None of the above. */
|
||||
typedef struct uv_env_item_s uv_env_item_t;
|
||||
typedef struct uv_cpu_info_s uv_cpu_info_t;
|
||||
typedef struct uv_interface_address_s uv_interface_address_t;
|
||||
typedef struct uv_dirent_s uv_dirent_t;
|
||||
typedef struct uv_passwd_s uv_passwd_t;
|
||||
typedef struct uv_utsname_s uv_utsname_t;
|
||||
typedef struct uv_statfs_s uv_statfs_t;
|
||||
|
||||
|
||||
Handles represent long-lived objects. Async operations on such handles are
|
||||
@ -202,6 +218,7 @@ event watchers are active.
|
||||
|
||||
.. rubric:: idle-basic/main.c
|
||||
.. literalinclude:: ../../code/idle-basic/main.c
|
||||
:language: c
|
||||
:emphasize-lines: 6,10,14-17
|
||||
|
||||
Storing context
|
||||
|
@ -20,6 +20,7 @@ these things can be a bit difficult to understand, so let's look at
|
||||
|
||||
.. rubric:: src/unix/core.c - uv_run
|
||||
.. literalinclude:: ../../../src/unix/core.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 304-324
|
||||
:emphasize-lines: 10,19,21
|
||||
@ -43,6 +44,7 @@ iteration of the loop still takes places.
|
||||
|
||||
.. rubric:: uvstop/main.c
|
||||
.. literalinclude:: ../../code/uvstop/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:emphasize-lines: 11
|
||||
|
||||
|
@ -13,7 +13,7 @@ Simple filesystem read/write is achieved using the ``uv_fs_*`` functions and the
|
||||
watchers registered with the event loop when application interaction is
|
||||
required.
|
||||
|
||||
.. _thread pool: http://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling
|
||||
.. _thread pool: https://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling
|
||||
|
||||
All filesystem functions have two forms - *synchronous* and *asynchronous*.
|
||||
|
||||
@ -33,7 +33,7 @@ A file descriptor is obtained using
|
||||
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb)
|
||||
|
||||
``flags`` and ``mode`` are standard
|
||||
`Unix flags <http://man7.org/linux/man-pages/man2/open.2.html>`_.
|
||||
`Unix flags <https://man7.org/linux/man-pages/man2/open.2.html>`_.
|
||||
libuv takes care of converting to the appropriate Windows flags.
|
||||
|
||||
File descriptors are closed using
|
||||
@ -54,6 +54,7 @@ a callback for when the file is opened:
|
||||
|
||||
.. rubric:: uvcat/main.c - opening a file
|
||||
.. literalinclude:: ../../code/uvcat/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 41-53
|
||||
:emphasize-lines: 4, 6-7
|
||||
@ -63,8 +64,9 @@ The ``result`` field of a ``uv_fs_t`` is the file descriptor in case of the
|
||||
|
||||
.. rubric:: uvcat/main.c - read callback
|
||||
.. literalinclude:: ../../code/uvcat/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 26-40
|
||||
:lines: 26-39
|
||||
:emphasize-lines: 2,8,12
|
||||
|
||||
In the case of a read call, you should pass an *initialized* buffer which will
|
||||
@ -87,8 +89,9 @@ callbacks.
|
||||
|
||||
.. rubric:: uvcat/main.c - write callback
|
||||
.. literalinclude:: ../../code/uvcat/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 16-24
|
||||
:lines: 17-24
|
||||
:emphasize-lines: 6
|
||||
|
||||
.. warning::
|
||||
@ -100,6 +103,7 @@ We set the dominos rolling in ``main()``:
|
||||
|
||||
.. rubric:: uvcat/main.c
|
||||
.. literalinclude:: ../../code/uvcat/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 55-
|
||||
:emphasize-lines: 2
|
||||
@ -128,6 +132,7 @@ same patterns as the read/write/open calls, returning the result in the
|
||||
int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
|
||||
int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
|
||||
int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
|
||||
int uv_fs_mkstemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
|
||||
int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb);
|
||||
int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent);
|
||||
@ -145,6 +150,7 @@ same patterns as the read/write/open calls, returning the result in the
|
||||
int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
|
||||
int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
|
||||
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb);
|
||||
int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
|
||||
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
|
||||
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
|
||||
@ -154,6 +160,7 @@ same patterns as the read/write/open calls, returning the result in the
|
||||
int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
|
||||
int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
|
||||
int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
|
||||
int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
|
||||
|
||||
.. _buffers-and-streams:
|
||||
@ -186,7 +193,7 @@ and freed by the application.
|
||||
|
||||
.. ERROR::
|
||||
|
||||
THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER**
|
||||
**THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER**
|
||||
|
||||
To demonstrate streams we will need to use ``uv_pipe_t``. This allows streaming
|
||||
local files [#]_. Here is a simple tee utility using libuv. Doing all operations
|
||||
@ -203,8 +210,9 @@ opened as bidirectional by default.
|
||||
|
||||
.. rubric:: uvtee/main.c - read on pipes
|
||||
.. literalinclude:: ../../code/uvtee/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 61-80
|
||||
:lines: 62-80
|
||||
:emphasize-lines: 4,5,15
|
||||
|
||||
The third argument of ``uv_pipe_init()`` should be set to 1 for IPC using named
|
||||
@ -218,6 +226,7 @@ these buffers.
|
||||
|
||||
.. rubric:: uvtee/main.c - reading buffers
|
||||
.. literalinclude:: ../../code/uvtee/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 19-22,44-60
|
||||
|
||||
@ -242,6 +251,7 @@ point there is nothing to be read. Most applications will just ignore this.
|
||||
|
||||
.. rubric:: uvtee/main.c - Write to pipe
|
||||
.. literalinclude:: ../../code/uvtee/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 9-13,23-42
|
||||
|
||||
@ -278,10 +288,18 @@ a command whenever any of the watched files change::
|
||||
|
||||
./onchange <command> <file1> [file2] ...
|
||||
|
||||
.. note::
|
||||
|
||||
Currently this example only works on OSX and Windows.
|
||||
Refer to the `notes of uv_fs_event_start`_ function.
|
||||
|
||||
.. _notes of uv_fs_event_start: https://docs.libuv.org/en/v1.x/fs_event.html#c.uv_fs_event_start
|
||||
|
||||
The file change notification is started using ``uv_fs_event_init()``:
|
||||
|
||||
.. rubric:: onchange/main.c - The setup
|
||||
.. literalinclude:: ../../code/onchange/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 26-
|
||||
:emphasize-lines: 15
|
||||
@ -292,8 +310,8 @@ argument, ``flags``, can be:
|
||||
.. code-block:: c
|
||||
|
||||
/*
|
||||
* Flags to be passed to uv_fs_event_start().
|
||||
*/
|
||||
* Flags to be passed to uv_fs_event_start().
|
||||
*/
|
||||
enum uv_fs_event_flags {
|
||||
UV_FS_EVENT_WATCH_ENTRY = 1,
|
||||
UV_FS_EVENT_STAT = 2,
|
||||
@ -311,15 +329,16 @@ The callback will receive the following arguments:
|
||||
#. ``const char *filename`` - If a directory is being monitored, this is the
|
||||
file which was changed. Only non-``null`` on Linux and Windows. May be ``null``
|
||||
even on those platforms.
|
||||
#. ``int flags`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of
|
||||
both.
|
||||
#. ``int status`` - Currently 0.
|
||||
#. ``int events`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of
|
||||
both.
|
||||
#. ``int status`` - If ``status < 0``, there is an :ref:`libuv error<libuv-error-handling>`.
|
||||
|
||||
In our example we simply print the arguments and run the command using
|
||||
``system()``.
|
||||
|
||||
.. rubric:: onchange/main.c - file change notification callback
|
||||
.. literalinclude:: ../../code/onchange/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 9-24
|
||||
|
||||
|
@ -8,7 +8,7 @@ It is meant to cover the main areas of libuv, but is not a comprehensive
|
||||
reference discussing every function and data structure. The `official libuv
|
||||
documentation`_ may be consulted for full details.
|
||||
|
||||
.. _official libuv documentation: http://docs.libuv.org/en/v1.x/
|
||||
.. _official libuv documentation: https://docs.libuv.org/en/v1.x/
|
||||
|
||||
This book is still a work in progress, so sections may be incomplete, but
|
||||
I hope you will enjoy it as it grows.
|
||||
@ -47,29 +47,27 @@ Since then libuv has continued to mature and become a high quality standalone
|
||||
library for system programming. Users outside of node.js include Mozilla's
|
||||
Rust_ programming language, and a variety_ of language bindings.
|
||||
|
||||
This book and the code is based on libuv version `v1.3.0`_.
|
||||
This book and the code is based on libuv version `v1.42.0`_.
|
||||
|
||||
Code
|
||||
----
|
||||
|
||||
All the code from this book is included as part of the source of the book on
|
||||
Github. `Clone`_/`Download`_ the book, then build libuv::
|
||||
All the example code and the source of the book is included as part of
|
||||
the libuv_ project on Github.
|
||||
Clone or Download libuv_, then build it::
|
||||
|
||||
cd libuv
|
||||
./autogen.sh
|
||||
sh autogen.sh
|
||||
./configure
|
||||
make
|
||||
|
||||
There is no need to ``make install``. To build the examples run ``make`` in the
|
||||
``code/`` directory.
|
||||
``docs/code/`` directory.
|
||||
|
||||
.. _Clone: https://github.com/nikhilm/uvbook
|
||||
.. _Download: https://github.com/nikhilm/uvbook/downloads
|
||||
.. _v1.3.0: https://github.com/libuv/libuv/tags
|
||||
.. _v1.42.0: https://github.com/libuv/libuv/releases/tag/v1.42.0
|
||||
.. _V8: https://v8.dev
|
||||
.. _libev: http://software.schmorp.de/pkg/libev.html
|
||||
.. _libuv: https://github.com/libuv/libuv
|
||||
.. _node.js: https://www.nodejs.org
|
||||
.. _libev was removed: https://github.com/joyent/libuv/issues/485
|
||||
.. _Rust: https://www.rust-lang.org
|
||||
.. _variety: https://github.com/libuv/libuv/wiki/Projects-that-use-libuv
|
||||
.. _variety: https://github.com/libuv/libuv/blob/v1.x/LINKS.md
|
||||
|
@ -38,6 +38,7 @@ Here is a simple echo server
|
||||
|
||||
.. rubric:: tcp-echo-server/main.c - The listen socket
|
||||
.. literalinclude:: ../../code/tcp-echo-server/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 68-
|
||||
:emphasize-lines: 4-5,7-10
|
||||
@ -60,6 +61,7 @@ In this case we also establish interest in reading from this stream.
|
||||
|
||||
.. rubric:: tcp-echo-server/main.c - Accepting the client
|
||||
.. literalinclude:: ../../code/tcp-echo-server/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 51-66
|
||||
:emphasize-lines: 9-10
|
||||
@ -108,6 +110,7 @@ address from a `DHCP`_ server -- DHCP Discover.
|
||||
|
||||
.. rubric:: udp-dhcp/main.c - Setup and send UDP packets
|
||||
.. literalinclude:: ../../code/udp-dhcp/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 7-11,104-
|
||||
:emphasize-lines: 8,10-11,17-18,21
|
||||
@ -143,6 +146,7 @@ the OS will discard the data that could not fit* (That's UDP for you!).
|
||||
|
||||
.. rubric:: udp-dhcp/main.c - Reading packets
|
||||
.. literalinclude:: ../../code/udp-dhcp/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 17-40
|
||||
:emphasize-lines: 1,23
|
||||
@ -189,10 +193,11 @@ Querying DNS
|
||||
libuv provides asynchronous DNS resolution. For this it provides its own
|
||||
``getaddrinfo`` replacement [#]_. In the callback you can
|
||||
perform normal socket operations on the retrieved addresses. Let's connect to
|
||||
Freenode to see an example of DNS resolution.
|
||||
Libera.chat to see an example of DNS resolution.
|
||||
|
||||
.. rubric:: dns/main.c
|
||||
.. literalinclude:: ../../code/dns/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 61-
|
||||
:emphasize-lines: 12
|
||||
@ -200,7 +205,7 @@ Freenode to see an example of DNS resolution.
|
||||
If ``uv_getaddrinfo`` returns non-zero, something went wrong in the setup and
|
||||
your callback won't be invoked at all. All arguments can be freed immediately
|
||||
after ``uv_getaddrinfo`` returns. The `hostname`, `servname` and `hints`
|
||||
structures are documented in `the getaddrinfo man page <getaddrinfo>`_. The
|
||||
structures are documented in `the getaddrinfo man page <getaddrinfo_>`_. The
|
||||
callback can be ``NULL`` in which case the function will run synchronously.
|
||||
|
||||
In the resolver callback, you can pick any IP from the linked list of ``struct
|
||||
@ -209,6 +214,7 @@ call ``uv_freeaddrinfo`` in the callback.
|
||||
|
||||
.. rubric:: dns/main.c
|
||||
.. literalinclude:: ../../code/dns/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 42-60
|
||||
:emphasize-lines: 8,16
|
||||
@ -227,6 +233,7 @@ useful to allow your service to bind to IP addresses when it starts.
|
||||
|
||||
.. rubric:: interfaces/main.c
|
||||
.. literalinclude:: ../../code/interfaces/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:emphasize-lines: 9,17
|
||||
|
||||
@ -235,7 +242,7 @@ interface has multiple IPv4/IPv6 addresses, the name will be reported multiple
|
||||
times, with each address being reported once.
|
||||
|
||||
.. _c-ares: https://c-ares.haxx.se
|
||||
.. _getaddrinfo: https://www.kernel.org/doc/man-pages/online/pages/man3/getaddrinfo.3.html
|
||||
.. _getaddrinfo: https://man7.org/linux/man-pages/man3/getaddrinfo.3.html
|
||||
|
||||
.. _User Datagram Protocol: https://en.wikipedia.org/wiki/User_Datagram_Protocol
|
||||
.. _DHCP: https://tools.ietf.org/html/rfc2131
|
||||
|
@ -27,6 +27,7 @@ exits. This is achieved using ``uv_spawn``.
|
||||
|
||||
.. rubric:: spawn/main.c
|
||||
.. literalinclude:: ../../code/spawn/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 6-8,15-
|
||||
:emphasize-lines: 11,13-17
|
||||
@ -54,6 +55,7 @@ which caused the exit.
|
||||
|
||||
.. rubric:: spawn/main.c
|
||||
.. literalinclude:: ../../code/spawn/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 9-12
|
||||
:emphasize-lines: 3
|
||||
@ -104,6 +106,7 @@ does not affect it.
|
||||
|
||||
.. rubric:: detach/main.c
|
||||
.. literalinclude:: ../../code/detach/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 9-30
|
||||
:emphasize-lines: 12,19
|
||||
@ -140,6 +143,7 @@ stop watching. Here is a small example demonstrating the various possibilities:
|
||||
|
||||
.. rubric:: signal/main.c
|
||||
.. literalinclude:: ../../code/signal/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:emphasize-lines: 17-18,27-28
|
||||
|
||||
@ -172,6 +176,7 @@ which is:
|
||||
|
||||
.. rubric:: proc-streams/test.c
|
||||
.. literalinclude:: ../../code/proc-streams/test.c
|
||||
:language: c
|
||||
|
||||
The actual program ``proc-streams`` runs this while sharing only ``stderr``.
|
||||
The file descriptors of the child process are set using the ``stdio`` field in
|
||||
@ -199,6 +204,7 @@ Then we set the ``fd`` to ``stderr``.
|
||||
|
||||
.. rubric:: proc-streams/main.c
|
||||
.. literalinclude:: ../../code/proc-streams/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 15-17,27-
|
||||
:emphasize-lines: 6,10,11,12
|
||||
@ -217,12 +223,14 @@ A sample CGI script/executable is:
|
||||
|
||||
.. rubric:: cgi/tick.c
|
||||
.. literalinclude:: ../../code/cgi/tick.c
|
||||
:language: c
|
||||
|
||||
The CGI server combines the concepts from this chapter and :doc:`networking` so
|
||||
that every client is sent ten ticks after which that connection is closed.
|
||||
|
||||
.. rubric:: cgi/main.c
|
||||
.. literalinclude:: ../../code/cgi/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 49-63
|
||||
:emphasize-lines: 10
|
||||
@ -232,6 +240,7 @@ Here we simply accept the TCP connection and pass on the socket (*stream*) to
|
||||
|
||||
.. rubric:: cgi/main.c
|
||||
.. literalinclude:: ../../code/cgi/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 16, 25-45
|
||||
:emphasize-lines: 8-9,18,20
|
||||
@ -266,10 +275,10 @@ Domain Socket`_, or derived from `mkfifo(1)`_, or it could actually be a
|
||||
This is intended for the purpose of allowing multiple libuv processes to
|
||||
communicate with IPC. This is discussed below.
|
||||
|
||||
.. _pipe(7): http://man7.org/linux/man-pages/man7/pipe.7.html
|
||||
.. _mkfifo(1): http://man7.org/linux/man-pages/man1/mkfifo.1.html
|
||||
.. _socketpair(2): http://man7.org/linux/man-pages/man2/socketpair.2.html
|
||||
.. _Unix Domain Socket: http://man7.org/linux/man-pages/man7/unix.7.html
|
||||
.. _pipe(7): https://man7.org/linux/man-pages/man7/pipe.7.html
|
||||
.. _mkfifo(1): https://man7.org/linux/man-pages/man1/mkfifo.1.html
|
||||
.. _socketpair(2): https://man7.org/linux/man-pages/man2/socketpair.2.html
|
||||
.. _Unix Domain Socket: https://man7.org/linux/man-pages/man7/unix.7.html
|
||||
.. _Named Pipe: https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipes
|
||||
|
||||
|
||||
@ -291,6 +300,7 @@ messaging is no different from TCP, so we'll re-use the echo server example.
|
||||
|
||||
.. rubric:: pipe-echo-server/main.c
|
||||
.. literalinclude:: ../../code/pipe-echo-server/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 70-
|
||||
:emphasize-lines: 5,10,14
|
||||
@ -330,6 +340,7 @@ it by the master.
|
||||
|
||||
.. rubric:: multi-echo-server/worker.c
|
||||
.. literalinclude:: ../../code/multi-echo-server/worker.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 7-9,81-
|
||||
:emphasize-lines: 6-8
|
||||
@ -343,6 +354,7 @@ standard input of the worker, we connect the pipe to ``stdin`` using
|
||||
|
||||
.. rubric:: multi-echo-server/worker.c
|
||||
.. literalinclude:: ../../code/multi-echo-server/worker.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 51-79
|
||||
:emphasize-lines: 10,15,20
|
||||
@ -361,6 +373,7 @@ allow load balancing.
|
||||
|
||||
.. rubric:: multi-echo-server/main.c
|
||||
.. literalinclude:: ../../code/multi-echo-server/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 9-13
|
||||
|
||||
@ -369,6 +382,7 @@ master and the individual process.
|
||||
|
||||
.. rubric:: multi-echo-server/main.c
|
||||
.. literalinclude:: ../../code/multi-echo-server/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 51,61-95
|
||||
:emphasize-lines: 17,20-21
|
||||
@ -387,6 +401,7 @@ worker in the round-robin.
|
||||
|
||||
.. rubric:: multi-echo-server/main.c
|
||||
.. literalinclude:: ../../code/multi-echo-server/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 31-49
|
||||
:emphasize-lines: 9,12-13
|
||||
|
@ -39,6 +39,7 @@ wait for it to close using ``uv_thread_join()``.
|
||||
|
||||
.. rubric:: thread-create/main.c
|
||||
.. literalinclude:: ../../code/thread-create/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 26-36
|
||||
:emphasize-lines: 3-7
|
||||
@ -55,6 +56,7 @@ thread, scheduled pre-emptively by the operating system:
|
||||
|
||||
.. rubric:: thread-create/main.c
|
||||
.. literalinclude:: ../../code/thread-create/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 6-14
|
||||
:emphasize-lines: 2
|
||||
@ -124,6 +126,7 @@ example.
|
||||
|
||||
.. rubric:: locks/main.c - simple rwlocks
|
||||
.. literalinclude:: ../../code/locks/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:emphasize-lines: 13,16,27,31,42,55
|
||||
|
||||
@ -208,6 +211,7 @@ event loop from performing other activities.
|
||||
|
||||
.. rubric:: queue-work/main.c - lazy fibonacci
|
||||
.. literalinclude:: ../../code/queue-work/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 17-29
|
||||
|
||||
@ -221,6 +225,7 @@ The trigger is ``uv_queue_work``:
|
||||
|
||||
.. rubric:: queue-work/main.c
|
||||
.. literalinclude:: ../../code/queue-work/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 31-44
|
||||
:emphasize-lines: 10
|
||||
@ -248,6 +253,7 @@ up a signal handler for termination.
|
||||
|
||||
.. rubric:: queue-cancel/main.c
|
||||
.. literalinclude:: ../../code/queue-cancel/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 43-
|
||||
|
||||
@ -256,6 +262,7 @@ When the user triggers the signal by pressing ``Ctrl+C`` we send
|
||||
|
||||
.. rubric:: queue-cancel/main.c
|
||||
.. literalinclude:: ../../code/queue-cancel/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 33-41
|
||||
:emphasize-lines: 6
|
||||
@ -265,6 +272,7 @@ with ``status`` set to ``UV_ECANCELED``.
|
||||
|
||||
.. rubric:: queue-cancel/main.c
|
||||
.. literalinclude:: ../../code/queue-cancel/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 28-31
|
||||
:emphasize-lines: 2
|
||||
@ -292,8 +300,9 @@ informing the user of the status of running downloads.
|
||||
|
||||
.. rubric:: progress/main.c
|
||||
.. literalinclude:: ../../code/progress/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 7-8,34-
|
||||
:lines: 7-8,35-
|
||||
:emphasize-lines: 2,11
|
||||
|
||||
The async thread communication works *on loops* so although any thread can be
|
||||
@ -317,8 +326,9 @@ with the async watcher whenever it receives a message.
|
||||
|
||||
.. rubric:: progress/main.c
|
||||
.. literalinclude:: ../../code/progress/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 10-23
|
||||
:lines: 10-24
|
||||
:emphasize-lines: 7-8
|
||||
|
||||
In the download function, we modify the progress indicator and queue the message
|
||||
@ -327,8 +337,9 @@ non-blocking and will return immediately.
|
||||
|
||||
.. rubric:: progress/main.c
|
||||
.. literalinclude:: ../../code/progress/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 30-33
|
||||
:lines: 31-34
|
||||
|
||||
The callback is a standard libuv pattern, extracting the data from the watcher.
|
||||
|
||||
@ -336,8 +347,9 @@ Finally it is important to remember to clean up the watcher.
|
||||
|
||||
.. rubric:: progress/main.c
|
||||
.. literalinclude:: ../../code/progress/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 25-28
|
||||
:lines: 26-29
|
||||
:emphasize-lines: 3
|
||||
|
||||
After this example, which showed the abuse of the ``data`` field, bnoordhuis_
|
||||
|
@ -87,6 +87,7 @@ JS object and can be ref/unrefed.
|
||||
|
||||
.. rubric:: ref-timer/main.c
|
||||
.. literalinclude:: ../../code/ref-timer/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 5-8, 17-
|
||||
:emphasize-lines: 9
|
||||
@ -111,6 +112,7 @@ idle watcher to keep the UI operational.
|
||||
|
||||
.. rubric:: idle-compute/main.c
|
||||
.. literalinclude:: ../../code/idle-compute/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 5-9, 34-
|
||||
:emphasize-lines: 13
|
||||
@ -123,6 +125,7 @@ keep calling the idle callback again.
|
||||
|
||||
.. rubric:: idle-compute/main.c
|
||||
.. literalinclude:: ../../code/idle-compute/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 10-19
|
||||
|
||||
@ -215,6 +218,7 @@ progress with the download whenever libuv notifies of I/O readiness.
|
||||
|
||||
.. rubric:: uvwget/main.c - The setup
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 1-9,140-
|
||||
:emphasize-lines: 7,21,24-25
|
||||
@ -235,6 +239,7 @@ So we add each argument as an URL
|
||||
|
||||
.. rubric:: uvwget/main.c - Adding urls
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 39-56
|
||||
:emphasize-lines: 13-14
|
||||
@ -243,7 +248,7 @@ We let libcurl directly write the data to a file, but much more is possible if
|
||||
you so desire.
|
||||
|
||||
``start_timeout`` will be called immediately the first time by libcurl, so
|
||||
things are set in motion. This simply starts a libuv `timer <Timers>`_ which
|
||||
things are set in motion. This simply starts a libuv `timer <#timers>`_ which
|
||||
drives ``curl_multi_socket_action`` with ``CURL_SOCKET_TIMEOUT`` whenever it
|
||||
times out. ``curl_multi_socket_action`` is what drives libcurl, and what we
|
||||
call whenever sockets change state. But before we go into that, we need to poll
|
||||
@ -251,6 +256,7 @@ on sockets whenever ``handle_socket`` is called.
|
||||
|
||||
.. rubric:: uvwget/main.c - Setting up polling
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 102-140
|
||||
:emphasize-lines: 9,11,15,21,24
|
||||
@ -271,6 +277,7 @@ mask with the new value. ``curl_perform`` is the crux of this program.
|
||||
|
||||
.. rubric:: uvwget/main.c - Driving libcurl.
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 81-95
|
||||
:emphasize-lines: 2,6-7,12
|
||||
@ -288,6 +295,7 @@ transfers are done.
|
||||
|
||||
.. rubric:: uvwget/main.c - Reading transfer status.
|
||||
.. literalinclude:: ../../code/uvwget/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 58-79
|
||||
:emphasize-lines: 6,9-10,13-14
|
||||
@ -312,6 +320,7 @@ Let us first look at the interface provided to plugin authors.
|
||||
|
||||
.. rubric:: plugin/plugin.h
|
||||
.. literalinclude:: ../../code/plugin/plugin.h
|
||||
:language: c
|
||||
:linenos:
|
||||
|
||||
You can similarly add more functions that plugin authors can use to do useful
|
||||
@ -319,6 +328,7 @@ things in your application [#]_. A sample plugin using this API is:
|
||||
|
||||
.. rubric:: plugin/hello.c
|
||||
.. literalinclude:: ../../code/plugin/hello.c
|
||||
:language: c
|
||||
:linenos:
|
||||
|
||||
Our interface defines that all plugins should have an ``initialize`` function
|
||||
@ -340,6 +350,7 @@ This is done by using ``uv_dlopen`` to first load the shared library
|
||||
|
||||
.. rubric:: plugin/main.c
|
||||
.. literalinclude:: ../../code/plugin/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 7-
|
||||
:emphasize-lines: 15, 18, 24
|
||||
@ -393,6 +404,7 @@ Here is a simple example which prints white text on a red background:
|
||||
|
||||
.. rubric:: tty/main.c
|
||||
.. literalinclude:: ../../code/tty/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:emphasize-lines: 11-12,14,17,27
|
||||
|
||||
@ -403,6 +415,7 @@ escape codes.
|
||||
|
||||
.. rubric:: tty-gravity/main.c
|
||||
.. literalinclude:: ../../code/tty-gravity/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:emphasize-lines: 19,25,38
|
||||
|
||||
|
@ -20,7 +20,7 @@ Data types
|
||||
|
||||
The base libuv handle type.
|
||||
|
||||
.. c:type:: uv_handle_type
|
||||
.. c:enum:: uv_handle_type
|
||||
|
||||
The kind of the libuv handle.
|
||||
|
||||
@ -104,7 +104,7 @@ Public members
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: UV_HANDLE_TYPE_MAP(iter_macro)
|
||||
.. c:macro:: UV_HANDLE_TYPE_MAP(iter_macro)
|
||||
|
||||
Macro that expands to a series of invocations of `iter_macro` for
|
||||
each of the handle types. `iter_macro` is invoked with two
|
||||
|
@ -41,14 +41,22 @@ API
|
||||
|
||||
.. c:function:: int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle)
|
||||
|
||||
Initialize the handle.
|
||||
Initialize the handle. This function always succeeds.
|
||||
|
||||
:returns: 0
|
||||
|
||||
.. c:function:: int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb)
|
||||
|
||||
Start the handle with the given callback.
|
||||
Start the handle with the given callback. This function always succeeds,
|
||||
except when `cb` is `NULL`.
|
||||
|
||||
:returns: 0 on success, or `UV_EINVAL` when `cb == NULL`.
|
||||
|
||||
.. c:function:: int uv_idle_stop(uv_idle_t* idle)
|
||||
|
||||
Stop the handle, the callback will no longer be called.
|
||||
This function always succeeds.
|
||||
|
||||
:returns: 0
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
|
@ -7,7 +7,7 @@ Overview
|
||||
|
||||
libuv is a multi-platform support library with a focus on asynchronous I/O. It
|
||||
was primarily developed for use by `Node.js`_, but it's also used by `Luvit`_,
|
||||
`Julia`_, `pyuv`_, and `others`_.
|
||||
`Julia`_, `uvloop`_, and `others`_.
|
||||
|
||||
.. note::
|
||||
In case you find errors in this documentation you can help by sending
|
||||
@ -16,8 +16,8 @@ was primarily developed for use by `Node.js`_, but it's also used by `Luvit`_,
|
||||
.. _Node.js: https://nodejs.org
|
||||
.. _Luvit: https://luvit.io
|
||||
.. _Julia: https://julialang.org
|
||||
.. _pyuv: https://github.com/saghul/pyuv
|
||||
.. _others: https://github.com/libuv/libuv/wiki/Projects-that-use-libuv
|
||||
.. _uvloop: https://github.com/MagicStack/uvloop
|
||||
.. _others: https://github.com/libuv/libuv/blob/v1.x/LINKS.md
|
||||
|
||||
|
||||
Features
|
||||
|
@ -16,7 +16,7 @@ Data types
|
||||
|
||||
Loop data type.
|
||||
|
||||
.. c:type:: uv_run_mode
|
||||
.. c:enum:: uv_run_mode
|
||||
|
||||
Mode used to run the loop with :c:func:`uv_run`.
|
||||
|
||||
@ -68,6 +68,13 @@ API
|
||||
to suppress unnecessary wakeups when using a sampling profiler.
|
||||
Requesting other signals will fail with UV_EINVAL.
|
||||
|
||||
- UV_METRICS_IDLE_TIME: Accumulate the amount of idle time the event loop
|
||||
spends in the event provider.
|
||||
|
||||
This option is necessary to use :c:func:`uv_metrics_idle_time`.
|
||||
|
||||
.. versionchanged:: 1.39.0 added the UV_METRICS_IDLE_TIME option.
|
||||
|
||||
.. c:function:: int uv_loop_close(uv_loop_t* loop)
|
||||
|
||||
Releases all internal loop resources. Call this function only when the loop
|
||||
|
27
docs/src/metrics.rst
Normal file
27
docs/src/metrics.rst
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
.. _metrics:
|
||||
|
||||
Metrics operations
|
||||
======================
|
||||
|
||||
libuv provides a metrics API to track the amount of time the event loop has
|
||||
spent idle in the kernel's event provider.
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: uint64_t uv_metrics_idle_time(uv_loop_t* loop)
|
||||
|
||||
Retrieve the amount of time the event loop has been idle in the kernel's
|
||||
event provider (e.g. ``epoll_wait``). The call is thread safe.
|
||||
|
||||
The return value is the accumulated time spent idle in the kernel's event
|
||||
provider starting from when the :c:type:`uv_loop_t` was configured to
|
||||
collect the idle time.
|
||||
|
||||
.. note::
|
||||
The event loop will not begin accumulating the event provider's idle
|
||||
time until calling :c:type:`uv_loop_configure` with
|
||||
:c:type:`UV_METRICS_IDLE_TIME`.
|
||||
|
||||
.. versionadded:: 1.39.0
|
@ -131,11 +131,11 @@ Data types
|
||||
char* model;
|
||||
int speed;
|
||||
struct uv_cpu_times_s {
|
||||
uint64_t user;
|
||||
uint64_t nice;
|
||||
uint64_t sys;
|
||||
uint64_t idle;
|
||||
uint64_t irq;
|
||||
uint64_t user; /* milliseconds */
|
||||
uint64_t nice; /* milliseconds */
|
||||
uint64_t sys; /* milliseconds */
|
||||
uint64_t idle; /* milliseconds */
|
||||
uint64_t irq; /* milliseconds */
|
||||
} cpu_times;
|
||||
} uv_cpu_info_t;
|
||||
|
||||
@ -233,6 +233,24 @@ API
|
||||
sure the allocator is changed while no memory was allocated with
|
||||
the previous allocator, or that they are compatible.
|
||||
|
||||
.. warning:: Allocator must be thread-safe.
|
||||
|
||||
.. c:function:: void uv_library_shutdown(void);
|
||||
|
||||
.. versionadded:: 1.38.0
|
||||
|
||||
Release any global state that libuv is holding onto. Libuv will normally
|
||||
do so automatically when it is unloaded but it can be instructed to perform
|
||||
cleanup manually.
|
||||
|
||||
.. warning:: Only call :c:func:`uv_library_shutdown()` once.
|
||||
|
||||
.. warning:: Don't call :c:func:`uv_library_shutdown()` when there are
|
||||
still event loops or I/O requests active.
|
||||
|
||||
.. warning:: Don't call libuv functions after calling
|
||||
:c:func:`uv_library_shutdown()`.
|
||||
|
||||
.. c:function:: uv_buf_t uv_buf_init(char* base, unsigned int len)
|
||||
|
||||
Constructor for :c:type:`uv_buf_t`.
|
||||
@ -243,9 +261,9 @@ API
|
||||
|
||||
.. c:function:: char** uv_setup_args(int argc, char** argv)
|
||||
|
||||
Store the program arguments. Required for getting / setting the process title.
|
||||
Libuv may take ownership of the memory that `argv` points to. This function
|
||||
should be called exactly once, at program start-up.
|
||||
Store the program arguments. Required for getting / setting the process title
|
||||
or the executable path. Libuv may take ownership of the memory that `argv`
|
||||
points to. This function should be called exactly once, at program start-up.
|
||||
|
||||
Example:
|
||||
|
||||
@ -257,29 +275,44 @@ API
|
||||
.. c:function:: int uv_get_process_title(char* buffer, size_t size)
|
||||
|
||||
Gets the title of the current process. You *must* call `uv_setup_args`
|
||||
before calling this function. If `buffer` is `NULL` or `size` is zero,
|
||||
`UV_EINVAL` is returned. If `size` cannot accommodate the process title and
|
||||
terminating `NULL` character, the function returns `UV_ENOBUFS`.
|
||||
before calling this function on Unix and AIX systems. If `uv_setup_args`
|
||||
has not been called on systems that require it, then `UV_ENOBUFS` is
|
||||
returned. If `buffer` is `NULL` or `size` is zero, `UV_EINVAL` is returned.
|
||||
If `size` cannot accommodate the process title and terminating `nul`
|
||||
character, the function returns `UV_ENOBUFS`.
|
||||
|
||||
.. note::
|
||||
On BSD systems, `uv_setup_args` is needed for getting the initial process
|
||||
title. The process title returned will be an empty string until either
|
||||
`uv_setup_args` or `uv_set_process_title` is called.
|
||||
|
||||
.. versionchanged:: 1.18.1 now thread-safe on all supported platforms.
|
||||
|
||||
.. versionchanged:: 1.39.0 now returns an error if `uv_setup_args` is needed
|
||||
but hasn't been called.
|
||||
|
||||
.. c:function:: int uv_set_process_title(const char* title)
|
||||
|
||||
Sets the current process title. You *must* call `uv_setup_args` before
|
||||
calling this function. On platforms with a fixed size buffer for the process
|
||||
title the contents of `title` will be copied to the buffer and truncated if
|
||||
larger than the available space. Other platforms will return `UV_ENOMEM` if
|
||||
they cannot allocate enough space to duplicate the contents of `title`.
|
||||
calling this function on Unix and AIX systems. If `uv_setup_args` has not
|
||||
been called on systems that require it, then `UV_ENOBUFS` is returned. On
|
||||
platforms with a fixed size buffer for the process title the contents of
|
||||
`title` will be copied to the buffer and truncated if larger than the
|
||||
available space. Other platforms will return `UV_ENOMEM` if they cannot
|
||||
allocate enough space to duplicate the contents of `title`.
|
||||
|
||||
.. versionchanged:: 1.18.1 now thread-safe on all supported platforms.
|
||||
|
||||
.. versionchanged:: 1.39.0 now returns an error if `uv_setup_args` is needed
|
||||
but hasn't been called.
|
||||
|
||||
.. c:function:: int uv_resident_set_memory(size_t* rss)
|
||||
|
||||
Gets the resident set size (RSS) for the current process.
|
||||
|
||||
.. c:function:: int uv_uptime(double* uptime)
|
||||
|
||||
Gets the current system uptime.
|
||||
Gets the current system uptime. Depending on the system full or fractional seconds are returned.
|
||||
|
||||
.. c:function:: int uv_getrusage(uv_rusage_t* rusage)
|
||||
|
||||
@ -301,11 +334,30 @@ API
|
||||
|
||||
.. versionadded:: 1.16.0
|
||||
|
||||
.. c:function:: unsigned int uv_available_parallelism(void)
|
||||
|
||||
Returns an estimate of the default amount of parallelism a program should
|
||||
use. Always returns a non-zero value.
|
||||
|
||||
On Linux, inspects the calling thread's CPU affinity mask to determine if
|
||||
it has been pinned to specific CPUs.
|
||||
|
||||
On Windows, the available parallelism may be underreported on systems with
|
||||
more than 64 logical CPUs.
|
||||
|
||||
On other platforms, reports the number of CPUs that the operating system
|
||||
considers to be online.
|
||||
|
||||
.. versionadded:: 1.44.0
|
||||
|
||||
.. c:function:: int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count)
|
||||
|
||||
Gets information about the CPUs on the system. The `cpu_infos` array will
|
||||
have `count` elements and needs to be freed with :c:func:`uv_free_cpu_info`.
|
||||
|
||||
Use :c:func:`uv_available_parallelism` if you need to know how many CPUs
|
||||
are available for threads or child processes.
|
||||
|
||||
.. c:function:: void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count)
|
||||
|
||||
Frees the `cpu_infos` array previously allocated with :c:func:`uv_cpu_info`.
|
||||
@ -344,6 +396,10 @@ API
|
||||
|
||||
Convert a binary structure containing an IPv6 address to a string.
|
||||
|
||||
.. c:function:: int uv_ip_name(const struct sockaddr *src, char *dst, size_t size)
|
||||
|
||||
Convert a binary structure containing an IPv4 address or an IPv6 address to a string.
|
||||
|
||||
.. c:function:: int uv_inet_ntop(int af, const void* src, char* dst, size_t size)
|
||||
.. c:function:: int uv_inet_pton(int af, const char* src, void* dst)
|
||||
|
||||
@ -407,7 +463,8 @@ API
|
||||
|
||||
.. c:function:: int uv_exepath(char* buffer, size_t* size)
|
||||
|
||||
Gets the executable path.
|
||||
Gets the executable path. You *must* call `uv_setup_args` before calling
|
||||
this function.
|
||||
|
||||
.. c:function:: int uv_cwd(char* buffer, size_t* size)
|
||||
|
||||
@ -484,11 +541,11 @@ API
|
||||
|
||||
.. c:function:: uint64_t uv_get_free_memory(void)
|
||||
|
||||
Gets memory information (in bytes).
|
||||
Gets the amount of free memory available in the system, as reported by the kernel (in bytes).
|
||||
|
||||
.. c:function:: uint64_t uv_get_total_memory(void)
|
||||
|
||||
Gets memory information (in bytes).
|
||||
Gets the total amount of physical memory in the system (in bytes).
|
||||
|
||||
.. c:function:: uint64_t uv_get_constrained_memory(void)
|
||||
|
||||
@ -499,7 +556,7 @@ API
|
||||
|
||||
.. note::
|
||||
This function currently only returns a non-zero value on Linux, based
|
||||
on cgroups if it is present.
|
||||
on cgroups if it is present, and on z/OS based on RLIMIT_MEMLIMIT.
|
||||
|
||||
.. versionadded:: 1.29.0
|
||||
|
||||
@ -649,6 +706,16 @@ API
|
||||
On Windows, setting `PRIORITY_HIGHEST` will only work for elevated user,
|
||||
for others it will be silently reduced to `PRIORITY_HIGH`.
|
||||
|
||||
.. note::
|
||||
On IBM i PASE, the highest process priority is -10. The constant
|
||||
`UV_PRIORITY_HIGHEST` is -10, `UV_PRIORITY_HIGH` is -7,
|
||||
`UV_PRIORITY_ABOVE_NORMAL` is -4, `UV_PRIORITY_NORMAL` is 0,
|
||||
`UV_PRIORITY_BELOW_NORMAL` is 15 and `UV_PRIORITY_LOW` is 39.
|
||||
|
||||
.. note::
|
||||
On IBM i PASE, you are not allowed to change your priority unless you
|
||||
have the \*JOBCTL special authority (even to lower it).
|
||||
|
||||
.. versionadded:: 1.23.0
|
||||
|
||||
.. c:function:: int uv_os_uname(uv_utsname_t* buffer)
|
||||
@ -688,7 +755,7 @@ API
|
||||
:man:`sysctl(2)`.
|
||||
- FreeBSD: `getrandom(2) <https://www.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2>_`,
|
||||
or `/dev/urandom` after reading from `/dev/random` once.
|
||||
- NetBSD: `KERN_ARND` `sysctl(3) <https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+3+NetBSD-current>_`
|
||||
- NetBSD: `KERN_ARND` `sysctl(7) <https://man.netbsd.org/sysctl.7>_`
|
||||
- macOS, OpenBSD: `getentropy(2) <https://man.openbsd.org/getentropy.2>_`
|
||||
if available, or `/dev/urandom` after reading from `/dev/random` once.
|
||||
- AIX: `/dev/random`.
|
||||
|
@ -118,3 +118,21 @@ API
|
||||
function is blocking.
|
||||
|
||||
.. versionadded:: 1.16.0
|
||||
|
||||
.. c:function:: int uv_pipe(uv_file fds[2], int read_flags, int write_flags)
|
||||
|
||||
Create a pair of connected pipe handles.
|
||||
Data may be written to `fds[1]` and read from `fds[0]`.
|
||||
The resulting handles can be passed to `uv_pipe_open`, used with `uv_spawn`,
|
||||
or for any other purpose.
|
||||
|
||||
Valid values for `flags` are:
|
||||
|
||||
- UV_NONBLOCK_PIPE: Opens the specified socket handle for `OVERLAPPED`
|
||||
or `FIONBIO`/`O_NONBLOCK` I/O usage.
|
||||
This is recommended for handles that will be used by libuv,
|
||||
and not usually recommended otherwise.
|
||||
|
||||
Equivalent to :man:`pipe(2)` with the `O_CLOEXEC` flag set.
|
||||
|
||||
.. versionadded:: 1.41.0
|
||||
|
@ -86,36 +86,63 @@ API
|
||||
.. c:function:: int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb)
|
||||
|
||||
Starts polling the file descriptor. `events` is a bitmask made up of
|
||||
UV_READABLE, UV_WRITABLE, UV_PRIORITIZED and UV_DISCONNECT. As soon as an
|
||||
event is detected the callback will be called with `status` set to 0, and the
|
||||
detected events set on the `events` field.
|
||||
`UV_READABLE`, `UV_WRITABLE`, `UV_PRIORITIZED` and `UV_DISCONNECT`. As soon
|
||||
as an event is detected the callback will be called with `status` set to 0,
|
||||
and the detected events set on the `events` field.
|
||||
|
||||
The UV_PRIORITIZED event is used to watch for sysfs interrupts or TCP out-of-band
|
||||
messages.
|
||||
The `UV_PRIORITIZED` event is used to watch for sysfs interrupts or TCP
|
||||
out-of-band messages.
|
||||
|
||||
The UV_DISCONNECT event is optional in the sense that it may not be
|
||||
reported and the user is free to ignore it, but it can help optimize the shutdown
|
||||
path because an extra read or write call might be avoided.
|
||||
The `UV_DISCONNECT` event is optional in the sense that it may not be
|
||||
reported and the user is free to ignore it, but it can help optimize the
|
||||
shutdown path because an extra read or write call might be avoided.
|
||||
|
||||
If an error happens while polling, `status` will be < 0 and corresponds
|
||||
with one of the UV_E* error codes (see :ref:`errors`). The user should
|
||||
with one of the `UV_E*` error codes (see :ref:`errors`). The user should
|
||||
not close the socket while the handle is active. If the user does that
|
||||
anyway, the callback *may* be called reporting an error status, but this
|
||||
is **not** guaranteed.
|
||||
anyway, the callback *may* be called reporting an error status, but this is
|
||||
**not** guaranteed.
|
||||
|
||||
.. note::
|
||||
Calling :c:func:`uv_poll_start` on a handle that is already active is fine. Doing so
|
||||
will update the events mask that is being watched for.
|
||||
Calling :c:func:`uv_poll_start` on a handle that is already active is
|
||||
fine. Doing so will update the events mask that is being watched for.
|
||||
|
||||
.. note::
|
||||
Though UV_DISCONNECT can be set, it is unsupported on AIX and as such will not be set
|
||||
on the `events` field in the callback.
|
||||
Though `UV_DISCONNECT` can be set, it is unsupported on AIX and as such
|
||||
will not be set on the `events` field in the callback.
|
||||
|
||||
.. versionchanged:: 1.9.0 Added the UV_DISCONNECT event.
|
||||
.. versionchanged:: 1.14.0 Added the UV_PRIORITIZED event.
|
||||
.. note::
|
||||
If one of the events `UV_READABLE` or `UV_WRITABLE` are set, the
|
||||
callback will be called again, as long as the given fd/socket remains
|
||||
readable or writable accordingly. Particularly in each of the following
|
||||
scenarios:
|
||||
|
||||
* The callback has been called because the socket became
|
||||
readable/writable and the callback did not conduct a read/write on
|
||||
this socket at all.
|
||||
* The callback committed a read on the socket, and has not read all the
|
||||
available data (when `UV_READABLE` is set).
|
||||
* The callback committed a write on the socket, but it remained
|
||||
writable afterwards (when `UV_WRITABLE` is set).
|
||||
* The socket has already became readable/writable before calling
|
||||
:c:func:`uv_poll_start` on a poll handle associated with this socket,
|
||||
and since then the state of the socket did not changed.
|
||||
|
||||
In all of the above listed scenarios, the socket remains readable or
|
||||
writable and hence the callback will be called again (depending on the
|
||||
events set in the bitmask). This behaviour is known as level
|
||||
triggering.
|
||||
|
||||
.. versionchanged:: 1.9.0 Added the `UV_DISCONNECT` event.
|
||||
.. versionchanged:: 1.14.0 Added the `UV_PRIORITIZED` event.
|
||||
|
||||
.. c:function:: int uv_poll_stop(uv_poll_t* poll)
|
||||
|
||||
Stop polling the file descriptor, the callback will no longer be called.
|
||||
|
||||
.. note::
|
||||
Calling :c:func:`uv_poll_stop` is effective immediately: any pending
|
||||
callback is also canceled, even if the socket state change notification
|
||||
was already pending.
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
|
@ -33,14 +33,22 @@ API
|
||||
|
||||
.. c:function:: int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare)
|
||||
|
||||
Initialize the handle.
|
||||
Initialize the handle. This function always succeeds.
|
||||
|
||||
:returns: 0
|
||||
|
||||
.. c:function:: int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb)
|
||||
|
||||
Start the handle with the given callback.
|
||||
Start the handle with the given callback. This function always succeeds,
|
||||
except when `cb` is `NULL`.
|
||||
|
||||
:returns: 0 on success, or `UV_EINVAL` when `cb == NULL`.
|
||||
|
||||
.. c:function:: int uv_prepare_stop(uv_prepare_t* prepare)
|
||||
|
||||
Stop the handle, the callback will no longer be called.
|
||||
This function always succeeds.
|
||||
|
||||
:returns: 0
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
|
@ -102,72 +102,104 @@ Data types
|
||||
} data;
|
||||
} uv_stdio_container_t;
|
||||
|
||||
.. c:type:: uv_stdio_flags
|
||||
.. c:enum:: uv_stdio_flags
|
||||
|
||||
Flags specifying how a stdio should be transmitted to the child process.
|
||||
|
||||
::
|
||||
|
||||
typedef enum {
|
||||
/*
|
||||
* The following four options are mutually-exclusive, and define
|
||||
* the operation to perform for the corresponding file descriptor
|
||||
* in the child process:
|
||||
*/
|
||||
|
||||
/*
|
||||
* No file descriptor will be provided (or redirected to
|
||||
* `/dev/null` if it is fd 0, 1 or 2).
|
||||
*/
|
||||
UV_IGNORE = 0x00,
|
||||
|
||||
/*
|
||||
* Open a new pipe into `data.stream`, per the flags below. The
|
||||
* `data.stream` field must point to a uv_pipe_t object that has
|
||||
* been initialized with `uv_pipe_init(loop, data.stream, ipc);`,
|
||||
* but not yet opened or connected.
|
||||
/*
|
||||
UV_CREATE_PIPE = 0x01,
|
||||
|
||||
/*
|
||||
* The child process will be given a duplicate of the parent's
|
||||
* file descriptor given by `data.fd`.
|
||||
*/
|
||||
UV_INHERIT_FD = 0x02,
|
||||
|
||||
/*
|
||||
* The child process will be given a duplicate of the parent's
|
||||
* file descriptor being used by the stream handle given by
|
||||
* `data.stream`.
|
||||
*/
|
||||
UV_INHERIT_STREAM = 0x04,
|
||||
|
||||
/*
|
||||
* When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
|
||||
* determine the direction of flow, from the child process' perspective. Both
|
||||
* flags may be specified to create a duplex data stream.
|
||||
*/
|
||||
UV_READABLE_PIPE = 0x10,
|
||||
UV_WRITABLE_PIPE = 0x20
|
||||
UV_WRITABLE_PIPE = 0x20,
|
||||
|
||||
/*
|
||||
* Open the child pipe handle in overlapped mode on Windows.
|
||||
* On Unix it is silently ignored.
|
||||
*/
|
||||
UV_OVERLAPPED_PIPE = 0x40
|
||||
* When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the
|
||||
* handle in non-blocking mode in the child. This may cause loss of data,
|
||||
* if the child is not designed to handle to encounter this mode,
|
||||
* but can also be significantly more efficient.
|
||||
*/
|
||||
UV_NONBLOCK_PIPE = 0x40
|
||||
} uv_stdio_flags;
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: uv_process_t.pid
|
||||
.. c:member:: int uv_process_t.pid
|
||||
|
||||
The PID of the spawned process. It's set after calling :c:func:`uv_spawn`.
|
||||
|
||||
.. note::
|
||||
The :c:type:`uv_handle_t` members also apply.
|
||||
|
||||
.. c:member:: uv_process_options_t.exit_cb
|
||||
.. c:member:: uv_exit_cb uv_process_options_t.exit_cb
|
||||
|
||||
Callback called after the process exits.
|
||||
|
||||
.. c:member:: uv_process_options_t.file
|
||||
.. c:member:: const char* uv_process_options_t.file
|
||||
|
||||
Path pointing to the program to be executed.
|
||||
|
||||
.. c:member:: uv_process_options_t.args
|
||||
.. c:member:: char** uv_process_options_t.args
|
||||
|
||||
Command line arguments. args[0] should be the path to the program. On
|
||||
Windows this uses `CreateProcess` which concatenates the arguments into a
|
||||
string this can cause some strange errors. See the
|
||||
``UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS`` flag on :c:type:`uv_process_flags`.
|
||||
|
||||
.. c:member:: uv_process_options_t.env
|
||||
.. c:member:: char** uv_process_options_t.env
|
||||
|
||||
Environment for the new process. If NULL the parents environment is used.
|
||||
|
||||
.. c:member:: uv_process_options_t.cwd
|
||||
.. c:member:: const char* uv_process_options_t.cwd
|
||||
|
||||
Current working directory for the subprocess.
|
||||
|
||||
.. c:member:: uv_process_options_t.flags
|
||||
.. c:member:: unsigned int uv_process_options_t.flags
|
||||
|
||||
Various flags that control how :c:func:`uv_spawn` behaves. See
|
||||
:c:type:`uv_process_flags`.
|
||||
|
||||
.. c:member:: uv_process_options_t.stdio_count
|
||||
.. c:member:: uv_process_options_t.stdio
|
||||
.. c:member:: int uv_process_options_t.stdio_count
|
||||
.. c:member:: uv_stdio_container_t* uv_process_options_t.stdio
|
||||
|
||||
The `stdio` field points to an array of :c:type:`uv_stdio_container_t`
|
||||
structs that describe the file descriptors that will be made available to
|
||||
@ -178,8 +210,8 @@ Public members
|
||||
On Windows file descriptors greater than 2 are available to the child process only if
|
||||
the child processes uses the MSVCRT runtime.
|
||||
|
||||
.. c:member:: uv_process_options_t.uid
|
||||
.. c:member:: uv_process_options_t.gid
|
||||
.. c:member:: uv_uid_t uv_process_options_t.uid
|
||||
.. c:member:: uv_gid_t uv_process_options_t.gid
|
||||
|
||||
Libuv can change the child process' user/group id. This happens only when
|
||||
the appropriate bits are set in the flags fields.
|
||||
@ -188,14 +220,13 @@ Public members
|
||||
This is not supported on Windows, :c:func:`uv_spawn` will fail and set the error
|
||||
to ``UV_ENOTSUP``.
|
||||
|
||||
.. c:member:: uv_stdio_container_t.flags
|
||||
.. c:member:: uv_stdio_flags uv_stdio_container_t.flags
|
||||
|
||||
Flags specifying how the stdio container should be passed to the child. See
|
||||
:c:type:`uv_stdio_flags`.
|
||||
Flags specifying how the stdio container should be passed to the child.
|
||||
|
||||
.. c:member:: uv_stdio_container_t.data
|
||||
.. c:member:: union @0 uv_stdio_container_t.data
|
||||
|
||||
Union containing either the stream or fd to be passed on to the child
|
||||
Union containing either the `stream` or `fd` to be passed on to the child
|
||||
process.
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ Public members
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: UV_REQ_TYPE_MAP(iter_macro)
|
||||
.. c:macro:: UV_REQ_TYPE_MAP(iter_macro)
|
||||
|
||||
Macro that expands to a series of invocations of `iter_macro` for
|
||||
each of the request types. `iter_macro` is invoked with two
|
||||
@ -69,8 +69,8 @@ API
|
||||
Returns 0 on success, or an error code < 0 on failure.
|
||||
|
||||
Only cancellation of :c:type:`uv_fs_t`, :c:type:`uv_getaddrinfo_t`,
|
||||
:c:type:`uv_getnameinfo_t` and :c:type:`uv_work_t` requests is
|
||||
currently supported.
|
||||
:c:type:`uv_getnameinfo_t`, :c:type:`uv_random_t` and :c:type:`uv_work_t`
|
||||
requests is currently supported.
|
||||
|
||||
Cancelled requests have their callbacks invoked some time in the future.
|
||||
It's **not** safe to free the memory associated with the request until the
|
||||
@ -80,8 +80,9 @@ API
|
||||
|
||||
* A :c:type:`uv_fs_t` request has its req->result field set to `UV_ECANCELED`.
|
||||
|
||||
* A :c:type:`uv_work_t`, :c:type:`uv_getaddrinfo_t` or c:type:`uv_getnameinfo_t`
|
||||
request has its callback invoked with status == `UV_ECANCELED`.
|
||||
* A :c:type:`uv_work_t`, :c:type:`uv_getaddrinfo_t`,
|
||||
:c:type:`uv_getnameinfo_t` or :c:type:`uv_random_t` request has its
|
||||
callback invoked with status == `UV_ECANCELED`.
|
||||
|
||||
.. c:function:: size_t uv_req_size(uv_req_type type)
|
||||
|
||||
|
@ -18,7 +18,7 @@ from string import Template
|
||||
def make_link_node(rawtext, app, name, manpage_num, options):
|
||||
ref = app.config.man_url_regex
|
||||
if not ref:
|
||||
ref = "http://man7.org/linux/man-pages/man%s/%s.%s.html" %(manpage_num, name, manpage_num)
|
||||
ref = "https://man7.org/linux/man-pages/man%s/%s.%s.html" %(manpage_num, name, manpage_num)
|
||||
else:
|
||||
s = Template(ref)
|
||||
ref = s.substitute(num=manpage_num, topic=name)
|
||||
|
@ -139,6 +139,11 @@ API
|
||||
be made several times until there is no more data to read or
|
||||
:c:func:`uv_read_stop` is called.
|
||||
|
||||
.. versionchanged:: 1.38.0 :c:func:`uv_read_start()` now consistently
|
||||
returns `UV_EALREADY` when called twice, and `UV_EINVAL` when the
|
||||
stream is closing. With older libuv versions, it returns `UV_EALREADY`
|
||||
on Windows but not UNIX, and `UV_EINVAL` on UNIX but not Windows.
|
||||
|
||||
.. c:function:: int uv_read_stop(uv_stream_t*)
|
||||
|
||||
Stop reading data from the stream. The :c:type:`uv_read_cb` callback will
|
||||
@ -146,6 +151,11 @@ API
|
||||
|
||||
This function is idempotent and may be safely called on a stopped stream.
|
||||
|
||||
This function will always succeed; hence, checking its return value is
|
||||
unnecessary. A non-zero return indicates that finishing releasing resources
|
||||
may be pending on the next input event on that TTY on Windows, and does not
|
||||
indicate failure.
|
||||
|
||||
.. c:function:: int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb)
|
||||
|
||||
Write data to stream. Buffers are written in order. Example:
|
||||
@ -183,8 +193,9 @@ API
|
||||
initialized with `ipc` == 1.
|
||||
|
||||
.. note::
|
||||
`send_handle` must be a TCP socket or pipe, which is a server or a connection (listening
|
||||
or connected state). Bound sockets or pipes will be assumed to be servers.
|
||||
`send_handle` must be a TCP, pipe and UDP handle on Unix, or a TCP
|
||||
handle on Windows, which is a server or a connection (listening or
|
||||
connected state). Bound sockets or pipes will be assumed to be servers.
|
||||
|
||||
.. c:function:: int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs)
|
||||
|
||||
@ -197,6 +208,16 @@ API
|
||||
* < 0: negative error code (``UV_EAGAIN`` is returned if no data can be sent
|
||||
immediately).
|
||||
|
||||
.. c:function:: int uv_try_write2(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle)
|
||||
|
||||
Same as :c:func:`uv_try_write` and extended write function for sending
|
||||
handles over a pipe like c:func:`uv_write2`.
|
||||
|
||||
Try to send a handle is not supported on Windows,
|
||||
where it returns ``UV_EAGAIN``.
|
||||
|
||||
.. versionadded:: 1.42.0
|
||||
|
||||
.. c:function:: int uv_is_readable(const uv_stream_t* handle)
|
||||
|
||||
Returns 1 if the stream is readable, 0 otherwise.
|
||||
|
@ -81,10 +81,9 @@ API
|
||||
initialized ``struct sockaddr_in`` or ``struct sockaddr_in6``.
|
||||
|
||||
When the port is already taken, you can expect to see an ``UV_EADDRINUSE``
|
||||
error from either :c:func:`uv_tcp_bind`, :c:func:`uv_listen` or
|
||||
:c:func:`uv_tcp_connect`. That is, a successful call to this function does
|
||||
not guarantee that the call to :c:func:`uv_listen` or :c:func:`uv_tcp_connect`
|
||||
will succeed as well.
|
||||
error from :c:func:`uv_listen` or :c:func:`uv_tcp_connect`. That is,
|
||||
a successful call to this function does not guarantee that the call
|
||||
to :c:func:`uv_listen` or :c:func:`uv_tcp_connect` will succeed as well.
|
||||
|
||||
`flags` can contain ``UV_TCP_IPV6ONLY``, in which case dual-stack support
|
||||
is disabled and only IPv6 is used.
|
||||
@ -128,3 +127,20 @@ API
|
||||
:c:func:`uv_tcp_close_reset` calls is not allowed.
|
||||
|
||||
.. versionadded:: 1.32.0
|
||||
|
||||
.. c:function:: int uv_socketpair(int type, int protocol, uv_os_sock_t socket_vector[2], int flags0, int flags1)
|
||||
|
||||
Create a pair of connected sockets with the specified properties.
|
||||
The resulting handles can be passed to `uv_tcp_open`, used with `uv_spawn`,
|
||||
or for any other purpose.
|
||||
|
||||
Valid values for `flags0` and `flags1` are:
|
||||
|
||||
- UV_NONBLOCK_PIPE: Opens the specified socket handle for `OVERLAPPED`
|
||||
or `FIONBIO`/`O_NONBLOCK` I/O usage.
|
||||
This is recommended for handles that will be used by libuv,
|
||||
and not usually recommended otherwise.
|
||||
|
||||
Equivalent to :man:`socketpair(2)` with a domain of AF_UNIX.
|
||||
|
||||
.. versionadded:: 1.41.0
|
||||
|
@ -78,4 +78,11 @@ API
|
||||
|
||||
Get the timer repeat value.
|
||||
|
||||
.. c:function:: uint64_t uv_timer_get_due_in(const uv_timer_t* handle)
|
||||
|
||||
Get the timer due value or 0 if it has expired. The time is relative to
|
||||
:c:func:`uv_now()`.
|
||||
|
||||
.. versionadded:: 1.40.0
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
|
@ -16,7 +16,7 @@ Data types
|
||||
|
||||
TTY handle type.
|
||||
|
||||
.. c:type:: uv_tty_mode_t
|
||||
.. c:enum:: uv_tty_mode_t
|
||||
|
||||
.. versionadded:: 1.2.0
|
||||
|
||||
@ -33,7 +33,8 @@ Data types
|
||||
UV_TTY_MODE_IO
|
||||
} uv_tty_mode_t;
|
||||
|
||||
.. c:type:: uv_tty_vtermstate_t
|
||||
.. c:enum:: uv_tty_vtermstate_t
|
||||
|
||||
Console virtual terminal mode type:
|
||||
|
||||
::
|
||||
|
@ -41,13 +41,30 @@ Data types
|
||||
* (provided they all set the flag) but only the last one to bind will receive
|
||||
* any traffic, in effect "stealing" the port from the previous listener.
|
||||
*/
|
||||
UV_UDP_REUSEADDR = 4
|
||||
UV_UDP_REUSEADDR = 4,
|
||||
/*
|
||||
* Indicates that the message was received by recvmmsg and that it's not at
|
||||
* the beginning of the buffer allocated by alloc_cb - so the buffer provided
|
||||
* Indicates that the message was received by recvmmsg, so the buffer provided
|
||||
* must not be freed by the recv_cb callback.
|
||||
*/
|
||||
UV_UDP_MMSG_CHUNK = 8
|
||||
UV_UDP_MMSG_CHUNK = 8,
|
||||
/*
|
||||
* Indicates that the buffer provided has been fully utilized by recvmmsg and
|
||||
* that it should now be freed by the recv_cb callback. When this flag is set
|
||||
* in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL.
|
||||
*/
|
||||
UV_UDP_MMSG_FREE = 16,
|
||||
/*
|
||||
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
|
||||
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
|
||||
* Linux. This stops the Linux kernel from supressing some ICMP error messages
|
||||
* and enables full ICMP error reporting for faster failover.
|
||||
* This flag is no-op on platforms other than Linux.
|
||||
*/
|
||||
UV_UDP_LINUX_RECVERR = 32,
|
||||
/*
|
||||
* Indicates that recvmmsg should be used, if available.
|
||||
*/
|
||||
UV_UDP_RECVMMSG = 256
|
||||
};
|
||||
|
||||
.. c:type:: void (*uv_udp_send_cb)(uv_udp_send_t* req, int status)
|
||||
@ -64,7 +81,8 @@ Data types
|
||||
* `nread`: Number of bytes that have been received.
|
||||
0 if there is no more data to read. Note that 0 may also mean that an
|
||||
empty datagram was received (in this case `addr` is not NULL). < 0 if
|
||||
a transmission error was detected.
|
||||
a transmission error was detected; if using :man:`recvmmsg(2)` no more
|
||||
chunks will be received and the buffer can be freed safely.
|
||||
* `buf`: :c:type:`uv_buf_t` with the received data.
|
||||
* `addr`: ``struct sockaddr*`` containing the address of the sender.
|
||||
Can be NULL. Valid for the duration of the callback only.
|
||||
@ -72,16 +90,23 @@ Data types
|
||||
|
||||
The callee is responsible for freeing the buffer, libuv does not reuse it.
|
||||
The buffer may be a null buffer (where `buf->base` == NULL and `buf->len` == 0)
|
||||
on error. Don't free the buffer when the UV_UDP_MMSG_CHUNK flag is set.
|
||||
The final callback receives the whole buffer (containing the first chunk)
|
||||
with the UV_UDP_MMSG_CHUNK flag cleared.
|
||||
on error.
|
||||
|
||||
When using :man:`recvmmsg(2)`, chunks will have the `UV_UDP_MMSG_CHUNK` flag set,
|
||||
those must not be freed. If no errors occur, there will be a final callback with
|
||||
`nread` set to 0, `addr` set to NULL and the buffer pointing at the initially
|
||||
allocated data with the `UV_UDP_MMSG_CHUNK` flag cleared and the `UV_UDP_MMSG_FREE`
|
||||
flag set. If a UDP socket error occurs, `nread` will be < 0. In either scenario,
|
||||
the callee can now safely free the provided buffer.
|
||||
|
||||
.. versionchanged:: 1.40.0 added the `UV_UDP_MMSG_FREE` flag.
|
||||
|
||||
.. note::
|
||||
The receive callback will be called with `nread` == 0 and `addr` == NULL when there is
|
||||
nothing to read, and with `nread` == 0 and `addr` != NULL when an empty UDP packet is
|
||||
received.
|
||||
|
||||
.. c:type:: uv_membership
|
||||
.. c:enum:: uv_membership
|
||||
|
||||
Membership type for a multicast address.
|
||||
|
||||
@ -122,12 +147,17 @@ API
|
||||
|
||||
.. c:function:: int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags)
|
||||
|
||||
Initialize the handle with the specified flags. At the moment the lower 8 bits
|
||||
of the `flags` parameter are used as the socket domain. A socket will be created
|
||||
for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created,
|
||||
just like :c:func:`uv_udp_init`.
|
||||
Initialize the handle with the specified flags. The lower 8 bits of the `flags`
|
||||
parameter are used as the socket domain. A socket will be created for the given domain.
|
||||
If the specified domain is ``AF_UNSPEC`` no socket is created, just like :c:func:`uv_udp_init`.
|
||||
|
||||
The remaining bits can be used to set one of these flags:
|
||||
|
||||
* `UV_UDP_RECVMMSG`: if set, and the platform supports it, :man:`recvmmsg(2)` will
|
||||
be used.
|
||||
|
||||
.. versionadded:: 1.7.0
|
||||
.. versionchanged:: 1.37.0 added the `UV_UDP_RECVMMSG` flag.
|
||||
|
||||
.. c:function:: int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock)
|
||||
|
||||
@ -156,7 +186,8 @@ API
|
||||
with the address and port to bind to.
|
||||
|
||||
:param flags: Indicate how the socket will be bound,
|
||||
``UV_UDP_IPV6ONLY`` and ``UV_UDP_REUSEADDR`` are supported.
|
||||
``UV_UDP_IPV6ONLY``, ``UV_UDP_REUSEADDR``, and ``UV_UDP_RECVERR``
|
||||
are supported.
|
||||
|
||||
:returns: 0 on success, or an error code < 0 on failure.
|
||||
|
||||
@ -373,6 +404,28 @@ API
|
||||
|
||||
:returns: 0 on success, or an error code < 0 on failure.
|
||||
|
||||
.. note::
|
||||
When using :man:`recvmmsg(2)`, the number of messages received at a time is limited
|
||||
by the number of max size dgrams that will fit into the buffer allocated in `alloc_cb`, and
|
||||
`suggested_size` in `alloc_cb` for udp_recv is always set to the size of 1 max size dgram.
|
||||
|
||||
.. versionchanged:: 1.35.0 added support for :man:`recvmmsg(2)` on supported platforms).
|
||||
The use of this feature requires a buffer larger than
|
||||
2 * 64KB to be passed to `alloc_cb`.
|
||||
.. versionchanged:: 1.37.0 :man:`recvmmsg(2)` support is no longer enabled implicitly,
|
||||
it must be explicitly requested by passing the `UV_UDP_RECVMMSG` flag to
|
||||
:c:func:`uv_udp_init_ex`.
|
||||
.. versionchanged:: 1.39.0 :c:func:`uv_udp_using_recvmmsg` can be used in `alloc_cb` to
|
||||
determine if a buffer sized for use with :man:`recvmmsg(2)` should be
|
||||
allocated for the current handle/platform.
|
||||
|
||||
.. c:function:: int uv_udp_using_recvmmsg(uv_udp_t* handle)
|
||||
|
||||
Returns 1 if the UDP handle was created with the `UV_UDP_RECVMMSG` flag
|
||||
and the platform supports :man:`recvmmsg(2)`, 0 otherwise.
|
||||
|
||||
.. versionadded:: 1.39.0
|
||||
|
||||
.. c:function:: int uv_udp_recv_stop(uv_udp_t* handle)
|
||||
|
||||
Stop listening for incoming datagrams.
|
||||
|
73
gyp_uv.py
73
gyp_uv.py
@ -1,73 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
try:
|
||||
import multiprocessing.synchronize
|
||||
gyp_parallel_support = True
|
||||
except ImportError:
|
||||
gyp_parallel_support = False
|
||||
|
||||
|
||||
CC = os.environ.get('CC', 'cc')
|
||||
script_dir = os.path.dirname(__file__)
|
||||
uv_root = os.path.normpath(script_dir)
|
||||
output_dir = os.path.join(os.path.abspath(uv_root), 'out')
|
||||
|
||||
sys.path.insert(0, os.path.join(uv_root, 'build', 'gyp', 'pylib'))
|
||||
try:
|
||||
import gyp
|
||||
except ImportError:
|
||||
print('You need to install gyp in build/gyp first. See the README.')
|
||||
sys.exit(42)
|
||||
|
||||
|
||||
def host_arch():
|
||||
machine = platform.machine()
|
||||
if machine == 'i386': return 'ia32'
|
||||
if machine == 'AMD64': return 'x64'
|
||||
if machine == 'x86_64': return 'x64'
|
||||
if machine.startswith('arm'): return 'arm'
|
||||
if machine.startswith('mips'): return 'mips'
|
||||
return machine # Return as-is and hope for the best.
|
||||
|
||||
|
||||
def run_gyp(args):
|
||||
rc = gyp.main(args)
|
||||
if rc != 0:
|
||||
print('Error running GYP')
|
||||
sys.exit(rc)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = sys.argv[1:]
|
||||
args.extend('-I common.gypi test/test.gyp'.split(' '))
|
||||
args.append('--depth=' + uv_root)
|
||||
|
||||
# There's a bug with windows which doesn't allow this feature.
|
||||
if sys.platform != 'win32':
|
||||
if '-f' not in args:
|
||||
args.extend('-f make'.split())
|
||||
if 'eclipse' not in args and 'ninja' not in args:
|
||||
args.extend(['-Goutput_dir=' + output_dir])
|
||||
args.extend(['--generator-output', output_dir])
|
||||
|
||||
if not any(a.startswith('-Dhost_arch=') for a in args):
|
||||
args.append('-Dhost_arch=%s' % host_arch())
|
||||
|
||||
if not any(a.startswith('-Dtarget_arch=') for a in args):
|
||||
args.append('-Dtarget_arch=%s' % host_arch())
|
||||
|
||||
if not any(a.startswith('-Duv_library=') for a in args):
|
||||
args.append('-Duv_library=static_library')
|
||||
|
||||
# Some platforms (OpenBSD for example) don't have multiprocessing.synchronize
|
||||
# so gyp must be run with --no-parallel
|
||||
if not gyp_parallel_support:
|
||||
args.append('--no-parallel')
|
||||
|
||||
gyp_args = list(args)
|
||||
print(gyp_args)
|
||||
run_gyp(gyp_args)
|
106
include/uv.h
106
include/uv.h
@ -45,6 +45,8 @@ extern "C" {
|
||||
# endif
|
||||
#elif __GNUC__ >= 4
|
||||
# define UV_EXTERN __attribute__((visibility("default")))
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) /* Sun Studio >= 8 */
|
||||
# define UV_EXTERN __global
|
||||
#else
|
||||
# define UV_EXTERN /* nothing */
|
||||
#endif
|
||||
@ -126,6 +128,7 @@ extern "C" {
|
||||
XX(ENOTEMPTY, "directory not empty") \
|
||||
XX(ENOTSOCK, "socket operation on non-socket") \
|
||||
XX(ENOTSUP, "operation not supported on socket") \
|
||||
XX(EOVERFLOW, "value too large for defined data type") \
|
||||
XX(EPERM, "operation not permitted") \
|
||||
XX(EPIPE, "broken pipe") \
|
||||
XX(EPROTO, "protocol error") \
|
||||
@ -148,6 +151,7 @@ extern "C" {
|
||||
XX(ENOTTY, "inappropriate ioctl for device") \
|
||||
XX(EFTYPE, "inappropriate file type or format") \
|
||||
XX(EILSEQ, "illegal byte sequence") \
|
||||
XX(ESOCKTNOSUPPORT, "socket type not supported") \
|
||||
|
||||
#define UV_HANDLE_TYPE_MAP(XX) \
|
||||
XX(ASYNC, async) \
|
||||
@ -247,7 +251,8 @@ typedef struct uv_utsname_s uv_utsname_t;
|
||||
typedef struct uv_statfs_s uv_statfs_t;
|
||||
|
||||
typedef enum {
|
||||
UV_LOOP_BLOCK_SIGNAL
|
||||
UV_LOOP_BLOCK_SIGNAL = 0,
|
||||
UV_METRICS_IDLE_TIME
|
||||
} uv_loop_option;
|
||||
|
||||
typedef enum {
|
||||
@ -265,6 +270,8 @@ typedef void* (*uv_realloc_func)(void* ptr, size_t size);
|
||||
typedef void* (*uv_calloc_func)(size_t count, size_t size);
|
||||
typedef void (*uv_free_func)(void* ptr);
|
||||
|
||||
UV_EXTERN void uv_library_shutdown(void);
|
||||
|
||||
UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,
|
||||
uv_realloc_func realloc_func,
|
||||
uv_calloc_func calloc_func,
|
||||
@ -472,6 +479,12 @@ UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd);
|
||||
|
||||
UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);
|
||||
|
||||
UV_EXTERN int uv_pipe(uv_file fds[2], int read_flags, int write_flags);
|
||||
UV_EXTERN int uv_socketpair(int type,
|
||||
int protocol,
|
||||
uv_os_sock_t socket_vector[2],
|
||||
int flags0,
|
||||
int flags1);
|
||||
|
||||
#define UV_STREAM_FIELDS \
|
||||
/* number of bytes queued for writing */ \
|
||||
@ -517,6 +530,10 @@ UV_EXTERN int uv_write2(uv_write_t* req,
|
||||
UV_EXTERN int uv_try_write(uv_stream_t* handle,
|
||||
const uv_buf_t bufs[],
|
||||
unsigned int nbufs);
|
||||
UV_EXTERN int uv_try_write2(uv_stream_t* handle,
|
||||
const uv_buf_t bufs[],
|
||||
unsigned int nbufs,
|
||||
uv_stream_t* send_handle);
|
||||
|
||||
/* uv_write_t is a subclass of uv_req_t. */
|
||||
struct uv_write_s {
|
||||
@ -607,11 +624,28 @@ enum uv_udp_flags {
|
||||
*/
|
||||
UV_UDP_REUSEADDR = 4,
|
||||
/*
|
||||
* Indicates that the message was received by recvmmsg and that it's not at
|
||||
* the beginning of the buffer allocated by alloc_cb - so the buffer provided
|
||||
* Indicates that the message was received by recvmmsg, so the buffer provided
|
||||
* must not be freed by the recv_cb callback.
|
||||
*/
|
||||
UV_UDP_MMSG_CHUNK = 8
|
||||
UV_UDP_MMSG_CHUNK = 8,
|
||||
/*
|
||||
* Indicates that the buffer provided has been fully utilized by recvmmsg and
|
||||
* that it should now be freed by the recv_cb callback. When this flag is set
|
||||
* in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL.
|
||||
*/
|
||||
UV_UDP_MMSG_FREE = 16,
|
||||
/*
|
||||
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
|
||||
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
|
||||
* Linux. This stops the Linux kernel from suppressing some ICMP error
|
||||
* messages and enables full ICMP error reporting for faster failover.
|
||||
* This flag is no-op on platforms other than Linux.
|
||||
*/
|
||||
UV_UDP_LINUX_RECVERR = 32,
|
||||
/*
|
||||
* Indicates that recvmmsg should be used, if available.
|
||||
*/
|
||||
UV_UDP_RECVMMSG = 256
|
||||
};
|
||||
|
||||
typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
|
||||
@ -687,6 +721,7 @@ UV_EXTERN int uv_udp_try_send(uv_udp_t* handle,
|
||||
UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
|
||||
uv_alloc_cb alloc_cb,
|
||||
uv_udp_recv_cb recv_cb);
|
||||
UV_EXTERN int uv_udp_using_recvmmsg(const uv_udp_t* handle);
|
||||
UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
|
||||
UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
|
||||
UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);
|
||||
@ -857,6 +892,7 @@ UV_EXTERN int uv_timer_stop(uv_timer_t* handle);
|
||||
UV_EXTERN int uv_timer_again(uv_timer_t* handle);
|
||||
UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat);
|
||||
UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle);
|
||||
UV_EXTERN uint64_t uv_timer_get_due_in(const uv_timer_t* handle);
|
||||
|
||||
|
||||
/*
|
||||
@ -918,10 +954,13 @@ typedef enum {
|
||||
UV_WRITABLE_PIPE = 0x20,
|
||||
|
||||
/*
|
||||
* Open the child pipe handle in overlapped mode on Windows.
|
||||
* On Unix it is silently ignored.
|
||||
* When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the
|
||||
* handle in non-blocking mode in the child. This may cause loss of data,
|
||||
* if the child is not designed to handle to encounter this mode,
|
||||
* but can also be significantly more efficient.
|
||||
*/
|
||||
UV_OVERLAPPED_PIPE = 0x40
|
||||
UV_NONBLOCK_PIPE = 0x40,
|
||||
UV_OVERLAPPED_PIPE = 0x40 /* old name, for compatibility */
|
||||
} uv_stdio_flags;
|
||||
|
||||
typedef struct uv_stdio_container_s {
|
||||
@ -1065,11 +1104,11 @@ UV_EXTERN int uv_cancel(uv_req_t* req);
|
||||
|
||||
|
||||
struct uv_cpu_times_s {
|
||||
uint64_t user;
|
||||
uint64_t nice;
|
||||
uint64_t sys;
|
||||
uint64_t idle;
|
||||
uint64_t irq;
|
||||
uint64_t user; /* milliseconds */
|
||||
uint64_t nice; /* milliseconds */
|
||||
uint64_t sys; /* milliseconds */
|
||||
uint64_t idle; /* milliseconds */
|
||||
uint64_t irq; /* milliseconds */
|
||||
};
|
||||
|
||||
struct uv_cpu_info_s {
|
||||
@ -1094,8 +1133,8 @@ struct uv_interface_address_s {
|
||||
|
||||
struct uv_passwd_s {
|
||||
char* username;
|
||||
long uid;
|
||||
long gid;
|
||||
unsigned long uid;
|
||||
unsigned long gid;
|
||||
char* shell;
|
||||
char* homedir;
|
||||
};
|
||||
@ -1183,16 +1222,27 @@ UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
|
||||
UV_EXTERN uv_pid_t uv_os_getpid(void);
|
||||
UV_EXTERN uv_pid_t uv_os_getppid(void);
|
||||
|
||||
#define UV_PRIORITY_LOW 19
|
||||
#define UV_PRIORITY_BELOW_NORMAL 10
|
||||
#define UV_PRIORITY_NORMAL 0
|
||||
#define UV_PRIORITY_ABOVE_NORMAL -7
|
||||
#define UV_PRIORITY_HIGH -14
|
||||
#define UV_PRIORITY_HIGHEST -20
|
||||
#if defined(__PASE__)
|
||||
/* On IBM i PASE, the highest process priority is -10 */
|
||||
# define UV_PRIORITY_LOW 39 /* RUNPTY(99) */
|
||||
# define UV_PRIORITY_BELOW_NORMAL 15 /* RUNPTY(50) */
|
||||
# define UV_PRIORITY_NORMAL 0 /* RUNPTY(20) */
|
||||
# define UV_PRIORITY_ABOVE_NORMAL -4 /* RUNTY(12) */
|
||||
# define UV_PRIORITY_HIGH -7 /* RUNPTY(6) */
|
||||
# define UV_PRIORITY_HIGHEST -10 /* RUNPTY(1) */
|
||||
#else
|
||||
# define UV_PRIORITY_LOW 19
|
||||
# define UV_PRIORITY_BELOW_NORMAL 10
|
||||
# define UV_PRIORITY_NORMAL 0
|
||||
# define UV_PRIORITY_ABOVE_NORMAL -7
|
||||
# define UV_PRIORITY_HIGH -14
|
||||
# define UV_PRIORITY_HIGHEST -20
|
||||
#endif
|
||||
|
||||
UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
|
||||
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
|
||||
|
||||
UV_EXTERN unsigned int uv_available_parallelism(void);
|
||||
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
|
||||
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
|
||||
|
||||
@ -1227,6 +1277,7 @@ UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
|
||||
|
||||
UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
|
||||
|
||||
UV_EXTERN uint64_t uv_metrics_idle_time(uv_loop_t* loop);
|
||||
|
||||
typedef enum {
|
||||
UV_FS_UNKNOWN = -1,
|
||||
@ -1265,7 +1316,8 @@ typedef enum {
|
||||
UV_FS_READDIR,
|
||||
UV_FS_CLOSEDIR,
|
||||
UV_FS_STATFS,
|
||||
UV_FS_MKSTEMP
|
||||
UV_FS_MKSTEMP,
|
||||
UV_FS_LUTIME
|
||||
} uv_fs_type;
|
||||
|
||||
struct uv_dir_s {
|
||||
@ -1290,6 +1342,7 @@ struct uv_fs_s {
|
||||
|
||||
UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);
|
||||
UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);
|
||||
UV_EXTERN int uv_fs_get_system_error(const uv_fs_t*);
|
||||
UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);
|
||||
UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);
|
||||
UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);
|
||||
@ -1438,6 +1491,12 @@ UV_EXTERN int uv_fs_futime(uv_loop_t* loop,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_lutime(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
@ -1602,6 +1661,7 @@ UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);
|
||||
|
||||
UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size);
|
||||
UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size);
|
||||
UV_EXTERN int uv_ip_name(const struct sockaddr* src, char* dst, size_t size);
|
||||
|
||||
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
|
||||
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
|
||||
@ -1750,9 +1810,11 @@ struct uv_loop_s {
|
||||
unsigned int active_handles;
|
||||
void* handle_queue[2];
|
||||
union {
|
||||
void* unused[2];
|
||||
void* unused;
|
||||
unsigned int count;
|
||||
} active_reqs;
|
||||
/* Internal storage for future extensions. */
|
||||
void* internal_fields;
|
||||
/* Internal flag to signal loop stop. */
|
||||
unsigned int stop_flag;
|
||||
UV_LOOP_PRIVATE_FIELDS
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||
* to be included it must be included before this header file.
|
||||
*/
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int getifaddrs(struct ifaddrs **ifap);
|
||||
extern void freeifaddrs(struct ifaddrs *ifa);
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
@ -317,7 +317,7 @@
|
||||
#if defined(EPROTO) && !defined(_WIN32)
|
||||
# define UV__EPROTO UV__ERR(EPROTO)
|
||||
#else
|
||||
# define UV__EPROTO UV__ERR(4046)
|
||||
# define UV__EPROTO (-4046)
|
||||
#endif
|
||||
|
||||
#if defined(EPROTONOSUPPORT) && !defined(_WIN32)
|
||||
@ -445,4 +445,16 @@
|
||||
# define UV__EILSEQ (-4027)
|
||||
#endif
|
||||
|
||||
#if defined(EOVERFLOW) && !defined(_WIN32)
|
||||
# define UV__EOVERFLOW UV__ERR(EOVERFLOW)
|
||||
#else
|
||||
# define UV__EOVERFLOW (-4026)
|
||||
#endif
|
||||
|
||||
#if defined(ESOCKTNOSUPPORT) && !defined(_WIN32)
|
||||
# define UV__ESOCKTNOSUPPORT UV__ERR(ESOCKTNOSUPPORT)
|
||||
#else
|
||||
# define UV__ESOCKTNOSUPPORT (-4025)
|
||||
#endif
|
||||
|
||||
#endif /* UV_ERRNO_H_ */
|
||||
|
@ -251,7 +251,7 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
for (;;) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
|
@ -65,10 +65,10 @@
|
||||
# include "uv/bsd.h"
|
||||
#elif defined(__CYGWIN__) || \
|
||||
defined(__MSYS__) || \
|
||||
defined(__HAIKU__) || \
|
||||
defined(__QNX__) || \
|
||||
defined(__GNU__)
|
||||
# include "uv/posix.h"
|
||||
#elif defined(__HAIKU__)
|
||||
# include "uv/posix.h"
|
||||
#endif
|
||||
|
||||
#ifndef NI_MAXHOST
|
||||
|
@ -26,13 +26,13 @@
|
||||
* Versions with the same major number are ABI stable. API is allowed to
|
||||
* evolve between minor releases, but only in a backwards compatible way.
|
||||
* Make sure you update the -soname directives in configure.ac
|
||||
* and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
|
||||
* whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
|
||||
* not UV_VERSION_PATCH.)
|
||||
*/
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 35
|
||||
#define UV_VERSION_PATCH 0
|
||||
#define UV_VERSION_MINOR 44
|
||||
#define UV_VERSION_PATCH 1
|
||||
#define UV_VERSION_IS_RELEASE 1
|
||||
#define UV_VERSION_SUFFIX ""
|
||||
|
||||
|
@ -45,7 +45,14 @@ typedef struct pollfd {
|
||||
#endif
|
||||
|
||||
#include <mswsock.h>
|
||||
// Disable the typedef in mstcpip.h of MinGW.
|
||||
#define _TCP_INITIAL_RTO_PARAMETERS _TCP_INITIAL_RTO_PARAMETERS__AVOID
|
||||
#define TCP_INITIAL_RTO_PARAMETERS TCP_INITIAL_RTO_PARAMETERS__AVOID
|
||||
#define PTCP_INITIAL_RTO_PARAMETERS PTCP_INITIAL_RTO_PARAMETERS__AVOID
|
||||
#include <ws2tcpip.h>
|
||||
#undef _TCP_INITIAL_RTO_PARAMETERS
|
||||
#undef TCP_INITIAL_RTO_PARAMETERS
|
||||
#undef PTCP_INITIAL_RTO_PARAMETERS
|
||||
#include <windows.h>
|
||||
|
||||
#include <process.h>
|
||||
@ -216,7 +223,7 @@ typedef struct _AFD_POLL_INFO {
|
||||
AFD_POLL_HANDLE_INFO Handles[1];
|
||||
} AFD_POLL_INFO, *PAFD_POLL_INFO;
|
||||
|
||||
#define UV_MSAFD_PROVIDER_COUNT 3
|
||||
#define UV_MSAFD_PROVIDER_COUNT 4
|
||||
|
||||
|
||||
/**
|
||||
@ -256,21 +263,14 @@ typedef union {
|
||||
} unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */
|
||||
} uv_cond_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
unsigned int num_readers_;
|
||||
CRITICAL_SECTION num_readers_lock_;
|
||||
HANDLE write_semaphore_;
|
||||
} state_;
|
||||
/* TODO: remove me in v2.x. */
|
||||
struct {
|
||||
SRWLOCK unused_;
|
||||
} unused1_;
|
||||
/* TODO: remove me in v2.x. */
|
||||
struct {
|
||||
uv_mutex_t unused1_;
|
||||
uv_mutex_t unused2_;
|
||||
} unused2_;
|
||||
typedef struct {
|
||||
SRWLOCK read_write_lock_;
|
||||
/* TODO: retained for ABI compatibility; remove me in v2.x */
|
||||
#ifdef _WIN64
|
||||
unsigned char padding_[72];
|
||||
#else
|
||||
unsigned char padding_[44];
|
||||
#endif
|
||||
} uv_rwlock_t;
|
||||
|
||||
typedef struct {
|
||||
|
12
libuv-static.pc.in
Normal file
12
libuv-static.pc.in
Normal file
@ -0,0 +1,12 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=${prefix}
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libuv-static
|
||||
Version: @PACKAGE_VERSION@
|
||||
Description: multi-platform support library with a focus on asynchronous I/O.
|
||||
URL: http://libuv.org/
|
||||
|
||||
Libs: -L${libdir} -luv_a @LIBS@
|
||||
Cflags: -I${includedir}
|
@ -89,6 +89,7 @@
|
||||
{"name":"uv_udp_recv_stop"},
|
||||
{"name":"uv_udp_get_send_queue_size"},
|
||||
{"name":"uv_udp_get_send_queue_count"},
|
||||
{"name":"uv__udp_disconnect"},
|
||||
{"name":"uv_tty_init"},
|
||||
{"name":"uv_tty_set_mode"},
|
||||
{"name":"uv_tty_reset_mode"},
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifdef _WIN32
|
||||
#include "win/internal.h"
|
||||
#include "win/handle-inl.h"
|
||||
#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
|
||||
#define uv__make_close_pending(h) uv__want_endgame((h)->loop, (h))
|
||||
#else
|
||||
#include "unix/internal.h"
|
||||
#endif
|
||||
|
50
src/idna.c
50
src/idna.c
@ -19,7 +19,9 @@
|
||||
|
||||
#include "uv.h"
|
||||
#include "idna.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
|
||||
static unsigned uv__utf8_decode1_slow(const char** p,
|
||||
const char* pe,
|
||||
@ -32,7 +34,7 @@ static unsigned uv__utf8_decode1_slow(const char** p,
|
||||
if (a > 0xF7)
|
||||
return -1;
|
||||
|
||||
switch (*p - pe) {
|
||||
switch (pe - *p) {
|
||||
default:
|
||||
if (a > 0xEF) {
|
||||
min = 0x10000;
|
||||
@ -62,6 +64,8 @@ static unsigned uv__utf8_decode1_slow(const char** p,
|
||||
a = 0;
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case 0:
|
||||
return -1; /* Invalid continuation byte. */
|
||||
}
|
||||
|
||||
@ -88,6 +92,8 @@ static unsigned uv__utf8_decode1_slow(const char** p,
|
||||
unsigned uv__utf8_decode1(const char** p, const char* pe) {
|
||||
unsigned a;
|
||||
|
||||
assert(*p < pe);
|
||||
|
||||
a = (unsigned char) *(*p)++;
|
||||
|
||||
if (a < 128)
|
||||
@ -96,9 +102,6 @@ unsigned uv__utf8_decode1(const char** p, const char* pe) {
|
||||
return uv__utf8_decode1_slow(p, pe, a);
|
||||
}
|
||||
|
||||
#define foreach_codepoint(c, p, pe) \
|
||||
for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;)
|
||||
|
||||
static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
char** d, char* de) {
|
||||
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
@ -121,15 +124,22 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
ss = s;
|
||||
todo = 0;
|
||||
|
||||
foreach_codepoint(c, &s, se) {
|
||||
/* Note: after this loop we've visited all UTF-8 characters and know
|
||||
* they're legal so we no longer need to check for decode errors.
|
||||
*/
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
|
||||
if (c == UINT_MAX)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (c < 128)
|
||||
h++;
|
||||
else if (c == (unsigned) -1)
|
||||
return UV_EINVAL;
|
||||
else
|
||||
todo++;
|
||||
}
|
||||
|
||||
/* Only write "xn--" when there are non-ASCII characters. */
|
||||
if (todo > 0) {
|
||||
if (*d < de) *(*d)++ = 'x';
|
||||
if (*d < de) *(*d)++ = 'n';
|
||||
@ -137,9 +147,13 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
if (*d < de) *(*d)++ = '-';
|
||||
}
|
||||
|
||||
/* Write ASCII characters. */
|
||||
x = 0;
|
||||
s = ss;
|
||||
foreach_codepoint(c, &s, se) {
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c > 127)
|
||||
continue;
|
||||
|
||||
@ -166,10 +180,15 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
while (todo > 0) {
|
||||
m = -1;
|
||||
s = ss;
|
||||
foreach_codepoint(c, &s, se)
|
||||
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c >= n)
|
||||
if (c < m)
|
||||
m = c;
|
||||
}
|
||||
|
||||
x = m - n;
|
||||
y = h + 1;
|
||||
@ -181,7 +200,10 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
n = m;
|
||||
|
||||
s = ss;
|
||||
foreach_codepoint(c, &s, se) {
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c < n)
|
||||
if (++delta == 0)
|
||||
return UV_E2BIG; /* Overflow. */
|
||||
@ -245,8 +267,6 @@ static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef foreach_codepoint
|
||||
|
||||
long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
const char* si;
|
||||
const char* st;
|
||||
@ -256,10 +276,14 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
|
||||
ds = d;
|
||||
|
||||
for (si = s; si < se; /* empty */) {
|
||||
si = s;
|
||||
while (si < se) {
|
||||
st = si;
|
||||
c = uv__utf8_decode1(&si, se);
|
||||
|
||||
if (c == UINT_MAX)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (c != '.')
|
||||
if (c != 0x3002) /* 。 */
|
||||
if (c != 0xFF0E) /* . */
|
||||
|
@ -141,8 +141,9 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {
|
||||
if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))
|
||||
*tp++ = ':';
|
||||
*tp++ = '\0';
|
||||
if (UV_E2BIG == uv__strscpy(dst, tmp, size))
|
||||
if ((size_t) (tp - tmp) > size)
|
||||
return UV_ENOSPC;
|
||||
uv__strscpy(dst, tmp, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ static int uv__random(void* buf, size_t buflen) {
|
||||
|
||||
#if defined(__PASE__)
|
||||
rc = uv__random_readpath("/dev/urandom", buf, buflen);
|
||||
#elif defined(_AIX)
|
||||
#elif defined(_AIX) || defined(__QNX__)
|
||||
rc = uv__random_readpath("/dev/random", buf, buflen);
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__) || \
|
||||
(defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
|
||||
|
@ -1,3 +1,24 @@
|
||||
/* 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 "strscpy.h"
|
||||
#include <limits.h> /* SSIZE_MAX */
|
||||
|
||||
|
@ -1,3 +1,24 @@
|
||||
/* 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_STRSCPY_H_
|
||||
#define UV_STRSCPY_H_
|
||||
|
||||
@ -7,7 +28,7 @@
|
||||
*/
|
||||
#include "uv.h"
|
||||
|
||||
/* Copies up to |n-1| bytes from |d| to |s| and always zero-terminates
|
||||
/* Copies up to |n-1| bytes from |s| to |d| and always zero-terminates
|
||||
* the result, except when |n==0|. Returns the number of bytes copied
|
||||
* or UV_E2BIG if |d| is too small.
|
||||
*
|
||||
|
@ -160,14 +160,20 @@ static void post(QUEUE* q, enum uv__work_kind kind) {
|
||||
}
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
UV_DESTRUCTOR(static void cleanup(void)) {
|
||||
#ifdef __MVS__
|
||||
/* TODO(itodorov) - zos: revisit when Woz compiler is available. */
|
||||
__attribute__((destructor))
|
||||
#endif
|
||||
void uv__threadpool_cleanup(void) {
|
||||
unsigned int i;
|
||||
|
||||
if (nthreads == 0)
|
||||
return;
|
||||
|
||||
#ifndef __MVS__
|
||||
/* TODO(gabylb) - zos: revisit when Woz compiler is available. */
|
||||
post(&exit_message, UV__WORK_CPU);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
if (uv_thread_join(threads + i))
|
||||
@ -182,7 +188,6 @@ UV_DESTRUCTOR(static void cleanup(void)) {
|
||||
threads = NULL;
|
||||
nthreads = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void init_threads(void) {
|
||||
|
16
src/timer.c
16
src/timer.c
@ -51,18 +51,14 @@ static int timer_less_than(const struct heap_node* ha,
|
||||
/* Compare start_id when both have the same timeout. start_id is
|
||||
* allocated with loop->timer_counter in uv_timer_start().
|
||||
*/
|
||||
if (a->start_id < b->start_id)
|
||||
return 1;
|
||||
if (b->start_id < a->start_id)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
return a->start_id < b->start_id;
|
||||
}
|
||||
|
||||
|
||||
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
|
||||
handle->timer_cb = NULL;
|
||||
handle->timeout = 0;
|
||||
handle->repeat = 0;
|
||||
return 0;
|
||||
}
|
||||
@ -135,6 +131,14 @@ uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_timer_get_due_in(const uv_timer_t* handle) {
|
||||
if (handle->loop->time >= handle->timeout)
|
||||
return 0;
|
||||
|
||||
return handle->timeout - handle->loop->time;
|
||||
}
|
||||
|
||||
|
||||
int uv__next_timeout(const uv_loop_t* loop) {
|
||||
const struct heap_node* heap_node;
|
||||
const uv_timer_t* handle;
|
||||
|
@ -22,42 +22,23 @@
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in6_var.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <utmp.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <sys/protosw.h>
|
||||
#include <procinfo.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <sys/pollset.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/mntctl.h>
|
||||
#include <sys/vmount.h>
|
||||
#include <limits.h>
|
||||
#include <strings.h>
|
||||
#include <sys/vnode.h>
|
||||
extern char* original_exepath;
|
||||
extern uv_mutex_t process_title_mutex;
|
||||
extern uv_once_t process_title_mutex_once;
|
||||
extern void init_process_title_mutex_once(void);
|
||||
|
||||
uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
uint64_t G = 1000000000;
|
||||
@ -78,80 +59,31 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
*/
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int res;
|
||||
char args[PATH_MAX];
|
||||
char abspath[PATH_MAX];
|
||||
size_t abspath_size;
|
||||
char args[UV__PATH_MAX];
|
||||
size_t cached_len;
|
||||
struct procsinfo pi;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_lock(&process_title_mutex);
|
||||
if (original_exepath != NULL) {
|
||||
cached_len = strlen(original_exepath);
|
||||
*size -= 1;
|
||||
if (*size > cached_len)
|
||||
*size = cached_len;
|
||||
memcpy(buffer, original_exepath, *size);
|
||||
buffer[*size] = '\0';
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
return 0;
|
||||
}
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
pi.pi_pid = getpid();
|
||||
res = getargs(&pi, sizeof(pi), args, sizeof(args));
|
||||
|
||||
if (res < 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
/*
|
||||
* Possibilities for args:
|
||||
* i) an absolute path such as: /home/user/myprojects/nodejs/node
|
||||
* ii) a relative path such as: ./node or ../myprojects/nodejs/node
|
||||
* iii) a bare filename such as "node", after exporting PATH variable
|
||||
* to its location.
|
||||
*/
|
||||
|
||||
/* Case i) and ii) absolute or relative paths */
|
||||
if (strchr(args, '/') != NULL) {
|
||||
if (realpath(args, abspath) != abspath)
|
||||
return UV__ERR(errno);
|
||||
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
/* Case iii). Search PATH environment variable */
|
||||
char trypath[PATH_MAX];
|
||||
char *clonedpath = NULL;
|
||||
char *token = NULL;
|
||||
char *path = getenv("PATH");
|
||||
|
||||
if (path == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
clonedpath = uv__strdup(path);
|
||||
if (clonedpath == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
token = strtok(clonedpath, ":");
|
||||
while (token != NULL) {
|
||||
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
|
||||
if (realpath(trypath, abspath) == abspath) {
|
||||
/* Check the match is executable */
|
||||
if (access(abspath, X_OK) == 0) {
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
uv__free(clonedpath);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
}
|
||||
uv__free(clonedpath);
|
||||
|
||||
/* Out of tokens (path entries), and no match found */
|
||||
return UV_EINVAL;
|
||||
}
|
||||
return uv__search_path(args, buffer, size);
|
||||
}
|
||||
|
@ -65,14 +65,15 @@
|
||||
#define RDWR_BUF_SIZE 4096
|
||||
#define EQ(a,b) (strcmp(a,b) == 0)
|
||||
|
||||
static uv_mutex_t process_title_mutex;
|
||||
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
||||
char* original_exepath = NULL;
|
||||
uv_mutex_t process_title_mutex;
|
||||
uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
||||
static void* args_mem = NULL;
|
||||
static char** process_argv = NULL;
|
||||
static int process_argc = 0;
|
||||
static char* process_title_ptr = NULL;
|
||||
|
||||
static void init_process_title_mutex_once(void) {
|
||||
void init_process_title_mutex_once(void) {
|
||||
uv_mutex_init(&process_title_mutex);
|
||||
}
|
||||
|
||||
@ -145,6 +146,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
int i;
|
||||
int rc;
|
||||
int add_failed;
|
||||
int user_timeout;
|
||||
int reset_timeout;
|
||||
|
||||
if (loop->nfds == 0) {
|
||||
assert(QUEUE_EMPTY(&loop->watcher_queue));
|
||||
@ -214,7 +217,21 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
base = loop->time;
|
||||
count = 48; /* Benchmarks suggest this gives the best throughput. */
|
||||
|
||||
if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
|
||||
reset_timeout = 1;
|
||||
user_timeout = timeout;
|
||||
timeout = 0;
|
||||
} else {
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* Only need to set the provider_entry_time if timeout != 0. The function
|
||||
* will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
|
||||
*/
|
||||
if (timeout != 0)
|
||||
uv__metrics_set_provider_entry_time(loop);
|
||||
|
||||
nfds = pollset_poll(loop->backend_fd,
|
||||
events,
|
||||
ARRAY_SIZE(events),
|
||||
@ -227,6 +244,15 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
SAVE_ERRNO(uv__update_time(loop));
|
||||
|
||||
if (nfds == 0) {
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
if (timeout > 0)
|
||||
goto update_timeout;
|
||||
}
|
||||
|
||||
assert(timeout != -1);
|
||||
return;
|
||||
}
|
||||
@ -236,6 +262,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
@ -280,16 +311,25 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
/* 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)
|
||||
if (w == &loop->signal_io_watcher) {
|
||||
have_signals = 1;
|
||||
else
|
||||
} else {
|
||||
uv__metrics_update_idle_time(loop);
|
||||
w->cb(loop, w, pe->revents);
|
||||
}
|
||||
|
||||
nevents++;
|
||||
}
|
||||
|
||||
if (have_signals != 0)
|
||||
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;
|
||||
@ -830,6 +870,7 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
char exepath[UV__PATH_MAX];
|
||||
char** new_argv;
|
||||
size_t size;
|
||||
char* s;
|
||||
@ -845,6 +886,15 @@ char** uv_setup_args(int argc, char** argv) {
|
||||
process_argv = argv;
|
||||
process_argc = argc;
|
||||
|
||||
/* Use argv[0] to determine value for uv_exepath(). */
|
||||
size = sizeof(exepath);
|
||||
if (uv__search_path(argv[0], exepath, &size) == 0) {
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_lock(&process_title_mutex);
|
||||
original_exepath = uv__strdup(exepath);
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
}
|
||||
|
||||
/* Calculate how much memory we need for the argv strings. */
|
||||
size = 0;
|
||||
for (i = 0; i < argc; i++)
|
||||
@ -875,6 +925,10 @@ char** uv_setup_args(int argc, char** argv) {
|
||||
int uv_set_process_title(const char* title) {
|
||||
char* new_title;
|
||||
|
||||
/* If uv_setup_args wasn't called or failed, we can't continue. */
|
||||
if (process_argv == NULL || args_mem == NULL)
|
||||
return UV_ENOBUFS;
|
||||
|
||||
/* We cannot free this pointer when libuv shuts down,
|
||||
* the process may still be using it.
|
||||
*/
|
||||
@ -908,6 +962,10 @@ int uv_get_process_title(char* buffer, size_t size) {
|
||||
if (buffer == NULL || size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
/* If uv_setup_args wasn't called, we can't continue. */
|
||||
if (process_argv == NULL)
|
||||
return UV_ENOBUFS;
|
||||
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_lock(&process_title_mutex);
|
||||
|
||||
@ -926,7 +984,7 @@ int uv_get_process_title(char* buffer, size_t size) {
|
||||
}
|
||||
|
||||
|
||||
UV_DESTRUCTOR(static void free_args_mem(void)) {
|
||||
void uv__process_title_cleanup(void) {
|
||||
uv__free(args_mem); /* Keep valgrind happy. */
|
||||
args_mem = NULL;
|
||||
}
|
||||
|
@ -1,712 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2013, Kenneth MacKay
|
||||
Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement #289016)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "uv/android-ifaddrs.h"
|
||||
#include "uv-common.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/if_packet.h>
|
||||
|
||||
typedef struct NetlinkList
|
||||
{
|
||||
struct NetlinkList *m_next;
|
||||
struct nlmsghdr *m_data;
|
||||
unsigned int m_size;
|
||||
} NetlinkList;
|
||||
|
||||
static int netlink_socket(pid_t *p_pid)
|
||||
{
|
||||
struct sockaddr_nl l_addr;
|
||||
socklen_t l_len;
|
||||
|
||||
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_len = sizeof(l_addr);
|
||||
if(getsockname(l_socket, (struct sockaddr *)&l_addr, &l_len) < 0)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
*p_pid = l_addr.nl_pid;
|
||||
|
||||
return l_socket;
|
||||
}
|
||||
|
||||
static int netlink_send(int p_socket, int p_request)
|
||||
{
|
||||
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
|
||||
|
||||
struct nlmsghdr *l_hdr;
|
||||
struct rtgenmsg *l_msg;
|
||||
struct sockaddr_nl l_addr;
|
||||
|
||||
memset(l_buffer, 0, sizeof(l_buffer));
|
||||
|
||||
l_hdr = (struct nlmsghdr *)l_buffer;
|
||||
l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
|
||||
|
||||
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
|
||||
l_hdr->nlmsg_type = p_request;
|
||||
l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
l_hdr->nlmsg_pid = 0;
|
||||
l_hdr->nlmsg_seq = p_socket;
|
||||
l_msg->rtgen_family = AF_UNSPEC;
|
||||
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
|
||||
}
|
||||
|
||||
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
|
||||
{
|
||||
struct sockaddr_nl l_addr;
|
||||
struct msghdr l_msg;
|
||||
|
||||
struct iovec l_iov;
|
||||
l_iov.iov_base = p_buffer;
|
||||
l_iov.iov_len = p_len;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int l_result;
|
||||
l_msg.msg_name = (void *)&l_addr;
|
||||
l_msg.msg_namelen = sizeof(l_addr);
|
||||
l_msg.msg_iov = &l_iov;
|
||||
l_msg.msg_iovlen = 1;
|
||||
l_msg.msg_control = NULL;
|
||||
l_msg.msg_controllen = 0;
|
||||
l_msg.msg_flags = 0;
|
||||
l_result = recvmsg(p_socket, &l_msg, 0);
|
||||
|
||||
if(l_result < 0)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Buffer was too small */
|
||||
if(l_msg.msg_flags & MSG_TRUNC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
}
|
||||
|
||||
static struct nlmsghdr *getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done)
|
||||
{
|
||||
size_t l_size = 4096;
|
||||
void *l_buffer = NULL;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int l_read;
|
||||
|
||||
uv__free(l_buffer);
|
||||
l_buffer = uv__malloc(l_size);
|
||||
if (l_buffer == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_read = netlink_recv(p_socket, l_buffer, l_size);
|
||||
*p_size = l_read;
|
||||
if(l_read == -2)
|
||||
{
|
||||
uv__free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
if(l_read >= 0)
|
||||
{
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
*p_done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
uv__free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return l_buffer;
|
||||
}
|
||||
|
||||
l_size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
|
||||
{
|
||||
NetlinkList *l_item = uv__malloc(sizeof(NetlinkList));
|
||||
if (l_item == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_item->m_next = NULL;
|
||||
l_item->m_data = p_data;
|
||||
l_item->m_size = p_size;
|
||||
return l_item;
|
||||
}
|
||||
|
||||
static void freeResultList(NetlinkList *p_list)
|
||||
{
|
||||
NetlinkList *l_cur;
|
||||
while(p_list)
|
||||
{
|
||||
l_cur = p_list;
|
||||
p_list = p_list->m_next;
|
||||
uv__free(l_cur->m_data);
|
||||
uv__free(l_cur);
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *getResultList(int p_socket, int p_request, pid_t p_pid)
|
||||
{
|
||||
int l_size;
|
||||
int l_done;
|
||||
NetlinkList *l_list;
|
||||
NetlinkList *l_end;
|
||||
|
||||
if(netlink_send(p_socket, p_request) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_list = NULL;
|
||||
l_end = NULL;
|
||||
|
||||
l_done = 0;
|
||||
while(!l_done)
|
||||
{
|
||||
NetlinkList *l_item;
|
||||
|
||||
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, p_pid, &l_size, &l_done);
|
||||
/* Error */
|
||||
if(!l_hdr)
|
||||
{
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_item = newListItem(l_hdr, l_size);
|
||||
if (!l_item)
|
||||
{
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
if(!l_list)
|
||||
{
|
||||
l_list = l_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_end->m_next = l_item;
|
||||
}
|
||||
l_end = l_item;
|
||||
}
|
||||
return l_list;
|
||||
}
|
||||
|
||||
static size_t maxSize(size_t a, size_t b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
return sizeof(struct sockaddr_in);
|
||||
case AF_INET6:
|
||||
return sizeof(struct sockaddr_in6);
|
||||
case AF_PACKET:
|
||||
return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
|
||||
default:
|
||||
return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_PACKET:
|
||||
memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
|
||||
((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
|
||||
break;
|
||||
default:
|
||||
memcpy(p_dest->sa_data, p_data, p_size);
|
||||
break;
|
||||
}
|
||||
p_dest->sa_family = p_family;
|
||||
}
|
||||
|
||||
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
|
||||
{
|
||||
if(!*p_resultList)
|
||||
{
|
||||
*p_resultList = p_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ifaddrs *l_cur = *p_resultList;
|
||||
while(l_cur->ifa_next)
|
||||
{
|
||||
l_cur = l_cur->ifa_next;
|
||||
}
|
||||
l_cur->ifa_next = p_entry;
|
||||
}
|
||||
}
|
||||
|
||||
static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
|
||||
{
|
||||
struct ifaddrs *l_entry;
|
||||
|
||||
char *l_index;
|
||||
char *l_name;
|
||||
char *l_addr;
|
||||
char *l_data;
|
||||
|
||||
struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
size_t l_dataSize = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
struct rtattr *l_rta;
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
|
||||
break;
|
||||
case IFLA_IFNAME:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
l_dataSize += NLMSG_ALIGN(l_rtaSize);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l_entry = uv__malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
|
||||
if (l_entry == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = "";
|
||||
|
||||
l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
l_name = l_index + sizeof(int);
|
||||
l_addr = l_name + l_nameSize;
|
||||
l_data = l_addr + l_addrSize;
|
||||
|
||||
/* Save the interface index so we can look it up when handling the
|
||||
* addresses.
|
||||
*/
|
||||
memcpy(l_index, &l_info->ifi_index, sizeof(int));
|
||||
|
||||
l_entry->ifa_flags = l_info->ifi_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
|
||||
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
|
||||
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
|
||||
if(l_rta->rta_type == IFLA_ADDRESS)
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFLA_IFNAME:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
memcpy(l_data, l_rtaData, l_rtaDataSize);
|
||||
l_entry->ifa_data = l_data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
|
||||
{
|
||||
int l_num = 0;
|
||||
struct ifaddrs *l_cur = *p_links;
|
||||
while(l_cur && l_num < p_numLinks)
|
||||
{
|
||||
char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs);
|
||||
int l_index;
|
||||
memcpy(&l_index, l_indexPtr, sizeof(int));
|
||||
if(l_index == p_index)
|
||||
{
|
||||
return l_cur;
|
||||
}
|
||||
|
||||
l_cur = l_cur->ifa_next;
|
||||
++l_num;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
|
||||
{
|
||||
struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
|
||||
struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
|
||||
int l_addedNetmask = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
struct rtattr *l_rta;
|
||||
struct ifaddrs *l_entry;
|
||||
|
||||
char *l_name;
|
||||
char *l_addr;
|
||||
|
||||
for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
if(l_info->ifa_family == AF_PACKET)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_LOCAL:
|
||||
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
|
||||
{
|
||||
/* Make room for netmask */
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
l_addedNetmask = 1;
|
||||
}
|
||||
break;
|
||||
case IFA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaDataSize + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l_entry = uv__malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
|
||||
if (l_entry == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = (l_interface ? l_interface->ifa_name : "");
|
||||
|
||||
l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
l_addr = l_name + l_nameSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifa_flags;
|
||||
if(l_interface)
|
||||
{
|
||||
l_entry->ifa_flags |= l_interface->ifa_flags;
|
||||
}
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_BROADCAST:
|
||||
case IFA_LOCAL:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
|
||||
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
if(l_info->ifa_family == AF_INET6)
|
||||
{
|
||||
if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
|
||||
{
|
||||
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apparently in a point-to-point network IFA_ADDRESS contains
|
||||
* the dest address and IFA_LOCAL contains the local address
|
||||
*/
|
||||
if(l_rta->rta_type == IFA_ADDRESS)
|
||||
{
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
}
|
||||
else if(l_rta->rta_type == IFA_LOCAL)
|
||||
{
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = l_entry->ifa_addr;
|
||||
}
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFA_LABEL:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
|
||||
{
|
||||
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
|
||||
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
|
||||
unsigned char l_mask[16] = {0};
|
||||
unsigned i;
|
||||
for(i=0; i<(l_prefix/8); ++i)
|
||||
{
|
||||
l_mask[i] = 0xff;
|
||||
}
|
||||
if(l_prefix % 8)
|
||||
{
|
||||
l_mask[i] = 0xff << (8 - (l_prefix % 8));
|
||||
}
|
||||
|
||||
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
|
||||
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
|
||||
{
|
||||
|
||||
int l_numLinks = 0;
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||
{
|
||||
if(interpretLink(l_hdr, p_resultList) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
++l_numLinks;
|
||||
}
|
||||
}
|
||||
}
|
||||
return l_numLinks;
|
||||
}
|
||||
|
||||
static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
|
||||
{
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWADDR)
|
||||
{
|
||||
if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
int l_socket;
|
||||
int l_result;
|
||||
int l_numLinks;
|
||||
pid_t l_pid;
|
||||
NetlinkList *l_linkResults;
|
||||
NetlinkList *l_addrResults;
|
||||
|
||||
if(!ifap)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*ifap = NULL;
|
||||
|
||||
l_socket = netlink_socket(&l_pid);
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_linkResults = getResultList(l_socket, RTM_GETLINK, l_pid);
|
||||
if(!l_linkResults)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_addrResults = getResultList(l_socket, RTM_GETADDR, l_pid);
|
||||
if(!l_addrResults)
|
||||
{
|
||||
close(l_socket);
|
||||
freeResultList(l_linkResults);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_result = 0;
|
||||
l_numLinks = interpretLinks(l_socket, l_pid, l_linkResults, ifap);
|
||||
if(l_numLinks == -1 || interpretAddrs(l_socket, l_pid, l_addrResults, ifap, l_numLinks) == -1)
|
||||
{
|
||||
l_result = -1;
|
||||
}
|
||||
|
||||
freeResultList(l_linkResults);
|
||||
freeResultList(l_addrResults);
|
||||
close(l_socket);
|
||||
return l_result;
|
||||
}
|
||||
|
||||
void freeifaddrs(struct ifaddrs *ifa)
|
||||
{
|
||||
struct ifaddrs *l_cur;
|
||||
while(ifa)
|
||||
{
|
||||
l_cur = ifa;
|
||||
ifa = ifa->ifa_next;
|
||||
uv__free(l_cur);
|
||||
}
|
||||
}
|
@ -32,6 +32,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h> /* sched_yield() */
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/eventfd.h>
|
||||
@ -81,20 +82,32 @@ int uv_async_send(uv_async_t* handle) {
|
||||
|
||||
/* Only call this from the event loop thread. */
|
||||
static int uv__async_spin(uv_async_t* handle) {
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
for (;;) {
|
||||
/* rc=0 -- handle is not pending.
|
||||
* rc=1 -- handle is pending, other thread is still working with it.
|
||||
* rc=2 -- handle is pending, other thread is done.
|
||||
/* 997 is not completely chosen at random. It's a prime number, acyclical
|
||||
* by nature, and should therefore hopefully dampen sympathetic resonance.
|
||||
*/
|
||||
rc = cmpxchgi(&handle->pending, 2, 0);
|
||||
for (i = 0; i < 997; i++) {
|
||||
/* rc=0 -- handle is not pending.
|
||||
* rc=1 -- handle is pending, other thread is still working with it.
|
||||
* rc=2 -- handle is pending, other thread is done.
|
||||
*/
|
||||
rc = cmpxchgi(&handle->pending, 2, 0);
|
||||
|
||||
if (rc != 1)
|
||||
return rc;
|
||||
if (rc != 1)
|
||||
return rc;
|
||||
|
||||
/* Other thread is busy with this handle, spin until it's done. */
|
||||
cpu_relax();
|
||||
/* Other thread is busy with this handle, spin until it's done. */
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
/* Yield the CPU. We may have preempted the other thread while it's
|
||||
* inside the critical section and if it's running on the same CPU
|
||||
* as us, we'll just burn CPU cycles until the end of our time slice.
|
||||
*/
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,7 +214,7 @@ static int uv__async_start(uv_loop_t* loop) {
|
||||
pipefd[0] = err;
|
||||
pipefd[1] = -1;
|
||||
#else
|
||||
err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
|
||||
err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE);
|
||||
if (err < 0)
|
||||
return err;
|
||||
#endif
|
||||
|
@ -52,7 +52,11 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
|
||||
|
||||
UV_UNUSED(static void cpu_relax(void)) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
__asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */
|
||||
__asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */
|
||||
#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||
__asm__ __volatile__ ("yield" ::: "memory");
|
||||
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
|
||||
__asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__)
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
@ -40,10 +40,10 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
||||
return 1;
|
||||
if (ent->ifa_addr == NULL)
|
||||
return 1;
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__)
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__)
|
||||
/*
|
||||
* If `exclude_type` is `UV__EXCLUDE_IFPHYS`, just see whether `sa_family`
|
||||
* equals to `AF_LINK` or not. Otherwise, the result depends on the operation
|
||||
* If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family`
|
||||
* equals `AF_LINK`. Otherwise, the result depends on the operating
|
||||
* system with `AF_LINK` or `PF_INET`.
|
||||
*/
|
||||
if (exclude_type == UV__EXCLUDE_IFPHYS)
|
||||
@ -53,7 +53,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
||||
defined(__HAIKU__)
|
||||
/*
|
||||
* On BSD getifaddrs returns information related to the raw underlying
|
||||
* devices. We're not interested in this information.
|
||||
* devices. We're not interested in this information.
|
||||
*/
|
||||
if (ent->ifa_addr->sa_family == AF_LINK)
|
||||
return 1;
|
||||
@ -69,7 +69,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
struct ifaddrs* addrs;
|
||||
struct ifaddrs* ent;
|
||||
uv_interface_address_t* address;
|
||||
#if !(defined(__CYGWIN__) || defined(__MSYS__))
|
||||
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
|
||||
int i;
|
||||
#endif
|
||||
|
||||
@ -113,7 +113,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
|
||||
}
|
||||
|
||||
if (ent->ifa_netmask->sa_family == AF_INET6) {
|
||||
if (ent->ifa_netmask == NULL) {
|
||||
memset(&address->netmask, 0, sizeof(address->netmask));
|
||||
} else if (ent->ifa_netmask->sa_family == AF_INET6) {
|
||||
address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
|
||||
} else {
|
||||
address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
|
||||
@ -124,7 +126,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
address++;
|
||||
}
|
||||
|
||||
#if !(defined(__CYGWIN__) || defined(__MSYS__))
|
||||
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
|
||||
/* Fill in physical addresses for each interface */
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
|
||||
|
@ -37,6 +37,12 @@ static void init_process_title_mutex_once(void) {
|
||||
}
|
||||
|
||||
|
||||
void uv__process_title_cleanup(void) {
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_destroy(&process_title_mutex);
|
||||
}
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
process_title = argc > 0 ? uv__strdup(argv[0]) : NULL;
|
||||
return argv;
|
||||
|
305
src/unix/core.c
305
src/unix/core.c
@ -71,7 +71,7 @@ extern char** environ;
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/filio.h>
|
||||
# include <sys/wait.h>
|
||||
# if defined(__FreeBSD__) || defined(__linux__)
|
||||
# if defined(__FreeBSD__)
|
||||
# define uv__accept4 accept4
|
||||
# endif
|
||||
# if defined(__NetBSD__)
|
||||
@ -79,25 +79,27 @@ extern char** environ;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
|
||||
# include <dlfcn.h> /* for dlsym */
|
||||
#endif
|
||||
|
||||
#if defined(__MVS__)
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/syscall.h>
|
||||
# include <sched.h>
|
||||
# include <sys/syscall.h>
|
||||
# define uv__accept4 accept4
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__)
|
||||
# include <sanitizer/linux_syscall_hooks.h>
|
||||
#endif
|
||||
|
||||
static int uv__run_pending(uv_loop_t* loop);
|
||||
|
||||
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
|
||||
STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec));
|
||||
STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->base) ==
|
||||
STATIC_ASSERT(sizeof(((uv_buf_t*) 0)->base) ==
|
||||
sizeof(((struct iovec*) 0)->iov_base));
|
||||
STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->len) ==
|
||||
STATIC_ASSERT(sizeof(((uv_buf_t*) 0)->len) ==
|
||||
sizeof(((struct iovec*) 0)->iov_len));
|
||||
STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base));
|
||||
STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len));
|
||||
@ -219,15 +221,23 @@ int uv__getiovmax(void) {
|
||||
#if defined(IOV_MAX)
|
||||
return IOV_MAX;
|
||||
#elif defined(_SC_IOV_MAX)
|
||||
static int iovmax = -1;
|
||||
if (iovmax == -1) {
|
||||
iovmax = sysconf(_SC_IOV_MAX);
|
||||
/* On some embedded devices (arm-linux-uclibc based ip camera),
|
||||
* sysconf(_SC_IOV_MAX) can not get the correct value. The return
|
||||
* value is -1 and the errno is EINPROGRESS. Degrade the value to 1.
|
||||
*/
|
||||
if (iovmax == -1) iovmax = 1;
|
||||
}
|
||||
static int iovmax_cached = -1;
|
||||
int iovmax;
|
||||
|
||||
iovmax = uv__load_relaxed(&iovmax_cached);
|
||||
if (iovmax != -1)
|
||||
return iovmax;
|
||||
|
||||
/* On some embedded devices (arm-linux-uclibc based ip camera),
|
||||
* sysconf(_SC_IOV_MAX) can not get the correct value. The return
|
||||
* value is -1 and the errno is EINPROGRESS. Degrade the value to 1.
|
||||
*/
|
||||
iovmax = sysconf(_SC_IOV_MAX);
|
||||
if (iovmax == -1)
|
||||
iovmax = 1;
|
||||
|
||||
uv__store_relaxed(&iovmax_cached, iovmax);
|
||||
|
||||
return iovmax;
|
||||
#else
|
||||
return 1024;
|
||||
@ -325,35 +335,36 @@ int uv_backend_fd(const uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
|
||||
int uv_backend_timeout(const uv_loop_t* loop) {
|
||||
if (loop->stop_flag != 0)
|
||||
return 0;
|
||||
|
||||
if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
|
||||
return 0;
|
||||
|
||||
if (!QUEUE_EMPTY(&loop->idle_handles))
|
||||
return 0;
|
||||
|
||||
if (!QUEUE_EMPTY(&loop->pending_queue))
|
||||
return 0;
|
||||
|
||||
if (loop->closing_handles)
|
||||
return 0;
|
||||
|
||||
return uv__next_timeout(loop);
|
||||
}
|
||||
|
||||
|
||||
static int uv__loop_alive(const uv_loop_t* loop) {
|
||||
return uv__has_active_handles(loop) ||
|
||||
uv__has_active_reqs(loop) ||
|
||||
!QUEUE_EMPTY(&loop->pending_queue) ||
|
||||
loop->closing_handles != NULL;
|
||||
}
|
||||
|
||||
|
||||
static int uv__backend_timeout(const uv_loop_t* loop) {
|
||||
if (loop->stop_flag == 0 &&
|
||||
/* uv__loop_alive(loop) && */
|
||||
(uv__has_active_handles(loop) || uv__has_active_reqs(loop)) &&
|
||||
QUEUE_EMPTY(&loop->pending_queue) &&
|
||||
QUEUE_EMPTY(&loop->idle_handles) &&
|
||||
loop->closing_handles == NULL)
|
||||
return uv__next_timeout(loop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_backend_timeout(const uv_loop_t* loop) {
|
||||
if (QUEUE_EMPTY(&loop->watcher_queue))
|
||||
return uv__backend_timeout(loop);
|
||||
/* Need to call uv_run to update the backend fd state. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_loop_alive(const uv_loop_t* loop) {
|
||||
return uv__loop_alive(loop);
|
||||
return uv__loop_alive(loop);
|
||||
}
|
||||
|
||||
|
||||
@ -375,9 +386,17 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
|
||||
|
||||
timeout = 0;
|
||||
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
|
||||
timeout = uv_backend_timeout(loop);
|
||||
timeout = uv__backend_timeout(loop);
|
||||
|
||||
uv__io_poll(loop, timeout);
|
||||
|
||||
/* 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
|
||||
* the timeout == 0) or was already updated b/c an event was received.
|
||||
*/
|
||||
uv__metrics_update_idle_time(loop);
|
||||
|
||||
uv__run_check(loop);
|
||||
uv__run_closing_handles(loop);
|
||||
|
||||
@ -518,7 +537,7 @@ int uv__close_nocancel(int fd) {
|
||||
#if defined(__APPLE__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
|
||||
#if defined(__LP64__) || defined(TARGET_OS_IPHONE)
|
||||
#if defined(__LP64__) || TARGET_OS_IPHONE
|
||||
extern int close$NOCANCEL(int);
|
||||
return close$NOCANCEL(fd);
|
||||
#else
|
||||
@ -526,7 +545,13 @@ int uv__close_nocancel(int fd) {
|
||||
return close$NOCANCEL$UNIX2003(fd);
|
||||
#endif
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(__linux__)
|
||||
#elif defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__)
|
||||
long rc;
|
||||
__sanitizer_syscall_pre_close(fd);
|
||||
rc = syscall(SYS_close, fd);
|
||||
__sanitizer_syscall_post_close(rc, fd);
|
||||
return rc;
|
||||
#elif defined(__linux__) && !defined(__SANITIZE_THREAD__)
|
||||
return syscall(SYS_close, fd);
|
||||
#else
|
||||
return close(fd);
|
||||
@ -561,7 +586,7 @@ int uv__close(int fd) {
|
||||
return uv__close_nocheckstdio(fd);
|
||||
}
|
||||
|
||||
|
||||
#if UV__NONBLOCK_IS_IOCTL
|
||||
int uv__nonblock_ioctl(int fd, int set) {
|
||||
int r;
|
||||
|
||||
@ -574,21 +599,6 @@ int uv__nonblock_ioctl(int fd, int set) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__)
|
||||
int uv__cloexec_ioctl(int fd, int set) {
|
||||
int r;
|
||||
|
||||
do
|
||||
r = ioctl(fd, set ? FIOCLEX : FIONCLEX);
|
||||
while (r == -1 && errno == EINTR);
|
||||
|
||||
if (r)
|
||||
return UV__ERR(errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -623,25 +633,13 @@ int uv__nonblock_fcntl(int fd, int set) {
|
||||
}
|
||||
|
||||
|
||||
int uv__cloexec_fcntl(int fd, int set) {
|
||||
int uv__cloexec(int fd, int set) {
|
||||
int flags;
|
||||
int r;
|
||||
|
||||
do
|
||||
r = fcntl(fd, F_GETFD);
|
||||
while (r == -1 && errno == EINTR);
|
||||
|
||||
if (r == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
/* Bail out now if already set/clear. */
|
||||
if (!!(r & FD_CLOEXEC) == !!set)
|
||||
return 0;
|
||||
|
||||
flags = 0;
|
||||
if (set)
|
||||
flags = r | FD_CLOEXEC;
|
||||
else
|
||||
flags = r & ~FD_CLOEXEC;
|
||||
flags = FD_CLOEXEC;
|
||||
|
||||
do
|
||||
r = fcntl(fd, F_SETFD, flags);
|
||||
@ -661,7 +659,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
|
||||
int* end;
|
||||
#if defined(__linux__)
|
||||
static int no_msg_cmsg_cloexec;
|
||||
if (no_msg_cmsg_cloexec == 0) {
|
||||
if (0 == uv__load_relaxed(&no_msg_cmsg_cloexec)) {
|
||||
rc = recvmsg(fd, msg, flags | 0x40000000); /* MSG_CMSG_CLOEXEC */
|
||||
if (rc != -1)
|
||||
return rc;
|
||||
@ -670,7 +668,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
|
||||
rc = recvmsg(fd, msg, flags);
|
||||
if (rc == -1)
|
||||
return UV__ERR(errno);
|
||||
no_msg_cmsg_cloexec = 1;
|
||||
uv__store_relaxed(&no_msg_cmsg_cloexec, 1);
|
||||
} else {
|
||||
rc = recvmsg(fd, msg, flags);
|
||||
}
|
||||
@ -834,8 +832,8 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) {
|
||||
}
|
||||
|
||||
nwatchers = next_power_of_two(len + 2) - 2;
|
||||
watchers = uv__realloc(loop->watchers,
|
||||
(nwatchers + 2) * sizeof(loop->watchers[0]));
|
||||
watchers = uv__reallocf(loop->watchers,
|
||||
(nwatchers + 2) * sizeof(loop->watchers[0]));
|
||||
|
||||
if (watchers == NULL)
|
||||
abort();
|
||||
@ -912,13 +910,12 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
if (w->pevents == 0) {
|
||||
QUEUE_REMOVE(&w->watcher_queue);
|
||||
QUEUE_INIT(&w->watcher_queue);
|
||||
w->events = 0;
|
||||
|
||||
if (loop->watchers[w->fd] != NULL) {
|
||||
assert(loop->watchers[w->fd] == w);
|
||||
if (w == loop->watchers[w->fd]) {
|
||||
assert(loop->nfds > 0);
|
||||
loop->watchers[w->fd] = NULL;
|
||||
loop->nfds--;
|
||||
w->events = 0;
|
||||
}
|
||||
}
|
||||
else if (QUEUE_EMPTY(&w->watcher_queue))
|
||||
@ -1015,6 +1012,32 @@ int uv__open_cloexec(const char* path, int flags) {
|
||||
}
|
||||
|
||||
|
||||
int uv__slurp(const char* filename, char* buf, size_t len) {
|
||||
ssize_t n;
|
||||
int fd;
|
||||
|
||||
assert(len > 0);
|
||||
|
||||
fd = uv__open_cloexec(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
do
|
||||
n = read(fd, buf, len - 1);
|
||||
while (n == -1 && errno == EINTR);
|
||||
|
||||
if (uv__close_nocheckstdio(fd))
|
||||
abort();
|
||||
|
||||
if (n < 0)
|
||||
return UV__ERR(errno);
|
||||
|
||||
buf[n] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv__dup2_cloexec(int oldfd, int newfd) {
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__)
|
||||
int r;
|
||||
@ -1141,13 +1164,6 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
size_t shell_size;
|
||||
long initsize;
|
||||
int r;
|
||||
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
|
||||
int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**);
|
||||
|
||||
getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
|
||||
if (getpwuid_r == NULL)
|
||||
return UV_ENOSYS;
|
||||
#endif
|
||||
|
||||
if (pwd == NULL)
|
||||
return UV_EINVAL;
|
||||
@ -1169,7 +1185,9 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
if (buf == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
|
||||
do
|
||||
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
|
||||
while (r == EINTR);
|
||||
|
||||
if (r != ERANGE)
|
||||
break;
|
||||
@ -1179,7 +1197,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
|
||||
if (r != 0) {
|
||||
uv__free(buf);
|
||||
return -r;
|
||||
return UV__ERR(r);
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
@ -1257,7 +1275,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) {
|
||||
|
||||
*envitems = uv__calloc(i, sizeof(**envitems));
|
||||
|
||||
if (envitems == NULL)
|
||||
if (*envitems == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
for (j = 0, cnt = 0; j < i; j++) {
|
||||
@ -1530,3 +1548,112 @@ void uv_sleep(unsigned int msec) {
|
||||
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
int uv__search_path(const char* prog, char* buf, size_t* buflen) {
|
||||
char abspath[UV__PATH_MAX];
|
||||
size_t abspath_size;
|
||||
char trypath[UV__PATH_MAX];
|
||||
char* cloned_path;
|
||||
char* path_env;
|
||||
char* token;
|
||||
|
||||
if (buf == NULL || buflen == NULL || *buflen == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
/*
|
||||
* Possibilities for prog:
|
||||
* i) an absolute path such as: /home/user/myprojects/nodejs/node
|
||||
* ii) a relative path such as: ./node or ../myprojects/nodejs/node
|
||||
* iii) a bare filename such as "node", after exporting PATH variable
|
||||
* to its location.
|
||||
*/
|
||||
|
||||
/* Case i) and ii) absolute or relative paths */
|
||||
if (strchr(prog, '/') != NULL) {
|
||||
if (realpath(prog, abspath) != abspath)
|
||||
return UV__ERR(errno);
|
||||
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*buflen -= 1;
|
||||
if (*buflen > abspath_size)
|
||||
*buflen = abspath_size;
|
||||
|
||||
memcpy(buf, abspath, *buflen);
|
||||
buf[*buflen] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Case iii). Search PATH environment variable */
|
||||
cloned_path = NULL;
|
||||
token = NULL;
|
||||
path_env = getenv("PATH");
|
||||
|
||||
if (path_env == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
cloned_path = uv__strdup(path_env);
|
||||
if (cloned_path == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
token = strtok(cloned_path, ":");
|
||||
while (token != NULL) {
|
||||
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, prog);
|
||||
if (realpath(trypath, abspath) == abspath) {
|
||||
/* Check the match is executable */
|
||||
if (access(abspath, X_OK) == 0) {
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*buflen -= 1;
|
||||
if (*buflen > abspath_size)
|
||||
*buflen = abspath_size;
|
||||
|
||||
memcpy(buf, abspath, *buflen);
|
||||
buf[*buflen] = '\0';
|
||||
|
||||
uv__free(cloned_path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
}
|
||||
uv__free(cloned_path);
|
||||
|
||||
/* Out of tokens (path entries), and no match found */
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
|
||||
unsigned int uv_available_parallelism(void) {
|
||||
#ifdef __linux__
|
||||
cpu_set_t set;
|
||||
long rc;
|
||||
|
||||
memset(&set, 0, sizeof(set));
|
||||
|
||||
/* sysconf(_SC_NPROCESSORS_ONLN) in musl calls sched_getaffinity() but in
|
||||
* glibc it's... complicated... so for consistency try sched_getaffinity()
|
||||
* before falling back to sysconf(_SC_NPROCESSORS_ONLN).
|
||||
*/
|
||||
if (0 == sched_getaffinity(0, sizeof(set), &set))
|
||||
rc = CPU_COUNT(&set);
|
||||
else
|
||||
rc = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
if (rc < 1)
|
||||
rc = 1;
|
||||
|
||||
return (unsigned) rc;
|
||||
#elif defined(__MVS__)
|
||||
return 1; /* TODO(bnoordhuis) Read from CSD_NUMBER_ONLINE_CPUS? */
|
||||
#else /* __linux__ */
|
||||
long rc;
|
||||
|
||||
rc = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (rc < 1)
|
||||
rc = 1;
|
||||
|
||||
return (unsigned) rc;
|
||||
#endif /* __linux__ */
|
||||
}
|
||||
|
@ -30,8 +30,7 @@
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
# include <CoreFoundation/CoreFoundation.h>
|
||||
# include <ApplicationServices/ApplicationServices.h>
|
||||
#include "darwin-stub.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
113
src/unix/darwin-stub.h
Normal file
113
src/unix/darwin-stub.h
Normal file
@ -0,0 +1,113 @@
|
||||
/* 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_DARWIN_STUB_H_
|
||||
#define UV_DARWIN_STUB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct CFArrayCallBacks;
|
||||
struct CFRunLoopSourceContext;
|
||||
struct FSEventStreamContext;
|
||||
struct CFRange;
|
||||
|
||||
typedef double CFAbsoluteTime;
|
||||
typedef double CFTimeInterval;
|
||||
typedef int FSEventStreamEventFlags;
|
||||
typedef int OSStatus;
|
||||
typedef long CFIndex;
|
||||
typedef struct CFArrayCallBacks CFArrayCallBacks;
|
||||
typedef struct CFRunLoopSourceContext CFRunLoopSourceContext;
|
||||
typedef struct FSEventStreamContext FSEventStreamContext;
|
||||
typedef uint32_t FSEventStreamCreateFlags;
|
||||
typedef uint64_t FSEventStreamEventId;
|
||||
typedef unsigned CFStringEncoding;
|
||||
typedef void* CFAllocatorRef;
|
||||
typedef void* CFArrayRef;
|
||||
typedef void* CFBundleRef;
|
||||
typedef void* CFDataRef;
|
||||
typedef void* CFDictionaryRef;
|
||||
typedef void* CFMutableDictionaryRef;
|
||||
typedef struct CFRange CFRange;
|
||||
typedef void* CFRunLoopRef;
|
||||
typedef void* CFRunLoopSourceRef;
|
||||
typedef void* CFStringRef;
|
||||
typedef void* CFTypeRef;
|
||||
typedef void* FSEventStreamRef;
|
||||
|
||||
typedef uint32_t IOOptionBits;
|
||||
typedef unsigned int io_iterator_t;
|
||||
typedef unsigned int io_object_t;
|
||||
typedef unsigned int io_service_t;
|
||||
typedef unsigned int io_registry_entry_t;
|
||||
|
||||
|
||||
typedef void (*FSEventStreamCallback)(const FSEventStreamRef,
|
||||
void*,
|
||||
size_t,
|
||||
void*,
|
||||
const FSEventStreamEventFlags*,
|
||||
const FSEventStreamEventId*);
|
||||
|
||||
struct CFRunLoopSourceContext {
|
||||
CFIndex version;
|
||||
void* info;
|
||||
void* pad[7];
|
||||
void (*perform)(void*);
|
||||
};
|
||||
|
||||
struct FSEventStreamContext {
|
||||
CFIndex version;
|
||||
void* info;
|
||||
void* pad[3];
|
||||
};
|
||||
|
||||
struct CFRange {
|
||||
CFIndex location;
|
||||
CFIndex length;
|
||||
};
|
||||
|
||||
static const CFStringEncoding kCFStringEncodingUTF8 = 0x8000100;
|
||||
static const OSStatus noErr = 0;
|
||||
|
||||
static const FSEventStreamEventId kFSEventStreamEventIdSinceNow = -1;
|
||||
|
||||
static const int kFSEventStreamCreateFlagNoDefer = 2;
|
||||
static const int kFSEventStreamCreateFlagFileEvents = 16;
|
||||
|
||||
static const int kFSEventStreamEventFlagEventIdsWrapped = 8;
|
||||
static const int kFSEventStreamEventFlagHistoryDone = 16;
|
||||
static const int kFSEventStreamEventFlagItemChangeOwner = 0x4000;
|
||||
static const int kFSEventStreamEventFlagItemCreated = 0x100;
|
||||
static const int kFSEventStreamEventFlagItemFinderInfoMod = 0x2000;
|
||||
static const int kFSEventStreamEventFlagItemInodeMetaMod = 0x400;
|
||||
static const int kFSEventStreamEventFlagItemIsDir = 0x20000;
|
||||
static const int kFSEventStreamEventFlagItemModified = 0x1000;
|
||||
static const int kFSEventStreamEventFlagItemRemoved = 0x200;
|
||||
static const int kFSEventStreamEventFlagItemRenamed = 0x800;
|
||||
static const int kFSEventStreamEventFlagItemXattrMod = 0x8000;
|
||||
static const int kFSEventStreamEventFlagKernelDropped = 4;
|
||||
static const int kFSEventStreamEventFlagMount = 64;
|
||||
static const int kFSEventStreamEventFlagRootChanged = 32;
|
||||
static const int kFSEventStreamEventFlagUnmount = 128;
|
||||
static const int kFSEventStreamEventFlagUserDropped = 2;
|
||||
|
||||
#endif /* UV_DARWIN_STUB_H_ */
|
@ -25,6 +25,7 @@
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
|
||||
@ -32,6 +33,13 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <unistd.h> /* sysconf */
|
||||
|
||||
#include "darwin-stub.h"
|
||||
|
||||
static uv_once_t once = UV_ONCE_INIT;
|
||||
static uint64_t (*time_func)(void);
|
||||
static mach_timebase_info_data_t timebase;
|
||||
|
||||
typedef unsigned char UInt8;
|
||||
|
||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||
loop->cf_state = NULL;
|
||||
@ -48,15 +56,19 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
static mach_timebase_info_data_t info;
|
||||
|
||||
if ((ACCESS_ONCE(uint32_t, info.numer) == 0 ||
|
||||
ACCESS_ONCE(uint32_t, info.denom) == 0) &&
|
||||
mach_timebase_info(&info) != KERN_SUCCESS)
|
||||
static void uv__hrtime_init_once(void) {
|
||||
if (KERN_SUCCESS != mach_timebase_info(&timebase))
|
||||
abort();
|
||||
|
||||
return mach_absolute_time() * info.numer / info.denom;
|
||||
time_func = (uint64_t (*)(void)) dlsym(RTLD_DEFAULT, "mach_continuous_time");
|
||||
if (time_func == NULL)
|
||||
time_func = mach_absolute_time;
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
uv_once(&once, uv__hrtime_init_once);
|
||||
return time_func() * timebase.numer / timebase.denom;
|
||||
}
|
||||
|
||||
|
||||
@ -171,17 +183,159 @@ int uv_uptime(double* uptime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uv__get_cpu_speed(uint64_t* speed) {
|
||||
/* IOKit */
|
||||
void (*pIOObjectRelease)(io_object_t);
|
||||
kern_return_t (*pIOMasterPort)(mach_port_t, mach_port_t*);
|
||||
CFMutableDictionaryRef (*pIOServiceMatching)(const char*);
|
||||
kern_return_t (*pIOServiceGetMatchingServices)(mach_port_t,
|
||||
CFMutableDictionaryRef,
|
||||
io_iterator_t*);
|
||||
io_service_t (*pIOIteratorNext)(io_iterator_t);
|
||||
CFTypeRef (*pIORegistryEntryCreateCFProperty)(io_registry_entry_t,
|
||||
CFStringRef,
|
||||
CFAllocatorRef,
|
||||
IOOptionBits);
|
||||
|
||||
/* CoreFoundation */
|
||||
CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
|
||||
const char*,
|
||||
CFStringEncoding);
|
||||
CFStringEncoding (*pCFStringGetSystemEncoding)(void);
|
||||
UInt8 *(*pCFDataGetBytePtr)(CFDataRef);
|
||||
CFIndex (*pCFDataGetLength)(CFDataRef);
|
||||
void (*pCFDataGetBytes)(CFDataRef, CFRange, UInt8*);
|
||||
void (*pCFRelease)(CFTypeRef);
|
||||
|
||||
void* core_foundation_handle;
|
||||
void* iokit_handle;
|
||||
int err;
|
||||
|
||||
kern_return_t kr;
|
||||
mach_port_t mach_port;
|
||||
io_iterator_t it;
|
||||
io_object_t service;
|
||||
|
||||
mach_port = 0;
|
||||
|
||||
err = UV_ENOENT;
|
||||
core_foundation_handle = dlopen("/System/Library/Frameworks/"
|
||||
"CoreFoundation.framework/"
|
||||
"CoreFoundation",
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
iokit_handle = dlopen("/System/Library/Frameworks/IOKit.framework/"
|
||||
"IOKit",
|
||||
RTLD_LAZY | RTLD_LOCAL);
|
||||
|
||||
if (core_foundation_handle == NULL || iokit_handle == NULL)
|
||||
goto out;
|
||||
|
||||
#define V(handle, symbol) \
|
||||
do { \
|
||||
*(void **)(&p ## symbol) = dlsym((handle), #symbol); \
|
||||
if (p ## symbol == NULL) \
|
||||
goto out; \
|
||||
} \
|
||||
while (0)
|
||||
V(iokit_handle, IOMasterPort);
|
||||
V(iokit_handle, IOServiceMatching);
|
||||
V(iokit_handle, IOServiceGetMatchingServices);
|
||||
V(iokit_handle, IOIteratorNext);
|
||||
V(iokit_handle, IOObjectRelease);
|
||||
V(iokit_handle, IORegistryEntryCreateCFProperty);
|
||||
V(core_foundation_handle, CFStringCreateWithCString);
|
||||
V(core_foundation_handle, CFStringGetSystemEncoding);
|
||||
V(core_foundation_handle, CFDataGetBytePtr);
|
||||
V(core_foundation_handle, CFDataGetLength);
|
||||
V(core_foundation_handle, CFDataGetBytes);
|
||||
V(core_foundation_handle, CFRelease);
|
||||
#undef V
|
||||
|
||||
#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
|
||||
|
||||
kr = pIOMasterPort(MACH_PORT_NULL, &mach_port);
|
||||
assert(kr == KERN_SUCCESS);
|
||||
CFMutableDictionaryRef classes_to_match
|
||||
= pIOServiceMatching("IOPlatformDevice");
|
||||
kr = pIOServiceGetMatchingServices(mach_port, classes_to_match, &it);
|
||||
assert(kr == KERN_SUCCESS);
|
||||
service = pIOIteratorNext(it);
|
||||
|
||||
CFStringRef device_type_str = S("device_type");
|
||||
CFStringRef clock_frequency_str = S("clock-frequency");
|
||||
|
||||
while (service != 0) {
|
||||
CFDataRef data;
|
||||
data = pIORegistryEntryCreateCFProperty(service,
|
||||
device_type_str,
|
||||
NULL,
|
||||
0);
|
||||
if (data) {
|
||||
const UInt8* raw = pCFDataGetBytePtr(data);
|
||||
if (strncmp((char*)raw, "cpu", 3) == 0 ||
|
||||
strncmp((char*)raw, "processor", 9) == 0) {
|
||||
CFDataRef freq_ref;
|
||||
freq_ref = pIORegistryEntryCreateCFProperty(service,
|
||||
clock_frequency_str,
|
||||
NULL,
|
||||
0);
|
||||
if (freq_ref) {
|
||||
const UInt8* freq_ref_ptr = pCFDataGetBytePtr(freq_ref);
|
||||
CFIndex len = pCFDataGetLength(freq_ref);
|
||||
if (len == 8)
|
||||
memcpy(speed, freq_ref_ptr, 8);
|
||||
else if (len == 4) {
|
||||
uint32_t v;
|
||||
memcpy(&v, freq_ref_ptr, 4);
|
||||
*speed = v;
|
||||
} else {
|
||||
*speed = 0;
|
||||
}
|
||||
|
||||
pCFRelease(freq_ref);
|
||||
pCFRelease(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pCFRelease(data);
|
||||
}
|
||||
|
||||
service = pIOIteratorNext(it);
|
||||
}
|
||||
|
||||
pIOObjectRelease(it);
|
||||
|
||||
err = 0;
|
||||
|
||||
if (device_type_str != NULL)
|
||||
pCFRelease(device_type_str);
|
||||
if (clock_frequency_str != NULL)
|
||||
pCFRelease(clock_frequency_str);
|
||||
|
||||
out:
|
||||
if (core_foundation_handle != NULL)
|
||||
dlclose(core_foundation_handle);
|
||||
|
||||
if (iokit_handle != NULL)
|
||||
dlclose(iokit_handle);
|
||||
|
||||
mach_port_deallocate(mach_task_self(), mach_port);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
|
||||
multiplier = ((uint64_t)1000L / ticks);
|
||||
char model[512];
|
||||
uint64_t cpuspeed;
|
||||
size_t size;
|
||||
unsigned int i;
|
||||
natural_t numcpus;
|
||||
mach_msg_type_number_t msg_type;
|
||||
processor_cpu_load_info_data_t *info;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
uint64_t cpuspeed;
|
||||
int err;
|
||||
|
||||
size = sizeof(model);
|
||||
if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) &&
|
||||
@ -189,9 +343,9 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
|
||||
size = sizeof(cpuspeed);
|
||||
if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0))
|
||||
return UV__ERR(errno);
|
||||
err = uv__get_cpu_speed(&cpuspeed);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
|
||||
(processor_info_array_t*)&info,
|
||||
|
@ -53,7 +53,7 @@ void uv_dlclose(uv_lib_t* lib) {
|
||||
int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
|
||||
dlerror(); /* Reset error status. */
|
||||
*ptr = dlsym(lib->handle, name);
|
||||
return uv__dlerror(lib);
|
||||
return *ptr ? 0 : uv__dlerror(lib);
|
||||
}
|
||||
|
||||
|
||||
|
422
src/unix/epoll.c
Normal file
422
src/unix/epoll.c
Normal file
@ -0,0 +1,422 @@
|
||||
/* Copyright libuv contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include <errno.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
int uv__epoll_init(uv_loop_t* loop) {
|
||||
int fd;
|
||||
fd = epoll_create1(O_CLOEXEC);
|
||||
|
||||
/* epoll_create1() can fail either because it's not implemented (old kernel)
|
||||
* or because it doesn't understand the O_CLOEXEC flag.
|
||||
*/
|
||||
if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
|
||||
fd = epoll_create(256);
|
||||
|
||||
if (fd != -1)
|
||||
uv__cloexec(fd, 1);
|
||||
}
|
||||
|
||||
loop->backend_fd = fd;
|
||||
if (fd == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
||||
struct epoll_event* events;
|
||||
struct epoll_event dummy;
|
||||
uintptr_t i;
|
||||
uintptr_t nfds;
|
||||
|
||||
assert(loop->watchers != NULL);
|
||||
assert(fd >= 0);
|
||||
|
||||
events = (struct epoll_event*) loop->watchers[loop->nwatchers];
|
||||
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
|
||||
if (events != NULL)
|
||||
/* Invalidate events with same file descriptor */
|
||||
for (i = 0; i < nfds; i++)
|
||||
if (events[i].data.fd == fd)
|
||||
events[i].data.fd = -1;
|
||||
|
||||
/* Remove the file descriptor from the epoll.
|
||||
* This avoids a problem where the same file description remains open
|
||||
* in another process, causing repeated junk epoll events.
|
||||
*
|
||||
* We pass in a dummy epoll_event, to work around a bug in old kernels.
|
||||
*/
|
||||
if (loop->backend_fd >= 0) {
|
||||
/* Work around a bug in kernels 3.10 to 3.19 where passing a struct that
|
||||
* has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
|
||||
*/
|
||||
memset(&dummy, 0, sizeof(dummy));
|
||||
epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||
struct epoll_event e;
|
||||
int rc;
|
||||
|
||||
memset(&e, 0, sizeof(e));
|
||||
e.events = POLLIN;
|
||||
e.data.fd = -1;
|
||||
|
||||
rc = 0;
|
||||
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))
|
||||
if (errno != EEXIST)
|
||||
rc = UV__ERR(errno);
|
||||
|
||||
if (rc == 0)
|
||||
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))
|
||||
abort();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
/* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
|
||||
* effectively infinite on 32 bits architectures. To avoid blocking
|
||||
* indefinitely, we cap the timeout and poll again if necessary.
|
||||
*
|
||||
* Note that "30 minutes" is a simplification because it depends on
|
||||
* the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200,
|
||||
* that being the largest value I have seen in the wild (and only once.)
|
||||
*/
|
||||
static const int max_safe_timeout = 1789569;
|
||||
static int no_epoll_pwait_cached;
|
||||
static int no_epoll_wait_cached;
|
||||
int no_epoll_pwait;
|
||||
int no_epoll_wait;
|
||||
struct epoll_event events[1024];
|
||||
struct epoll_event* pe;
|
||||
struct epoll_event e;
|
||||
int real_timeout;
|
||||
QUEUE* q;
|
||||
uv__io_t* w;
|
||||
sigset_t sigset;
|
||||
uint64_t sigmask;
|
||||
uint64_t base;
|
||||
int have_signals;
|
||||
int nevents;
|
||||
int count;
|
||||
int nfds;
|
||||
int fd;
|
||||
int op;
|
||||
int i;
|
||||
int user_timeout;
|
||||
int reset_timeout;
|
||||
|
||||
if (loop->nfds == 0) {
|
||||
assert(QUEUE_EMPTY(&loop->watcher_queue));
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&e, 0, sizeof(e));
|
||||
|
||||
while (!QUEUE_EMPTY(&loop->watcher_queue)) {
|
||||
q = QUEUE_HEAD(&loop->watcher_queue);
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q);
|
||||
|
||||
w = QUEUE_DATA(q, uv__io_t, watcher_queue);
|
||||
assert(w->pevents != 0);
|
||||
assert(w->fd >= 0);
|
||||
assert(w->fd < (int) loop->nwatchers);
|
||||
|
||||
e.events = w->pevents;
|
||||
e.data.fd = w->fd;
|
||||
|
||||
if (w->events == 0)
|
||||
op = EPOLL_CTL_ADD;
|
||||
else
|
||||
op = EPOLL_CTL_MOD;
|
||||
|
||||
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
|
||||
* events, skip the syscall and squelch the events after epoll_wait().
|
||||
*/
|
||||
if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
|
||||
if (errno != EEXIST)
|
||||
abort();
|
||||
|
||||
assert(op == EPOLL_CTL_ADD);
|
||||
|
||||
/* We've reactivated a file descriptor that's been watched before. */
|
||||
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))
|
||||
abort();
|
||||
}
|
||||
|
||||
w->events = w->pevents;
|
||||
}
|
||||
|
||||
sigmask = 0;
|
||||
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGPROF);
|
||||
sigmask |= 1 << (SIGPROF - 1);
|
||||
}
|
||||
|
||||
assert(timeout >= -1);
|
||||
base = loop->time;
|
||||
count = 48; /* Benchmarks suggest this gives the best throughput. */
|
||||
real_timeout = timeout;
|
||||
|
||||
if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
|
||||
reset_timeout = 1;
|
||||
user_timeout = timeout;
|
||||
timeout = 0;
|
||||
} else {
|
||||
reset_timeout = 0;
|
||||
user_timeout = 0;
|
||||
}
|
||||
|
||||
/* You could argue there is a dependency between these two but
|
||||
* ultimately we don't care about their ordering with respect
|
||||
* to one another. Worst case, we make a few system calls that
|
||||
* could have been avoided because another thread already knows
|
||||
* they fail with ENOSYS. Hardly the end of the world.
|
||||
*/
|
||||
no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached);
|
||||
no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached);
|
||||
|
||||
for (;;) {
|
||||
/* Only need to set the provider_entry_time if timeout != 0. The function
|
||||
* will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
|
||||
*/
|
||||
if (timeout != 0)
|
||||
uv__metrics_set_provider_entry_time(loop);
|
||||
|
||||
/* See the comment for max_safe_timeout for an explanation of why
|
||||
* this is necessary. Executive summary: kernel bug workaround.
|
||||
*/
|
||||
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
|
||||
timeout = max_safe_timeout;
|
||||
|
||||
if (sigmask != 0 && no_epoll_pwait != 0)
|
||||
if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
|
||||
abort();
|
||||
|
||||
if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
|
||||
nfds = epoll_pwait(loop->backend_fd,
|
||||
events,
|
||||
ARRAY_SIZE(events),
|
||||
timeout,
|
||||
&sigset);
|
||||
if (nfds == -1 && errno == ENOSYS) {
|
||||
uv__store_relaxed(&no_epoll_pwait_cached, 1);
|
||||
no_epoll_pwait = 1;
|
||||
}
|
||||
} else {
|
||||
nfds = epoll_wait(loop->backend_fd,
|
||||
events,
|
||||
ARRAY_SIZE(events),
|
||||
timeout);
|
||||
if (nfds == -1 && errno == ENOSYS) {
|
||||
uv__store_relaxed(&no_epoll_wait_cached, 1);
|
||||
no_epoll_wait = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sigmask != 0 && no_epoll_pwait != 0)
|
||||
if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
|
||||
abort();
|
||||
|
||||
/* Update loop->time unconditionally. It's tempting to skip the update when
|
||||
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
|
||||
* operating system didn't reschedule our process while in the syscall.
|
||||
*/
|
||||
SAVE_ERRNO(uv__update_time(loop));
|
||||
|
||||
if (nfds == 0) {
|
||||
assert(timeout != -1);
|
||||
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
/* We may have been inside the system call for longer than |timeout|
|
||||
* milliseconds so we need to update the timestamp to avoid drift.
|
||||
*/
|
||||
goto update_timeout;
|
||||
}
|
||||
|
||||
if (nfds == -1) {
|
||||
if (errno == ENOSYS) {
|
||||
/* epoll_wait() or epoll_pwait() failed, try the other system call. */
|
||||
assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (errno != EINTR)
|
||||
abort();
|
||||
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
/* Interrupted by a signal. Update timeout and poll again. */
|
||||
goto update_timeout;
|
||||
}
|
||||
|
||||
have_signals = 0;
|
||||
nevents = 0;
|
||||
|
||||
{
|
||||
/* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */
|
||||
union {
|
||||
struct epoll_event* events;
|
||||
uv__io_t* watchers;
|
||||
} x;
|
||||
|
||||
x.events = events;
|
||||
assert(loop->watchers != NULL);
|
||||
loop->watchers[loop->nwatchers] = x.watchers;
|
||||
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
|
||||
}
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
pe = events + i;
|
||||
fd = pe->data.fd;
|
||||
|
||||
/* Skip invalidated events, see uv__platform_invalidate_fd */
|
||||
if (fd == -1)
|
||||
continue;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert((unsigned) fd < loop->nwatchers);
|
||||
|
||||
w = loop->watchers[fd];
|
||||
|
||||
if (w == NULL) {
|
||||
/* File descriptor that we've stopped watching, disarm it.
|
||||
*
|
||||
* Ignore all errors because we may be racing with another thread
|
||||
* when the file descriptor is closed.
|
||||
*/
|
||||
epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Give users only events they're interested in. Prevents spurious
|
||||
* callbacks when previous callback invocation in this loop has stopped
|
||||
* the current watcher. Also, filters out events that users has not
|
||||
* requested us to watch.
|
||||
*/
|
||||
pe->events &= w->pevents | POLLERR | POLLHUP;
|
||||
|
||||
/* Work around an epoll quirk where it sometimes reports just the
|
||||
* EPOLLERR or EPOLLHUP event. In order to force the event loop to
|
||||
* move forward, we merge in the read/write events that the watcher
|
||||
* is interested in; uv__read() and uv__write() will then deal with
|
||||
* the error or hangup in the usual fashion.
|
||||
*
|
||||
* Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user
|
||||
* reads the available data, calls uv_read_stop(), then sometime later
|
||||
* calls uv_read_start() again. By then, libuv has forgotten about the
|
||||
* hangup and the kernel won't report EPOLLIN again because there's
|
||||
* nothing left to read. If anything, libuv is to blame here. The
|
||||
* current hack is just a quick bandaid; to properly fix it, libuv
|
||||
* needs to remember the error/hangup event. We should get that for
|
||||
* free when we switch over to edge-triggered I/O.
|
||||
*/
|
||||
if (pe->events == POLLERR || pe->events == POLLHUP)
|
||||
pe->events |=
|
||||
w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
|
||||
|
||||
if (pe->events != 0) {
|
||||
/* Run signal watchers last. This also affects child process watchers
|
||||
* because those are implemented in terms of signal watchers.
|
||||
*/
|
||||
if (w == &loop->signal_io_watcher) {
|
||||
have_signals = 1;
|
||||
} else {
|
||||
uv__metrics_update_idle_time(loop);
|
||||
w->cb(loop, w, pe->events);
|
||||
}
|
||||
|
||||
nevents++;
|
||||
}
|
||||
}
|
||||
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
}
|
||||
|
||||
if (have_signals != 0) {
|
||||
uv__metrics_update_idle_time(loop);
|
||||
loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
|
||||
}
|
||||
|
||||
loop->watchers[loop->nwatchers] = NULL;
|
||||
loop->watchers[loop->nwatchers + 1] = NULL;
|
||||
|
||||
if (have_signals != 0)
|
||||
return; /* Event loop should cycle now so don't poll again. */
|
||||
|
||||
if (nevents != 0) {
|
||||
if (nfds == ARRAY_SIZE(events) && --count != 0) {
|
||||
/* Poll for more events but don't block this time. */
|
||||
timeout = 0;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
update_timeout:
|
||||
assert(timeout > 0);
|
||||
|
||||
real_timeout -= (loop->time - base);
|
||||
if (real_timeout <= 0)
|
||||
return;
|
||||
|
||||
timeout = real_timeout;
|
||||
}
|
||||
}
|
||||
|
@ -56,31 +56,6 @@ int uv__platform_loop_init(uv_loop_t* loop) {
|
||||
void uv__platform_loop_delete(uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef __DragonFly__
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
char abspath[PATH_MAX * 2 + 1];
|
||||
ssize_t abspath_size;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
abspath_size = readlink("/proc/curproc/file", abspath, sizeof(abspath));
|
||||
if (abspath_size < 0)
|
||||
return UV__ERR(errno);
|
||||
|
||||
assert(abspath_size > 0);
|
||||
*size -= 1;
|
||||
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
char abspath[PATH_MAX * 2 + 1];
|
||||
int mib[4];
|
||||
@ -110,7 +85,6 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
int freecount;
|
||||
@ -290,26 +264,41 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
}
|
||||
|
||||
|
||||
int uv__sendmmsg(int fd,
|
||||
struct uv__mmsghdr* mmsg,
|
||||
unsigned int vlen,
|
||||
unsigned int flags) {
|
||||
#if __FreeBSD__ >= 11
|
||||
return sendmmsg(fd, mmsg, vlen, flags);
|
||||
int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
|
||||
#if __FreeBSD__ >= 11 && !defined(__DragonFly__)
|
||||
return sendmmsg(fd,
|
||||
(struct mmsghdr*) mmsg,
|
||||
vlen,
|
||||
0 /* flags */);
|
||||
#else
|
||||
return errno = ENOSYS, -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int uv__recvmmsg(int fd,
|
||||
struct uv__mmsghdr* mmsg,
|
||||
unsigned int vlen,
|
||||
unsigned int flags,
|
||||
struct timespec* timeout) {
|
||||
#if __FreeBSD__ >= 11
|
||||
return recvmmsg(fd, mmsg, vlen, flags, timeout);
|
||||
int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
|
||||
#if __FreeBSD__ >= 11 && !defined(__DragonFly__)
|
||||
return recvmmsg(fd,
|
||||
(struct mmsghdr*) mmsg,
|
||||
vlen,
|
||||
0 /* flags */,
|
||||
NULL /* timeout */);
|
||||
#else
|
||||
return errno = ENOSYS, -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t
|
||||
uv__fs_copy_file_range(int fd_in,
|
||||
off_t* off_in,
|
||||
int fd_out,
|
||||
off_t* off_out,
|
||||
size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
#if __FreeBSD__ >= 13 && !defined(__DragonFly__)
|
||||
return copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
|
||||
#else
|
||||
return errno = ENOSYS, -1;
|
||||
#endif
|
||||
}
|
||||
|
370
src/unix/fs.c
370
src/unix/fs.c
@ -56,8 +56,13 @@
|
||||
# define HAVE_PREADV 0
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "sys/utsname.h"
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__sun)
|
||||
# include <sys/sendfile.h>
|
||||
# include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
@ -79,7 +84,11 @@
|
||||
defined(__NetBSD__)
|
||||
# include <sys/param.h>
|
||||
# include <sys/mount.h>
|
||||
#elif defined(__sun) || defined(__MVS__) || defined(__NetBSD__) || defined(__HAIKU__)
|
||||
#elif defined(__sun) || \
|
||||
defined(__MVS__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__HAIKU__) || \
|
||||
defined(__QNX__)
|
||||
# include <sys/statvfs.h>
|
||||
#else
|
||||
# include <sys/statfs.h>
|
||||
@ -205,23 +214,45 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = time;
|
||||
ts.tv_nsec = (time - ts.tv_sec) * 1e9;
|
||||
|
||||
/* TODO(bnoordhuis) Remove this. utimesat() has nanosecond resolution but we
|
||||
* stick to microsecond resolution for the sake of consistency with other
|
||||
* platforms. I'm the original author of this compatibility hack but I'm
|
||||
* less convinced it's useful nowadays.
|
||||
*/
|
||||
ts.tv_nsec -= ts.tv_nsec % 1000;
|
||||
|
||||
if (ts.tv_nsec < 0) {
|
||||
ts.tv_nsec += 1e9;
|
||||
ts.tv_sec -= 1;
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
|
||||
UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = time;
|
||||
tv.tv_usec = (time - tv.tv_sec) * 1e6;
|
||||
if (tv.tv_usec < 0) {
|
||||
tv.tv_usec += 1e6;
|
||||
tv.tv_sec -= 1;
|
||||
}
|
||||
return tv;
|
||||
}
|
||||
|
||||
static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||
#if defined(__linux__) \
|
||||
|| defined(_AIX71) \
|
||||
|| defined(__HAIKU__)
|
||||
/* utimesat() has nanosecond resolution but we stick to microseconds
|
||||
* for the sake of consistency with other platforms.
|
||||
*/
|
||||
|| defined(__HAIKU__) \
|
||||
|| defined(__GNU__)
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = req->atime;
|
||||
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
||||
ts[1].tv_sec = req->mtime;
|
||||
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
||||
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
|
||||
return utimensat(req->file, NULL, ts, 0);
|
||||
#else
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
return futimens(req->file, ts);
|
||||
#endif
|
||||
#elif defined(__APPLE__) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
@ -230,10 +261,8 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__sun)
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = req->atime;
|
||||
tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
|
||||
tv[1].tv_sec = req->mtime;
|
||||
tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
# if defined(__sun)
|
||||
return futimesat(req->file, NULL, tv);
|
||||
# else
|
||||
@ -300,13 +329,14 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
|
||||
if (path_length < pattern_size ||
|
||||
strcmp(path + path_length - pattern_size, pattern)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
r = -1;
|
||||
goto clobber;
|
||||
}
|
||||
|
||||
uv_once(&once, uv__mkostemp_initonce);
|
||||
|
||||
#ifdef O_CLOEXEC
|
||||
if (no_cloexec_support == 0 && uv__mkostemp != NULL) {
|
||||
if (uv__load_relaxed(&no_cloexec_support) == 0 && uv__mkostemp != NULL) {
|
||||
r = uv__mkostemp(path, O_CLOEXEC);
|
||||
|
||||
if (r >= 0)
|
||||
@ -315,11 +345,11 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
|
||||
/* If mkostemp() returns EINVAL, it means the kernel doesn't
|
||||
support O_CLOEXEC, so we just fallback to mkstemp() below. */
|
||||
if (errno != EINVAL)
|
||||
return r;
|
||||
goto clobber;
|
||||
|
||||
/* We set the static variable so that next calls don't even
|
||||
try to use mkostemp. */
|
||||
no_cloexec_support = 1;
|
||||
uv__store_relaxed(&no_cloexec_support, 1);
|
||||
}
|
||||
#endif /* O_CLOEXEC */
|
||||
|
||||
@ -341,6 +371,9 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
|
||||
if (req->cb != NULL)
|
||||
uv_rwlock_rdunlock(&req->loop->cloexec_lock);
|
||||
|
||||
clobber:
|
||||
if (r < 0)
|
||||
path[0] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -450,7 +483,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
|
||||
result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
|
||||
#else
|
||||
# if defined(__linux__)
|
||||
if (no_preadv) retry:
|
||||
if (uv__load_relaxed(&no_preadv)) retry:
|
||||
# endif
|
||||
{
|
||||
result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
|
||||
@ -462,7 +495,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
|
||||
req->nbufs,
|
||||
req->off);
|
||||
if (result == -1 && errno == ENOSYS) {
|
||||
no_preadv = 1;
|
||||
uv__store_relaxed(&no_preadv, 1);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
@ -619,7 +652,11 @@ static int uv__fs_closedir(uv_fs_t* req) {
|
||||
|
||||
static int uv__fs_statfs(uv_fs_t* req) {
|
||||
uv_statfs_t* stat_fs;
|
||||
#if defined(__sun) || defined(__MVS__) || defined(__NetBSD__) || defined(__HAIKU__)
|
||||
#if defined(__sun) || \
|
||||
defined(__MVS__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__HAIKU__) || \
|
||||
defined(__QNX__)
|
||||
struct statvfs buf;
|
||||
|
||||
if (0 != statvfs(req->path, &buf))
|
||||
@ -636,7 +673,12 @@ static int uv__fs_statfs(uv_fs_t* req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(__sun) || defined(__MVS__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
|
||||
#if defined(__sun) || \
|
||||
defined(__MVS__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__HAIKU__) || \
|
||||
defined(__QNX__)
|
||||
stat_fs->f_type = 0; /* f_type is not supported. */
|
||||
#else
|
||||
stat_fs->f_type = buf.f_type;
|
||||
@ -666,7 +708,6 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
||||
ssize_t maxlen;
|
||||
ssize_t len;
|
||||
char* buf;
|
||||
char* newbuf;
|
||||
|
||||
#if defined(_POSIX_PATH_MAX) || defined(PATH_MAX)
|
||||
maxlen = uv__fs_pathmax_size(req->path);
|
||||
@ -710,14 +751,10 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
||||
|
||||
/* Uncommon case: resize to make room for the trailing nul byte. */
|
||||
if (len == maxlen) {
|
||||
newbuf = uv__realloc(buf, len + 1);
|
||||
buf = uv__reallocf(buf, len + 1);
|
||||
|
||||
if (newbuf == NULL) {
|
||||
uv__free(buf);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = newbuf;
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
@ -869,6 +906,115 @@ out:
|
||||
}
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
static unsigned uv__kernel_version(void) {
|
||||
static unsigned cached_version;
|
||||
struct utsname u;
|
||||
unsigned version;
|
||||
unsigned major;
|
||||
unsigned minor;
|
||||
unsigned patch;
|
||||
|
||||
version = uv__load_relaxed(&cached_version);
|
||||
if (version != 0)
|
||||
return version;
|
||||
|
||||
if (-1 == uname(&u))
|
||||
return 0;
|
||||
|
||||
if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch))
|
||||
return 0;
|
||||
|
||||
version = major * 65536 + minor * 256 + patch;
|
||||
uv__store_relaxed(&cached_version, version);
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
/* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command
|
||||
* in copy_file_range() when it shouldn't. There is no workaround except to
|
||||
* fall back to a regular copy.
|
||||
*/
|
||||
static int uv__is_buggy_cephfs(int fd) {
|
||||
struct statfs s;
|
||||
|
||||
if (-1 == fstatfs(fd, &s))
|
||||
return 0;
|
||||
|
||||
if (s.f_type != /* CephFS */ 0xC36400)
|
||||
return 0;
|
||||
|
||||
return uv__kernel_version() < /* 4.20.0 */ 0x041400;
|
||||
}
|
||||
|
||||
|
||||
static int uv__is_cifs_or_smb(int fd) {
|
||||
struct statfs s;
|
||||
|
||||
if (-1 == fstatfs(fd, &s))
|
||||
return 0;
|
||||
|
||||
switch ((unsigned) s.f_type) {
|
||||
case 0x0000517Bu: /* SMB */
|
||||
case 0xFE534D42u: /* SMB2 */
|
||||
case 0xFF534D42u: /* CIFS */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off,
|
||||
int out_fd, size_t len) {
|
||||
static int no_copy_file_range_support;
|
||||
ssize_t r;
|
||||
|
||||
if (uv__load_relaxed(&no_copy_file_range_support)) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = uv__fs_copy_file_range(in_fd, off, out_fd, NULL, len, 0);
|
||||
|
||||
if (r != -1)
|
||||
return r;
|
||||
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
/* Pre-4.20 kernels have a bug where CephFS uses the RADOS
|
||||
* copy-from command when it shouldn't.
|
||||
*/
|
||||
if (uv__is_buggy_cephfs(in_fd))
|
||||
errno = ENOSYS; /* Use fallback. */
|
||||
break;
|
||||
case ENOSYS:
|
||||
uv__store_relaxed(&no_copy_file_range_support, 1);
|
||||
break;
|
||||
case EPERM:
|
||||
/* It's been reported that CIFS spuriously fails.
|
||||
* Consider it a transient error.
|
||||
*/
|
||||
if (uv__is_cifs_or_smb(out_fd))
|
||||
errno = ENOSYS; /* Use fallback. */
|
||||
break;
|
||||
case ENOTSUP:
|
||||
case EXDEV:
|
||||
/* ENOTSUP - it could work on another file system type.
|
||||
* EXDEV - it will not work when in_fd and out_fd are not on the same
|
||||
* mounted filesystem (pre Linux 5.3)
|
||||
*/
|
||||
errno = ENOSYS; /* Use fallback. */
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
|
||||
static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
||||
int in_fd;
|
||||
int out_fd;
|
||||
@ -880,9 +1026,20 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
||||
{
|
||||
off_t off;
|
||||
ssize_t r;
|
||||
size_t len;
|
||||
int try_sendfile;
|
||||
|
||||
off = req->off;
|
||||
r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);
|
||||
len = req->bufsml[0].len;
|
||||
try_sendfile = 1;
|
||||
|
||||
#ifdef __linux__
|
||||
r = uv__fs_try_copy_file_range(in_fd, &off, out_fd, len);
|
||||
try_sendfile = (r == -1 && errno == ENOSYS);
|
||||
#endif
|
||||
|
||||
if (try_sendfile)
|
||||
r = sendfile(out_fd, in_fd, &off, len);
|
||||
|
||||
/* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
|
||||
* it still writes out data. Fortunately, we can detect it by checking if
|
||||
@ -918,6 +1075,17 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
||||
*/
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#if defined(__FreeBSD__)
|
||||
off_t off;
|
||||
|
||||
off = req->off;
|
||||
r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0);
|
||||
if (r >= 0) {
|
||||
r = off - req->off;
|
||||
req->off = off;
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
len = 0;
|
||||
r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
|
||||
#elif defined(__FreeBSD_kernel__)
|
||||
@ -973,14 +1141,9 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
|| defined(_AIX71) \
|
||||
|| defined(__sun) \
|
||||
|| defined(__HAIKU__)
|
||||
/* utimesat() has nanosecond resolution but we stick to microseconds
|
||||
* for the sake of consistency with other platforms.
|
||||
*/
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = req->atime;
|
||||
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
||||
ts[1].tv_sec = req->mtime;
|
||||
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
return utimensat(AT_FDCWD, req->path, ts, 0);
|
||||
#elif defined(__APPLE__) \
|
||||
|| defined(__DragonFly__) \
|
||||
@ -989,10 +1152,8 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__)
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = req->atime;
|
||||
tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
|
||||
tv[1].tv_sec = req->mtime;
|
||||
tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
return utimes(req->path, tv);
|
||||
#elif defined(_AIX) \
|
||||
&& !defined(_AIX71)
|
||||
@ -1015,6 +1176,32 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uv__fs_lutime(uv_fs_t* req) {
|
||||
#if defined(__linux__) || \
|
||||
defined(_AIX71) || \
|
||||
defined(__sun) || \
|
||||
defined(__HAIKU__) || \
|
||||
defined(__GNU__)
|
||||
struct timespec ts[2];
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
|
||||
#elif defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__)
|
||||
struct timeval tv[2];
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
return lutimes(req->path, tv);
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uv__fs_write(uv_fs_t* req) {
|
||||
#if defined(__linux__)
|
||||
static int no_pwritev;
|
||||
@ -1084,9 +1271,10 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
int dst_flags;
|
||||
int result;
|
||||
int err;
|
||||
size_t bytes_to_send;
|
||||
int64_t in_offset;
|
||||
ssize_t bytes_written;
|
||||
off_t bytes_to_send;
|
||||
off_t in_offset;
|
||||
off_t bytes_written;
|
||||
size_t bytes_chunk;
|
||||
|
||||
dstfd = -1;
|
||||
err = 0;
|
||||
@ -1104,7 +1292,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
dst_flags = O_WRONLY | O_CREAT;
|
||||
|
||||
if (req->flags & UV_FS_COPYFILE_EXCL)
|
||||
dst_flags |= O_EXCL;
|
||||
@ -1123,37 +1311,40 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get the destination file's mode. */
|
||||
if (fstat(dstfd, &dst_statsbuf)) {
|
||||
err = UV__ERR(errno);
|
||||
goto out;
|
||||
}
|
||||
/* If the file is not being opened exclusively, verify that the source and
|
||||
destination are not the same file. If they are the same, bail out early. */
|
||||
if ((req->flags & UV_FS_COPYFILE_EXCL) == 0) {
|
||||
/* Get the destination file's mode. */
|
||||
if (fstat(dstfd, &dst_statsbuf)) {
|
||||
err = UV__ERR(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check if srcfd and dstfd refer to the same file */
|
||||
if (src_statsbuf.st_dev == dst_statsbuf.st_dev &&
|
||||
src_statsbuf.st_ino == dst_statsbuf.st_ino) {
|
||||
goto out;
|
||||
/* Check if srcfd and dstfd refer to the same file */
|
||||
if (src_statsbuf.st_dev == dst_statsbuf.st_dev &&
|
||||
src_statsbuf.st_ino == dst_statsbuf.st_ino) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Truncate the file in case the destination already existed. */
|
||||
if (ftruncate(dstfd, 0) != 0) {
|
||||
err = UV__ERR(errno);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
|
||||
err = UV__ERR(errno);
|
||||
#ifdef __linux__
|
||||
/* fchmod() on CIFS shares always fails with EPERM unless the share is
|
||||
* mounted with "noperm". As fchmod() is a meaningless operation on such
|
||||
* shares anyway, detect that condition and squelch the error.
|
||||
*/
|
||||
if (err != UV_EPERM)
|
||||
goto out;
|
||||
|
||||
{
|
||||
struct statfs s;
|
||||
|
||||
/* fchmod() on CIFS shares always fails with EPERM unless the share is
|
||||
* mounted with "noperm". As fchmod() is a meaningless operation on such
|
||||
* shares anyway, detect that condition and squelch the error.
|
||||
*/
|
||||
if (fstatfs(dstfd, &s) == -1)
|
||||
goto out;
|
||||
|
||||
if (s.f_type != /* CIFS */ 0xFF534D42u)
|
||||
goto out;
|
||||
}
|
||||
if (!uv__is_cifs_or_smb(dstfd))
|
||||
goto out;
|
||||
|
||||
err = 0;
|
||||
#else /* !__linux__ */
|
||||
@ -1185,7 +1376,10 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
bytes_to_send = src_statsbuf.st_size;
|
||||
in_offset = 0;
|
||||
while (bytes_to_send != 0) {
|
||||
uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_to_send, NULL);
|
||||
bytes_chunk = SSIZE_MAX;
|
||||
if (bytes_to_send < (off_t) bytes_chunk)
|
||||
bytes_chunk = bytes_to_send;
|
||||
uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_chunk, NULL);
|
||||
bytes_written = fs_req.result;
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
@ -1268,7 +1462,8 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
|
||||
dst->st_birthtim.tv_nsec = src->st_ctimensec;
|
||||
dst->st_flags = 0;
|
||||
dst->st_gen = 0;
|
||||
#elif !defined(_AIX) && ( \
|
||||
#elif !defined(_AIX) && \
|
||||
!defined(__MVS__) && ( \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
@ -1325,7 +1520,7 @@ static int uv__fs_statx(int fd,
|
||||
int mode;
|
||||
int rc;
|
||||
|
||||
if (no_statx)
|
||||
if (uv__load_relaxed(&no_statx))
|
||||
return UV_ENOSYS;
|
||||
|
||||
dirfd = AT_FDCWD;
|
||||
@ -1348,8 +1543,9 @@ static int uv__fs_statx(int fd,
|
||||
case -1:
|
||||
/* EPERM happens when a seccomp filter rejects the system call.
|
||||
* Has been observed with libseccomp < 2.3.3 and docker < 18.04.
|
||||
* EOPNOTSUPP is used on DVS exported filesystems
|
||||
*/
|
||||
if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
|
||||
if (errno != EINVAL && errno != EPERM && errno != ENOSYS && errno != EOPNOTSUPP)
|
||||
return -1;
|
||||
/* Fall through. */
|
||||
default:
|
||||
@ -1358,16 +1554,16 @@ static int uv__fs_statx(int fd,
|
||||
* implemented, rc might return 1 with 0 set as the error code in which
|
||||
* case we return ENOSYS.
|
||||
*/
|
||||
no_statx = 1;
|
||||
uv__store_relaxed(&no_statx, 1);
|
||||
return UV_ENOSYS;
|
||||
}
|
||||
|
||||
buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
|
||||
buf->st_dev = makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor);
|
||||
buf->st_mode = statxbuf.stx_mode;
|
||||
buf->st_nlink = statxbuf.stx_nlink;
|
||||
buf->st_uid = statxbuf.stx_uid;
|
||||
buf->st_gid = statxbuf.stx_gid;
|
||||
buf->st_rdev = statxbuf.stx_rdev_major;
|
||||
buf->st_rdev = makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor);
|
||||
buf->st_ino = statxbuf.stx_ino;
|
||||
buf->st_size = statxbuf.stx_size;
|
||||
buf->st_blksize = statxbuf.stx_blksize;
|
||||
@ -1528,6 +1724,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
X(FSYNC, uv__fs_fsync(req));
|
||||
X(FTRUNCATE, ftruncate(req->file, req->off));
|
||||
X(FUTIME, uv__fs_futime(req));
|
||||
X(LUTIME, uv__fs_lutime(req));
|
||||
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
|
||||
X(LINK, link(req->path, req->new_path));
|
||||
X(MKDIR, mkdir(req->path, req->mode));
|
||||
@ -1714,6 +1911,19 @@ int uv_fs_futime(uv_loop_t* loop,
|
||||
POST;
|
||||
}
|
||||
|
||||
int uv_fs_lutime(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb) {
|
||||
INIT(LUTIME);
|
||||
PATH;
|
||||
req->atime = atime;
|
||||
req->mtime = mtime;
|
||||
POST;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
INIT(LSTAT);
|
||||
@ -1987,7 +2197,7 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
|
||||
|
||||
/* Only necessary for asychronous requests, i.e., requests with a callback.
|
||||
* Synchronous ones don't copy their arguments and have req->path and
|
||||
* req->new_path pointing to user-owned memory. UV_FS_MKDTEMP and
|
||||
* req->new_path pointing to user-owned memory. UV_FS_MKDTEMP and
|
||||
* UV_FS_MKSTEMP are the exception to the rule, they always allocate memory.
|
||||
*/
|
||||
if (req->path != NULL &&
|
||||
@ -2042,3 +2252,7 @@ int uv_fs_statfs(uv_loop_t* loop,
|
||||
PATH;
|
||||
POST;
|
||||
}
|
||||
|
||||
int uv_fs_get_system_error(const uv_fs_t* req) {
|
||||
return -req->result;
|
||||
}
|
||||
|
@ -41,34 +41,33 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) {
|
||||
|
||||
#else /* TARGET_OS_IPHONE */
|
||||
|
||||
#include "darwin-stub.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <CoreFoundation/CFRunLoop.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
static const int kFSEventsModified =
|
||||
kFSEventStreamEventFlagItemChangeOwner |
|
||||
kFSEventStreamEventFlagItemFinderInfoMod |
|
||||
kFSEventStreamEventFlagItemInodeMetaMod |
|
||||
kFSEventStreamEventFlagItemModified |
|
||||
kFSEventStreamEventFlagItemXattrMod;
|
||||
|
||||
/* These are macros to avoid "initializer element is not constant" errors
|
||||
* with old versions of gcc.
|
||||
*/
|
||||
#define kFSEventsModified (kFSEventStreamEventFlagItemFinderInfoMod | \
|
||||
kFSEventStreamEventFlagItemModified | \
|
||||
kFSEventStreamEventFlagItemInodeMetaMod | \
|
||||
kFSEventStreamEventFlagItemChangeOwner | \
|
||||
kFSEventStreamEventFlagItemXattrMod)
|
||||
static const int kFSEventsRenamed =
|
||||
kFSEventStreamEventFlagItemCreated |
|
||||
kFSEventStreamEventFlagItemRemoved |
|
||||
kFSEventStreamEventFlagItemRenamed;
|
||||
|
||||
#define kFSEventsRenamed (kFSEventStreamEventFlagItemCreated | \
|
||||
kFSEventStreamEventFlagItemRemoved | \
|
||||
kFSEventStreamEventFlagItemRenamed)
|
||||
|
||||
#define kFSEventsSystem (kFSEventStreamEventFlagUserDropped | \
|
||||
kFSEventStreamEventFlagKernelDropped | \
|
||||
kFSEventStreamEventFlagEventIdsWrapped | \
|
||||
kFSEventStreamEventFlagHistoryDone | \
|
||||
kFSEventStreamEventFlagMount | \
|
||||
kFSEventStreamEventFlagUnmount | \
|
||||
kFSEventStreamEventFlagRootChanged)
|
||||
static const int kFSEventsSystem =
|
||||
kFSEventStreamEventFlagUserDropped |
|
||||
kFSEventStreamEventFlagKernelDropped |
|
||||
kFSEventStreamEventFlagEventIdsWrapped |
|
||||
kFSEventStreamEventFlagHistoryDone |
|
||||
kFSEventStreamEventFlagMount |
|
||||
kFSEventStreamEventFlagUnmount |
|
||||
kFSEventStreamEventFlagRootChanged;
|
||||
|
||||
typedef struct uv__fsevents_event_s uv__fsevents_event_t;
|
||||
typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t;
|
||||
@ -148,7 +147,7 @@ static void (*pFSEventStreamRelease)(FSEventStreamRef);
|
||||
static void (*pFSEventStreamScheduleWithRunLoop)(FSEventStreamRef,
|
||||
CFRunLoopRef,
|
||||
CFStringRef);
|
||||
static Boolean (*pFSEventStreamStart)(FSEventStreamRef);
|
||||
static int (*pFSEventStreamStart)(FSEventStreamRef);
|
||||
static void (*pFSEventStreamStop)(FSEventStreamRef);
|
||||
|
||||
#define UV__FSEVENTS_PROCESS(handle, block) \
|
||||
@ -215,7 +214,7 @@ static void uv__fsevents_push_event(uv_fs_event_t* handle,
|
||||
|
||||
|
||||
/* Runs in CF thread, when there're events in FSEventStream */
|
||||
static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
|
||||
static void uv__fsevents_event_cb(const FSEventStreamRef streamRef,
|
||||
void* info,
|
||||
size_t numEvents,
|
||||
void* eventPaths,
|
||||
@ -340,11 +339,8 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) {
|
||||
FSEventStreamCreateFlags flags;
|
||||
|
||||
/* Initialize context */
|
||||
ctx.version = 0;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.info = loop;
|
||||
ctx.retain = NULL;
|
||||
ctx.release = NULL;
|
||||
ctx.copyDescription = NULL;
|
||||
|
||||
latency = 0.05;
|
||||
|
||||
@ -599,8 +595,7 @@ out:
|
||||
static int uv__fsevents_loop_init(uv_loop_t* loop) {
|
||||
CFRunLoopSourceContext ctx;
|
||||
uv__cf_loop_state_t* state;
|
||||
pthread_attr_t attr_storage;
|
||||
pthread_attr_t* attr;
|
||||
pthread_attr_t attr;
|
||||
int err;
|
||||
|
||||
if (loop->cf_state != NULL)
|
||||
@ -645,25 +640,19 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
|
||||
goto fail_signal_source_create;
|
||||
}
|
||||
|
||||
/* In the unlikely event that pthread_attr_init() fails, create the thread
|
||||
* with the default stack size. We'll use a little more address space but
|
||||
* that in itself is not a fatal error.
|
||||
*/
|
||||
attr = &attr_storage;
|
||||
if (pthread_attr_init(attr))
|
||||
attr = NULL;
|
||||
if (pthread_attr_init(&attr))
|
||||
abort();
|
||||
|
||||
if (attr != NULL)
|
||||
if (pthread_attr_setstacksize(attr, 4 * PTHREAD_STACK_MIN))
|
||||
abort();
|
||||
if (pthread_attr_setstacksize(&attr, uv__thread_stack_size()))
|
||||
abort();
|
||||
|
||||
loop->cf_state = state;
|
||||
|
||||
/* uv_thread_t is an alias for pthread_t. */
|
||||
err = UV__ERR(pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop));
|
||||
err = UV__ERR(pthread_create(&loop->cf_thread, &attr, uv__cf_loop_runner, loop));
|
||||
|
||||
if (attr != NULL)
|
||||
pthread_attr_destroy(attr);
|
||||
if (pthread_attr_destroy(&attr))
|
||||
abort();
|
||||
|
||||
if (err)
|
||||
goto fail_thread_create;
|
||||
|
@ -21,9 +21,6 @@
|
||||
/* Expose glibc-specific EAI_* error codes. Needs to be defined before we
|
||||
* include any headers.
|
||||
*/
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
|
167
src/unix/hurd.c
Normal file
167
src/unix/hurd.c
Normal file
@ -0,0 +1,167 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <hurd.h>
|
||||
#include <hurd/process.h>
|
||||
#include <mach/task_info.h>
|
||||
#include <mach/vm_statistics.h>
|
||||
#include <mach/vm_param.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
kern_return_t err;
|
||||
/* XXX in current Hurd, strings are char arrays of 1024 elements */
|
||||
string_t exepath;
|
||||
ssize_t copied;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (*size - 1 > 0) {
|
||||
/* XXX limited length of buffer in current Hurd, this API will probably
|
||||
* evolve in the future */
|
||||
err = proc_get_exe(getproc(), getpid(), exepath);
|
||||
|
||||
if (err)
|
||||
return UV__ERR(err);
|
||||
}
|
||||
|
||||
copied = uv__strscpy(buffer, exepath, *size);
|
||||
|
||||
/* do not return error on UV_E2BIG failure */
|
||||
*size = copied < 0 ? strlen(buffer) : (size_t) copied;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uv_resident_set_memory(size_t* rss) {
|
||||
kern_return_t err;
|
||||
struct task_basic_info bi;
|
||||
mach_msg_type_number_t count;
|
||||
|
||||
count = TASK_BASIC_INFO_COUNT;
|
||||
err = task_info(mach_task_self(), TASK_BASIC_INFO,
|
||||
(task_info_t) &bi, &count);
|
||||
|
||||
if (err)
|
||||
return UV__ERR(err);
|
||||
|
||||
*rss = bi.resident_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
kern_return_t err;
|
||||
struct vm_statistics vmstats;
|
||||
|
||||
err = vm_statistics(mach_task_self(), &vmstats);
|
||||
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
return vmstats.free_count * vm_page_size;
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_total_memory(void) {
|
||||
kern_return_t err;
|
||||
host_basic_info_data_t hbi;
|
||||
mach_msg_type_number_t cnt;
|
||||
|
||||
cnt = HOST_BASIC_INFO_COUNT;
|
||||
err = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt);
|
||||
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
return hbi.memory_size;
|
||||
}
|
||||
|
||||
|
||||
int uv_uptime(double* uptime) {
|
||||
char buf[128];
|
||||
|
||||
/* Try /proc/uptime first */
|
||||
if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf)))
|
||||
if (1 == sscanf(buf, "%lf", uptime))
|
||||
return 0;
|
||||
|
||||
/* Reimplement here code from procfs to calculate uptime if not mounted? */
|
||||
|
||||
return UV__ERR(EIO);
|
||||
}
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
char buf[128]; /* Large enough to hold all of /proc/loadavg. */
|
||||
|
||||
if (0 == uv__slurp("/proc/loadavg", buf, sizeof(buf)))
|
||||
if (3 == sscanf(buf, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]))
|
||||
return;
|
||||
|
||||
/* Reimplement here code from procfs to calculate loadavg if not mounted? */
|
||||
}
|
||||
|
||||
|
||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
kern_return_t err;
|
||||
host_basic_info_data_t hbi;
|
||||
mach_msg_type_number_t cnt;
|
||||
|
||||
/* Get count of cpus */
|
||||
cnt = HOST_BASIC_INFO_COUNT;
|
||||
err = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt);
|
||||
|
||||
if (err) {
|
||||
err = UV__ERR(err);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
/* XXX not implemented on the Hurd */
|
||||
*cpu_infos = uv__calloc(hbi.avail_cpus, sizeof(**cpu_infos));
|
||||
if (*cpu_infos == NULL) {
|
||||
err = UV_ENOMEM;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
*count = hbi.avail_cpus;
|
||||
|
||||
return 0;
|
||||
|
||||
abort:
|
||||
*cpu_infos = NULL;
|
||||
*count = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
uint64_t uv_get_constrained_memory(void) {
|
||||
return 0; /* Memory constraints are unknown. */
|
||||
}
|
@ -26,7 +26,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -58,6 +57,9 @@
|
||||
#include <as400_protos.h>
|
||||
#include <as400_types.h>
|
||||
|
||||
char* original_exepath = NULL;
|
||||
uv_mutex_t process_title_mutex;
|
||||
uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
||||
|
||||
typedef struct {
|
||||
int bytes_available;
|
||||
@ -163,7 +165,7 @@ static void iconv_a2e(const char* src, unsigned char dst[], size_t length) {
|
||||
|
||||
srclen = strlen(src);
|
||||
if (srclen > length)
|
||||
abort();
|
||||
srclen = length;
|
||||
for (i = 0; i < srclen; i++)
|
||||
dst[i] = a2e[src[i]];
|
||||
/* padding the remaining part with spaces */
|
||||
@ -171,6 +173,9 @@ static void iconv_a2e(const char* src, unsigned char dst[], size_t length) {
|
||||
dst[i] = a2e[' '];
|
||||
}
|
||||
|
||||
void init_process_title_mutex_once(void) {
|
||||
uv_mutex_init(&process_title_mutex);
|
||||
}
|
||||
|
||||
static int get_ibmi_system_status(SSTS0200* rcvr) {
|
||||
/* rcvrlen is input parameter 2 to QWCRSSTS */
|
||||
@ -354,6 +359,10 @@ static int get_ibmi_physical_address(const char* line, char (*phys_addr)[6]) {
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
if (err.bytes_available > 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* convert ebcdic loca_adapter_address to ascii first */
|
||||
iconv_e2a(rcvr.loca_adapter_address, mac_addr,
|
||||
sizeof(rcvr.loca_adapter_address));
|
||||
@ -437,9 +446,42 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
}
|
||||
address->is_internal = cur->ifa_flags & IFF_LOOPBACK ? 1 : 0;
|
||||
if (!address->is_internal) {
|
||||
int rc = get_ibmi_physical_address(address->name, &address->phys_addr);
|
||||
if (rc != 0)
|
||||
r = rc;
|
||||
int rc = -1;
|
||||
size_t name_len = strlen(address->name);
|
||||
/* To get the associated MAC address, we must convert the address to a
|
||||
* line description. Normally, the name field contains the line
|
||||
* description name, but for VLANs it has the VLAN appended with a
|
||||
* period. Since object names can also contain periods and numbers, there
|
||||
* is no way to know if a returned name is for a VLAN or not. eg.
|
||||
* *LIND ETH1.1 and *LIND ETH1, VLAN 1 both have the same name: ETH1.1
|
||||
*
|
||||
* Instead, we apply the same heuristic used by some of the XPF ioctls:
|
||||
* - names > 10 *must* contain a VLAN
|
||||
* - assume names <= 10 do not contain a VLAN and try directly
|
||||
* - if >10 or QDCRLIND returned an error, try to strip off a VLAN
|
||||
* and try again
|
||||
* - if we still get an error or couldn't find a period, leave the MAC as
|
||||
* 00:00:00:00:00:00
|
||||
*/
|
||||
if (name_len <= 10) {
|
||||
/* Assume name does not contain a VLAN ID */
|
||||
rc = get_ibmi_physical_address(address->name, &address->phys_addr);
|
||||
}
|
||||
|
||||
if (name_len > 10 || rc != 0) {
|
||||
/* The interface name must contain a VLAN ID suffix. Attempt to strip
|
||||
* it off so we can get the line description to pass to QDCRLIND.
|
||||
*/
|
||||
char* temp_name = uv__strdup(address->name);
|
||||
char* dot = strrchr(temp_name, '.');
|
||||
if (dot != NULL) {
|
||||
*dot = '\0';
|
||||
if (strlen(temp_name) <= 10) {
|
||||
rc = get_ibmi_physical_address(temp_name, &address->phys_addr);
|
||||
}
|
||||
}
|
||||
uv__free(temp_name);
|
||||
}
|
||||
}
|
||||
|
||||
address++;
|
||||
@ -459,3 +501,37 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) {
|
||||
|
||||
uv__free(addresses);
|
||||
}
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
char exepath[UV__PATH_MAX];
|
||||
char* s;
|
||||
size_t size;
|
||||
|
||||
if (argc > 0) {
|
||||
/* Use argv[0] to determine value for uv_exepath(). */
|
||||
size = sizeof(exepath);
|
||||
if (uv__search_path(argv[0], exepath, &size) == 0) {
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_lock(&process_title_mutex);
|
||||
original_exepath = uv__strdup(exepath);
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
return argv;
|
||||
}
|
||||
|
||||
int uv_set_process_title(const char* title) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uv_get_process_title(char* buffer, size_t size) {
|
||||
if (buffer == NULL || size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
buffer[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uv__process_title_cleanup(void) {
|
||||
}
|
||||
|
@ -62,9 +62,18 @@
|
||||
# include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_PATH_MAX)
|
||||
# define UV__PATH_MAX _POSIX_PATH_MAX
|
||||
#elif defined(PATH_MAX)
|
||||
/*
|
||||
* Define common detection for active Thread Sanitizer
|
||||
* - clang uses __has_feature(thread_sanitizer)
|
||||
* - gcc-7+ uses __SANITIZE_THREAD__
|
||||
*/
|
||||
#if defined(__has_feature)
|
||||
# if __has_feature(thread_sanitizer)
|
||||
# define __SANITIZE_THREAD__ 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(PATH_MAX)
|
||||
# define UV__PATH_MAX PATH_MAX
|
||||
#else
|
||||
# define UV__PATH_MAX 8192
|
||||
@ -106,10 +115,8 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
|
||||
#if defined(__clang__) || \
|
||||
defined(__GNUC__) || \
|
||||
defined(__INTEL_COMPILER)
|
||||
# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
|
||||
# define UV_UNUSED(declaration) __attribute__((unused)) declaration
|
||||
#else
|
||||
# define UV_DESTRUCTOR(declaration) declaration
|
||||
# define UV_UNUSED(declaration) declaration
|
||||
#endif
|
||||
|
||||
@ -138,7 +145,8 @@ typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
|
||||
|
||||
/* loop flags */
|
||||
enum {
|
||||
UV_LOOP_BLOCK_SIGPROF = 1
|
||||
UV_LOOP_BLOCK_SIGPROF = 0x1,
|
||||
UV_LOOP_REAP_CHILDREN = 0x2
|
||||
};
|
||||
|
||||
/* flags of excluding ifaddr */
|
||||
@ -167,11 +175,11 @@ struct uv__stream_queued_fds_s {
|
||||
defined(__linux__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
#define uv__cloexec uv__cloexec_ioctl
|
||||
#define uv__nonblock uv__nonblock_ioctl
|
||||
#define UV__NONBLOCK_IS_IOCTL 1
|
||||
#else
|
||||
#define uv__cloexec uv__cloexec_fcntl
|
||||
#define uv__nonblock uv__nonblock_fcntl
|
||||
#define UV__NONBLOCK_IS_IOCTL 0
|
||||
#endif
|
||||
|
||||
/* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute
|
||||
@ -187,8 +195,7 @@ struct uv__stream_queued_fds_s {
|
||||
#endif
|
||||
|
||||
/* core */
|
||||
int uv__cloexec_ioctl(int fd, int set);
|
||||
int uv__cloexec_fcntl(int fd, int set);
|
||||
int uv__cloexec(int fd, int set);
|
||||
int uv__nonblock_ioctl(int fd, int set);
|
||||
int uv__nonblock_fcntl(int fd, int set);
|
||||
int uv__close(int fd); /* preserves errno */
|
||||
@ -232,14 +239,15 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
|
||||
int uv__accept(int sockfd);
|
||||
int uv__dup2_cloexec(int oldfd, int newfd);
|
||||
int uv__open_cloexec(const char* path, int flags);
|
||||
int uv__slurp(const char* filename, char* buf, size_t len);
|
||||
|
||||
/* tcp */
|
||||
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
|
||||
int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
|
||||
int uv__tcp_nodelay(int fd, int on);
|
||||
int uv__tcp_keepalive(int fd, int on, unsigned int delay);
|
||||
|
||||
/* pipe */
|
||||
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
|
||||
int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
|
||||
|
||||
/* signal */
|
||||
void uv__signal_close(uv_signal_t* handle);
|
||||
@ -250,6 +258,7 @@ int uv__signal_loop_fork(uv_loop_t* loop);
|
||||
/* platform specific */
|
||||
uint64_t uv__hrtime(uv_clocktype_t type);
|
||||
int uv__kqueue_init(uv_loop_t* loop);
|
||||
int uv__epoll_init(uv_loop_t* loop);
|
||||
int uv__platform_loop_init(uv_loop_t* loop);
|
||||
void uv__platform_loop_delete(uv_loop_t* loop);
|
||||
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd);
|
||||
@ -265,11 +274,14 @@ void uv__prepare_close(uv_prepare_t* handle);
|
||||
void uv__process_close(uv_process_t* handle);
|
||||
void uv__stream_close(uv_stream_t* handle);
|
||||
void uv__tcp_close(uv_tcp_t* handle);
|
||||
size_t uv__thread_stack_size(void);
|
||||
void uv__udp_close(uv_udp_t* handle);
|
||||
void uv__udp_finish_close(uv_udp_t* handle);
|
||||
uv_handle_type uv__handle_type(int fd);
|
||||
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);
|
||||
void uv__wait_children(uv_loop_t* loop);
|
||||
|
||||
/* random */
|
||||
int uv__random_devurandom(void* buf, size_t buflen);
|
||||
@ -285,12 +297,6 @@ int uv___stream_fd(const uv_stream_t* handle);
|
||||
#define uv__stream_fd(handle) ((handle)->io_watcher.fd)
|
||||
#endif /* defined(__APPLE__) */
|
||||
|
||||
#ifdef O_NONBLOCK
|
||||
# define UV__F_NONBLOCK O_NONBLOCK
|
||||
#else
|
||||
# define UV__F_NONBLOCK 1
|
||||
#endif
|
||||
|
||||
int uv__make_pipe(int fds[2], int flags);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
@ -330,25 +336,35 @@ int uv__getsockpeername(const uv_handle_t* handle,
|
||||
|
||||
#if defined(__linux__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__)
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__DragonFly__)
|
||||
#define HAVE_MMSG 1
|
||||
struct uv__mmsghdr {
|
||||
struct msghdr msg_hdr;
|
||||
unsigned int msg_len;
|
||||
};
|
||||
|
||||
int uv__recvmmsg(int fd,
|
||||
struct uv__mmsghdr* mmsg,
|
||||
unsigned int vlen,
|
||||
unsigned int flags,
|
||||
struct timespec* timeout);
|
||||
int uv__sendmmsg(int fd,
|
||||
struct uv__mmsghdr* mmsg,
|
||||
unsigned int vlen,
|
||||
unsigned int flags);
|
||||
int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen);
|
||||
int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen);
|
||||
#else
|
||||
#define HAVE_MMSG 0
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
#if !defined(_POSIX_VERSION) || _POSIX_VERSION < 200809L
|
||||
size_t strnlen(const char* s, size_t maxlen);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
ssize_t
|
||||
uv__fs_copy_file_range(int fd_in,
|
||||
off_t* off_in,
|
||||
int fd_out,
|
||||
off_t* off_out,
|
||||
size_t len,
|
||||
unsigned int flags);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* UV_UNIX_INTERNAL_H_ */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user