Delete libuv

pull/11/head
SChernykh 3 years ago
parent 7ac313ee0e
commit 098a29ff29

@ -1 +0,0 @@
test/fixtures/lorem_ipsum.txt text eol=lf

@ -1,13 +0,0 @@
<!--
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/libuv/discussions
If you are reporting a libuv test failure, please ensure that you are not
running the test as root.
Please include code that demonstrates the bug and keep it short and simple.
-->
* **Version**: <!-- libuv version -->
* **Platform**: <!-- `uname -a` (UNIX), or Windows version and machine type -->

@ -1,24 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 21
# 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
# Issues with these labels will never be considered stale
exemptLabels:
- v2
- enhancement
- good first issue
- feature-request
- doc
- bug
- not-stale
# Label to use when marking an issue as stale
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.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

@ -1,69 +0,0 @@
name: CI
on: [push, pull_request]
jobs:
build-android:
runs-on: ubuntu-latest
container: reactnativecommunity/react-native-android:2020-5-20
steps:
- uses: actions/checkout@v2
- name: Envinfo
run: npx envinfo
- name: 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-21 ..
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake --build .
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

@ -1,17 +0,0 @@
name: Sanitizer checks
on: [push, pull_request]
jobs:
asan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Envinfo
run: npx envinfo
- name: ASAN
run: |
mkdir build
cd build && cmake .. -DBUILD_TESTING=ON -DASAN=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build . && ./uv_run_tests_a

@ -1,76 +0,0 @@
*.swp
*.[oa]
*.l[oa]
*.opensdf
*.orig
*.pyc
*.sdf
*.suo
.vs/
*.VC.db
*.VC.opendb
core
vgcore.*
.buildstamp
.dirstamp
.deps/
/.libs/
/aclocal.m4
/ar-lib
/autom4te.cache/
/compile
/config.guess
/config.log
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/libuv.a
/libuv.dylib
/libuv.pc
/libuv.so
/ltmain.sh
/missing
/test-driver
Makefile
Makefile.in
/build/
/test/.libs/
/test/run-tests
/test/run-tests.exe
/test/run-tests.dSYM
/test/run-benchmarks
/test/run-benchmarks.exe
/test/run-benchmarks.dSYM
test_file_*
*.sln
*.sln.cache
*.ncb
*.vcproj
*.vcproj*.user
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
_UpgradeReport_Files/
UpgradeLog*.XML
Debug
Release
ipch
# sphinx generated files
/docs/build/
# Clion / IntelliJ project files
/.idea/
cmake-build-debug/
*.xcodeproj
*.xcworkspace
# make dist output
libuv-*.tar.*

@ -1,60 +0,0 @@
A. Hauptmann <andreashauptmann@t-online.de>
Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
Andy Fiddaman <andy@omniosce.org> <omnios@citrus-it.co.uk>
Bert Belder <bertbelder@gmail.com> <i@bertbelder.com>
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>
Brian White <mscdex@mscdex.net>
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr>
Christoph Iserlohn <christoph.iserlohn@innoq.com>
Darshan Sen <raisinten@gmail.com>
David Carlier <devnexen@gmail.com>
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
Frank Denis <github@pureftpd.org>
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>
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>
Leith Bade <leith@leithalweapon.geek.nz> <leith@mapbox.com>
Leonard Hecker <leonard.hecker91@gmail.com> <leonard@hecker.io>
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>
Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
San-Tai Hsu <vanilla@fatpipi.com>
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>
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>

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

@ -1,481 +0,0 @@
# Authors ordered by first contribution.
Ryan Dahl <ryan@joyent.com>
Bert Belder <bertbelder@gmail.com>
Josh Roesslein <jroesslein@gmail.com>
Alan Gutierrez <alan@prettyrobots.com>
Joshua Peek <josh@joshpeek.com>
Igor Zinkovsky <igorzi@microsoft.com>
San-Tai Hsu <vanilla@fatpipi.com>
Ben Noordhuis <info@bnoordhuis.nl>
Henry Rawas <henryr@schakra.com>
Robert Mustacchi <rm@joyent.com>
Matt Stevens <matt@alloysoft.com>
Paul Querna <pquerna@apache.org>
Shigeki Ohtsu <ohtsu@iij.ad.jp>
Tom Hughes <tom.hughes@palm.com>
Peter Bright <drpizza@quiscalusmexicanus.org>
Jeroen Janssen <jeroen.janssen@gmail.com>
Andrea Lattuada <ndr.lattuada@gmail.com>
Augusto Henrique Hentz <ahhentz@gmail.com>
Clifford Heath <clifford.heath@gmail.com>
Jorge Chamorro Bieling <jorge@jorgechamorro.com>
Luis Lavena <luislavena@gmail.com>
Matthew Sporleder <msporleder@gmail.com>
Erick Tryzelaar <erick.tryzelaar@gmail.com>
Isaac Z. Schlueter <i@izs.me>
Pieter Noordhuis <pcnoordhuis@gmail.com>
Marek Jelen <marek@jelen.biz>
Fedor Indutny <fedor.indutny@gmail.com>
Saúl Ibarra Corretgé <saghul@gmail.com>
Felix Geisendörfer <felix@debuggable.com>
Yuki Okumura <mjt@cltn.org>
Roman Shtylman <shtylman@gmail.com>
Frank Denis <github@pureftpd.org>
Carter Allen <CarterA@opt-6.com>
Tj Holowaychuk <tj@vision-media.ca>
Shimon Doodkin <helpmepro1@gmail.com>
Ryan Emery <seebees@gmail.com>
Bruce Mitchener <bruce.mitchener@gmail.com>
Maciej Małecki <maciej.malecki@notimplemented.org>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
Daisuke Murase <typester@cpan.org>
Paddy Byers <paddy.byers@gmail.com>
Dan VerWeire <dverweire@gmail.com>
Brandon Benvie <brandon@bbenvie.com>
Brandon Philips <brandon.philips@rackspace.com>
Nathan Rajlich <nathan@tootallnate.net>
Charlie McConnell <charlie@charlieistheman.com>
Vladimir Dronnikov <dronnikov@gmail.com>
Aaron Bieber <qbit@deftly.net>
Bulat Shakirzyanov <mallluhuct@gmail.com>
Brian White <mscdex@mscdex.net>
Erik Dubbelboer <erik@dubbelboer.com>
Keno Fischer <kenof@stanford.edu>
Ira Cooper <Ira.Cooper@mathworks.com>
Andrius Bentkus <andrius.bentkus@gmail.com>
Iñaki Baz Castillo <ibc@aliax.net>
Mark Cavage <mark.cavage@joyent.com>
George Yohng <georgegh@oss3d.com>
Xidorn Quan <quanxunzhen@gmail.com>
Roman Neuhauser <rneuhauser@suse.cz>
Shuhei Tanuma <shuhei.tanuma@gmail.com>
Bryan Cantrill <bcantrill@acm.org>
Trond Norbye <trond.norbye@gmail.com>
Tim Holy <holy@wustl.edu>
Prancesco Pertugio <meh@schizofreni.co>
Leonard Hecker <leonard.hecker91@gmail.com>
Andrew Paprocki <andrew@ishiboo.com>
Luigi Grilli <luigi.grilli@gmail.com>
Shannen Saez <shannenlaptop@gmail.com>
Artur Adib <arturadib@gmail.com>
Hiroaki Nakamura <hnakamur@gmail.com>
Ting-Yu Lin <ph.minamo@cytisan.com>
Stephen Gallagher <sgallagh@redhat.com>
Shane Holloway <shane.holloway@ieee.org>
Andrew Shaffer <darawk@gmail.com>
Vlad Tudose <vlad.tudose@intel.com>
Ben Leslie <benno@benno.id.au>
Tim Bradshaw <tfb@cley.com>
Timothy J. Fontaine <tjfontaine@gmail.com>
Marc Schlaich <marc.schlaich@googlemail.com>
Brian Mazza <louseman@gmail.com>
Elliot Saba <staticfloat@gmail.com>
Ben Kelly <ben@wanderview.com>
Nils Maier <maierman@web.de>
Nicholas Vavilov <vvnicholas@gmail.com>
Miroslav Bajtoš <miro.bajtos@gmail.com>
Sean Silva <chisophugis@gmail.com>
Wynn Wilkes <wynnw@movenetworks.com>
Andrei Sedoi <bsnote@gmail.com>
Alex Crichton <alex@alexcrichton.com>
Brent Cook <brent@boundary.com>
Brian Kaisner <bkize1@gmail.com>
Luca Bruno <lucab@debian.org>
Reini Urban <rurban@cpanel.net>
Maks Naumov <maksqwe1@ukr.net>
Sean Farrell <sean.farrell@rioki.org>
Chris Bank <cbank@adobe.com>
Geert Jansen <geertj@gmail.com>
Christoph Iserlohn <christoph.iserlohn@innoq.com>
Steven Kabbes <stevenkabbes@gmail.com>
Alex Gaynor <alex.gaynor@gmail.com>
huxingyi <huxingyi@msn.com>
Tenor Biel <tenorbiel@gmail.com>
Andrej Manduch <AManduch@gmail.com>
Joshua Neuheisel <joshua@neuheisel.us>
Alexis Campailla <alexis@janeasystems.com>
Yazhong Liu <yorkiefixer@gmail.com>
Sam Roberts <vieuxtech@gmail.com>
River Tarnell <river@loreley.flyingparchment.org.uk>
Nathan Sweet <nathanjsweet@gmail.com>
Trevor Norris <trev.norris@gmail.com>
Oguz Bastemur <obastemur@gmail.com>
Dylan Cali <calid1984@gmail.com>
Austin Foxley <austinf@cetoncorp.com>
Benjamin Saunders <ben.e.saunders@gmail.com>
Geoffry Song <goffrie@gmail.com>
William Light <wrl@illest.net>
Oleg Efimov <o.efimov@corp.badoo.com>
Lars Gierth <larsg@systemli.org>
Rasmus Christian Pedersen <zerhacken@yahoo.com>
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>
StarWing <weasley.wx@gmail.com>
thierry-FreeBSD <thierry@FreeBSD.org>
Isaiah Norton <isaiah.norton@gmail.com>
Raul Martins <raulms.martins@gmail.com>
David Capello <davidcapello@gmail.com>
Paul Tan <pyokagan@gmail.com>
Javier Hernández <jhernandez@emergya.com>
Tonis Tiigi <tonistiigi@gmail.com>
Norio Kobota <nori.0428@gmail.com>
李港平 <chopdown@gmail.com>
Chernyshev Viacheslav <astellar@ro.ru>
Stephen von Takach <steve@advancedcontrol.com.au>
JD Ballard <jd@pixelandline.com>
Luka Perkov <luka.perkov@sartura.hr>
Ryan Cole <ryan@rycole.com>
HungMingWu <u9089000@gmail.com>
Jay Satiro <raysatiro@yahoo.com>
Leith Bade <leith@leithalweapon.geek.nz>
Peter Atashian <retep998@gmail.com>
Tim Cooper <tim.cooper@layeh.com>
Caleb James DeLisle <cjd@hyperboria.ca>
Jameson Nash <vtjnash@gmail.com>
Graham Lee <ghmlee@ghmlee.com>
Andrew Low <Andrew_Low@ca.ibm.com>
Pavel Platto <hinidu@gmail.com>
Tony Kelman <tony@kelman.net>
John Firebaugh <john.firebaugh@gmail.com>
lilohuang <lilohuang@hotmail.com>
Paul Goldsmith <paul.goldsmith@aplink.net>
Julien Gilli <julien.gilli@joyent.com>
Michael Hudson-Doyle <michael.hudson@linaro.org>
Recep ASLANTAS <m@recp.me>
Rob Adams <readams@readams.net>
Zachary Newman <znewman01@gmail.com>
Robin Hahling <robin.hahling@gw-computing.net>
Jeff Widman <jeff@jeffwidman.com>
cjihrig <cjihrig@gmail.com>
Tomasz Kołodziejski <tkolodziejski@mozilla.com>
Unknown W. Brackets <checkins@unknownbrackets.org>
Emmanuel Odeke <odeke@ualberta.ca>
Mikhail Mukovnikov <yndi@me.com>
Thorsten Lorenz <thlorenz@gmx.de>
Yuri D'Elia <yuri.delia@eurac.edu>
Manos Nikolaidis <manos@shadowrobot.com>
Elijah Andrews <elijah@busbud.com>
Michael Ira Krufky <m.krufky@samsung.com>
Helge Deller <deller@gmx.de>
Joey Geralnik <jgeralnik@gmail.com>
Tim Caswell <tim@creationix.com>
Logan Rosen <loganrosen@gmail.com>
Kenneth Perry <thothonegan@gmail.com>
John Marino <marino@FreeBSD.org>
Alexey Melnichuk <mimir@newmail.ru>
Johan Bergström <bugs@bergstroem.nu>
Alex Mo <almosnow@gmail.com>
Luis Martinez de Bartolome <lasote@gmail.com>
Michael Penick <michael.penick@datastax.com>
Michael <michael_dawson@ca.ibm.com>
Massimiliano Torromeo <massimiliano.torromeo@gmail.com>
TomCrypto <thomas.beneteau@yahoo.fr>
Brett Vickers <brett@beevik.com>
Ole André Vadla Ravnås <oleavr@gmail.com>
Kazuho Oku <kazuhooku@gmail.com>
Ryan Phillips <ryan.phillips@rackspace.com>
Brian Green <briangreenery@gmail.com>
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
Corey Farrell <git@cfware.com>
Per Nilsson <pni@qlik.com>
Alan Rogers <alanjrogers@me.com>
Daryl Haresign <github@daryl.haresign.com>
Rui Abreu Ferreira <raf-ep@gmx.com>
João Reis <reis@janeasystems.com>
farblue68 <farblue68@gmail.com>
Jason Williams <necmon@yahoo.com>
Igor Soarez <igorsoarez@gmail.com>
Miodrag Milanovic <mmicko@gmail.com>
Cheng Zhao <zcbenz@gmail.com>
Michael Neumann <mneumann@think.localnet>
Stefano Cristiano <stefanocristiano82@gmail.com>
heshamsafi <hesham.safi.eldeen@gmail.com>
A. Hauptmann <andreashauptmann@t-online.de>
John McNamee <jpm@microwiz.com>
Yosuke Furukawa <yosuke.furukawa@gmail.com>
Santiago Gimeno <santiago.gimeno@quantion.es>
guworks <ground.up.works@gmail.com>
RossBencina <rossb@audiomulch.com>
Roger A. Light <roger@atchoo.org>
chenttuuvv <chenttuuvv@yahoo.com>
Richard Lau <rlau@redhat.com>
ronkorving <rkorving@wizcorp.jp>
Corbin Simpson <MostAwesomeDude@gmail.com>
Zachary Hamm <zsh@imipolexg.org>
Karl Skomski <karl@skomski.com>
Jeremy Whitlock <jwhitlock@apache.org>
Willem Thiart <himself@willemthiart.com>
Ben Trask <bentrask@comcast.net>
Jianghua Yang <jianghua.yjh@alibaba-inc.com>
Colin Snover <github.com@zetafleet.com>
Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Eli Skeggs <skeggse@gmail.com>
nmushell <nmushell@bloomberg.net>
Gireesh Punathil <gpunathi@in.ibm.com>
Ryan Johnston <ryan@mediapixel.co.nz>
Adam Stylinski <stylinae@mail.uc.edu>
Nathan Corvino <nathan@corvino.com>
Wink Saville <wink@saville.com>
Angel Leon <gubatron@gmail.com>
Louis DeJardin <lodejard@microsoft.com>
Imran Iqbal <imrani@ca.ibm.com>
Petka Antonov <petka_antonov@hotmail.com>
Ian Kronquist <iankronquist@teleport.com>
kkdaemon <kkdaemon@gmail.com>
Yuval Brik <yuval@brik.org.il>
Joran Dirk Greef <joran@ronomon.com>
Andrey Mazo <andrey.mazo@fidelissecurity.com>
sztomi <hello.sztomi@gmail.com>
Martin Bark <martin@barkynet.com>
Dave <dave@jut.io>
Alexis Murzeau <amubtdx@gmail.com>
Didiet <lynxluna@gmail.com>
Nan Xiang <514580344@qq.com>
Samuel Lorétan <sloretan@riotgames.com>
Nándor István Krácser <bonifaido@gmail.com>
Katsutoshi Horie <mps299792458@gmail.com>
Lukasz Jagiello <lukasz@wikia-inc.com>
Robert Chiras <robert.chiras@intel.com>
Kári Tristan Helgason <kthelgason@gmail.com>
Krishnaraj Bhat <krrishnarraj@gmail.com>
Enno Boland <g@s01.de>
Michael Fero <michael.fero@datastax.com>
Robert Jefe Lindstaedt <robert.lindstaedt@gmail.com>
Myles Borins <myles.borins@gmail.com>
Tony Theodore <tonyt@logyst.com>
Jason Ginchereau <jasongin@microsoft.com>
Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
Pierre-Marie de Rodat <pmderodat@kawie.fr>
Brian Maher <brian@brimworks.com>
neevek <i@neevek.net>
John Barboza <jbarboza@ca.ibm.com>
liuxiaobo <icexile@qq.com>
Michele Caini <michele.caini@gmail.com>
Bartosz Sosnowski <bartosz@janeasystems.com>
Matej Knopp <matej.knopp@gmail.com>
sunjin.lee <kod21236@gmail.com>
Matt Clarkson <mattyclarkson@gmail.com>
Jeffrey Clark <dude@zaplabs.com>
Bart Robinson <bartarr@gmail.com>
Vit Gottwald <vit.gottwald@gmail.com>
Vladimír Čunát <vladimir.cunat@nic.cz>
Alex Hultman <alexhultman@gmail.com>
Brad King <brad.king@kitware.com>
Philippe Laferriere <laferriere.phil@gmail.com>
Will Speak <lithiumflame@gmail.com>
Hitesh Kanwathirtha <digitalinfinity@gmail.com>
Eric Sciple <ersciple@microsoft.com>
jBarz <jBarz@users.noreply.github.com>
muflub <admin@lodle.net>
Daniel Bevenius <daniel.bevenius@gmail.com>
Howard Hellyer <hhellyer@uk.ibm.com>
Chris Araman <chris.araman@fuze.com>
Vladimir Matveev <vladima@microsoft.com>
Jason Madden <jamadden@gmail.com>
Jamie Davis <davisjam@vt.edu>
Daniel Kahn Gillmor <dkg@fifthhorseman.net>
Keane <erich.keane@intel.com>
James McCoy <jamessan@jamessan.com>
Bernardo Ramos <berna.gensis@gmail.com>
Juan Cruz Viotti <jviotti@openmailbox.org>
Gemini Wen <geminiwen@aliyun.com>
Sebastian Wiedenroth <wiedi@frubar.net>
Sai Ke WANG <swang304@bloomberg.net>
Barnabas Gema <gema.barnabas@gmail.com>
Romain Caire <romain@blade-group.com>
Robert Ayrapetyan <robert.ayrapetyan@gmail.com>
Refael Ackermann <refack@gmail.com>
André Klitzing <aklitzing@gmail.com>
Matthew Taylor <mstaveleytaylor@gmail.com>
CurlyMoo <curlymoo1@gmail.com>
XadillaX <admin@xcoder.in>
Anticrisis <anticrisisg@gmail.com>
Jacob Segal <jacob.e.segal@gmail.com>
Maciej Szeptuch (Neverous) <neverous@neverous.info>
Joel Winarske <joel.winarske@inrix.com>
Gergely Nagy <ngg@tresorit.com>
Kamil Rytarowski <n54@gmx.com>
tux.uudiin <77389867@qq.com>
Nick Logan <ugexe@cpan.org>
darobs <darobs@microsoft.com>
Zheng, Lei <realthunder.dev@gmail.com>
Carlo Marcelo Arenas Belón <carenas@gmail.com>
Scott Parker <scott.parker087@gmail.com>
Wade Brainerd <Wade.Brainerd@activision.com>
rayrase <rmartinez2175@eagle.fgcu.edu>
Pekka Nikander <pekka.nikander@iki.fi>
Ed Schouten <ed@nuxi.nl>
Xu Meng <mengxumx@cn.ibm.com>
Matt Harrison <hi@matt-harrison.com>
Anna Henningsen <anna@addaleax.net>
Jérémy Lal <kapouer@melix.org>
Ben Wijen <ben@wijen.net>
elephantp <elephantp@elephantp.blog>
Felix Yan <felixonmars@archlinux.org>
Mason X <me@masonx.ca>
Jesse Gorzinski <jgorzinski@gmail.com>
Ryuichi KAWAMATA <ryuichi.kawamata@dena.jp>
Joyee Cheung <joyeec9h3@gmail.com>
Michael Kilburn <crusader.mike@gmail.com>
Ruslan Bekenev <furyinbox@gmail.com>
Bob Burger <rgburger@beckman.com>
Thomas Versteeg <thomasversteeg@gmx.com>
zzzjim <zzzjim@users.noreply.github.com>
Alex Arslan <ararslan@comcast.net>
Kyle Farnung <kfarnung@microsoft.com>
ssrlive <30760636+ssrlive@users.noreply.github.com>
Tobias Nießen <tniessen@tnie.de>
Björn Linse <bjorn.linse@gmail.com>
zyxwvu Shi <i@shiyc.cn>
Peter Johnson <johnson.peter@gmail.com>
Paolo Greppi <paolo.greppi@libpf.com>
Shelley Vohr <shelley.vohr@gmail.com>
Ujjwal Sharma <usharma1998@gmail.com>
Michał Kozakiewicz <michalkozakiewicz3@gmail.com>
Emil Bay <github@tixz.dk>
Jeremiah Senkpiel <fishrock123@rocketmail.com>
Andy Zhang <zhangyong232@gmail.com>
dmabupt <dmabupt@gmail.com>
Ryan Liptak <squeek502@hotmail.com>
Ali Ijaz Sheikh <ofrobots@google.com>
hitesh <sainihitesh.scientist@gmail.com>
Svante Signell <svante.signell@gmail.com>
Samuel Thibault <sthibault@debian.org>
Jeremy Studer <studerj1.mail@gmail.com>
damon-kwok <563066990@qq.com>
Damon Kwok <MedusaIDE@outlook.com>
Ashe Connor <ashe@kivikakk.ee>
Rick <lcw0622@163.com>
Ivan Krylov <krylov.r00t@gmail.com>
Michael Meier <michael.meier@leica-geosystems.com>
ptlomholt <pt@lomholt.com>
Victor Costan <pwnall@chromium.org>
sid <sidyhe@hotmail.com>
Kevin Adler <kadler@us.ibm.com>
Stephen Belanger <admin@stephenbelanger.com>
yeyuanfeng <yeyuanfeng@bytedance.com>
erw7 <erw7.github@gmail.com>
Thomas Karl Pietrowski <thopiekar@gmail.com>
evgley <evgley@gmail.com>
Andreas Rohner <andreas.rohner@gmx.net>
Rich Trott <rtrott@gmail.com>
Milad Farazmand <miladfar@ca.ibm.com>
zlargon <zlargon1988@gmail.com>
Yury Selivanov <yury@magic.io>
Oscar Waddell <owaddell@beckman.com>
FX Coudert <fxcoudert@gmail.com>
George Zhao <zhaozg@gmail.com>
Kyle Edwards <kyle.edwards@kitware.com>
ken-cunningham-webuse <ken.cunningham.webuse@gmail.com>
Kelvin Jin <kelvinjin@google.com>
Leorize <leorize+oss@disroot.org>
Vlad A <vladmore@gmail.com>
Niels Lohmann <mail@nlohmann.me>
Jenil Christo <jenilchristo5@gmail.com>
Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
gengjiawen <technicalcute@gmail.com>
Leo Chung <gewalalb@gmail.com>
Javier Blazquez <jblazquez@riotgames.com>
Mustafa M <mus-m@outlook.com>
Zach Bjornson <zbbjornson@gmail.com>
Nan Xiao <nan@chinadtrace.org>
Ben Davies <kaiepi@outlook.com>
Nhan Khong <knhana7@gmail.com>
Crunkle <justcrunkle@hotmail.co.uk>
Tomas Krizek <tomas.krizek@nic.cz>
Konstantin Podsvirov <konstantin@podsvirov.pro>
seny <arseny.vakhrushev@gmail.com>
Vladimir Karnushin <v.karnushin@mail.ru>
MaYuming <maym@appexnetworks.com>
Eneas U de Queiroz <cotequeiroz@gmail.com>
Daniel Hahler <git@thequod.de>
Yang Yu <yang.yu@disigma.org>
David Carlier <devnexen@gmail.com>
Calvin Hill <calvin@hakobaito.co.uk>
Isabella Muerte <63051+slurps-mad-rips@users.noreply.github.com>
Ouyang Yadong <oyydoibh@gmail.com>
ZYSzys <zyszys98@gmail.com>
Carl Lei <xecycle@gmail.com>
Stefan Bender <stefan.bender@ntnu.no>
nia <nia@NetBSD.org>
virtualyw <virtualyw@gmail.com>
Witold Kręcicki <wpk@isc.org>
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>

@ -1,670 +0,0 @@
cmake_minimum_required(VERSION 3.4)
project(libuv LANGUAGES C)
cmake_policy(SET CMP0057 NEW) # Enable IN_LIST operator
cmake_policy(SET CMP0064 NEW) # Support if (TEST) operator
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(CheckCCompilerFlag)
include(GNUInstallDirs)
include(CTest)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_C_STANDARD 90)
cmake_dependent_option(LIBUV_BUILD_TESTS
"Build the unit tests when BUILD_TESTING is enabled and we are the root project" ON
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
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)
if(ASAN AND CMAKE_C_COMPILER_ID MATCHES "AppleClang|GNU|Clang")
add_definitions(-D__ASAN__=1)
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
endif()
# Compiler check
string(CONCAT is-msvc $<OR:
$<C_COMPILER_ID:MSVC>,
$<STREQUAL:${CMAKE_C_COMPILER_FRONTEND_VARIANT},MSVC>
>)
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
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)
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
src/idna.c
src/inet.c
src/random.c
src/strscpy.c
src/threadpool.c
src/timer.c
src/uv-common.c
src/uv-data-getter-setters.c
src/version.c)
if(WIN32)
list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602)
list(APPEND uv_libraries
psapi
user32
advapi32
iphlpapi
userenv
ws2_32)
list(APPEND uv_sources
src/win/async.c
src/win/core.c
src/win/detect-wakeup.c
src/win/dl.c
src/win/error.c
src/win/fs.c
src/win/fs-event.c
src/win/getaddrinfo.c
src/win/getnameinfo.c
src/win/handle.c
src/win/loop-watcher.c
src/win/pipe.c
src/win/thread.c
src/win/poll.c
src/win/process.c
src/win/process-stdio.c
src/win/signal.c
src/win/snprintf.c
src/win/stream.c
src/win/tcp.c
src/win/tty.c
src/win/udp.c
src/win/util.c
src/win/winapi.c
src/win/winsock.c)
list(APPEND uv_test_libraries ws2_32)
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 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.
list(APPEND uv_libraries pthread)
endif()
list(APPEND uv_sources
src/unix/async.c
src/unix/core.c
src/unix/dl.c
src/unix/fs.c
src/unix/getaddrinfo.c
src/unix/getnameinfo.c
src/unix/loop-watcher.c
src/unix/loop.c
src/unix/pipe.c
src/unix/poll.c
src/unix/process.c
src/unix/random-devurandom.c
src/unix/signal.c
src/unix/stream.c
src/unix/tcp.c
src/unix/thread.c
src/unix/tty.c
src/unix/udp.c)
list(APPEND uv_test_sources test/runner-unix.c)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
list(APPEND uv_defines
_ALL_SOURCE
_LINUX_SOURCE_COMPAT
_THREAD_SAFE
_XOPEN_SOURCE=500
HAVE_SYS_AHAFS_EVPRODS_H)
list(APPEND uv_libraries perfstat)
list(APPEND uv_sources
src/unix/aix.c
src/unix/aix-common.c)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
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
src/unix/procfs-exepath.c
src/unix/pthread-fixes.c
src/unix/random-getentropy.c
src/unix/random-getrandom.c
src/unix/random-sysctl-linux.c
src/unix/epoll.c)
endif()
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux")
list(APPEND uv_sources src/unix/proctitle.c)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
list(APPEND uv_sources src/unix/freebsd.c)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
list(APPEND uv_sources src/unix/posix-hrtime.c src/unix/bsd-proctitle.c)
endif()
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
list(APPEND uv_sources src/unix/bsd-ifaddrs.c src/unix/kqueue.c)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
list(APPEND uv_sources src/unix/random-getrandom.c)
endif()
if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
list(APPEND uv_sources src/unix/random-getentropy.c)
endif()
if(APPLE)
list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1)
list(APPEND uv_sources
src/unix/darwin-proctitle.c
src/unix/darwin.c
src/unix/fsevents.c)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112)
list(APPEND uv_libraries dl rt)
list(APPEND uv_sources
src/unix/linux-core.c
src/unix/linux-inotify.c
src/unix/linux-syscalls.c
src/unix/procfs-exepath.c
src/unix/random-getrandom.c
src/unix/random-sysctl-linux.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 "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)
list(APPEND uv_defines _OPEN_SYS_IF_EXT)
list(APPEND uv_defines _OPEN_SYS_SOCK_EXT3)
list(APPEND uv_defines _OPEN_SYS_SOCK_IPV6)
list(APPEND uv_defines _UNIX03_SOURCE)
list(APPEND uv_defines _UNIX03_THREADS)
list(APPEND uv_defines _UNIX03_WITHDRAWN)
list(APPEND uv_defines _XOPEN_SOURCE=600)
list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED)
list(APPEND uv_sources
src/unix/pthread-fixes.c
src/unix/os390.c
src/unix/os390-syscalls.c
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 _REENTRANT)
list(APPEND uv_libraries kstat nsl sendfile socket)
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")
list(APPEND uv_test_libraries util)
endif()
add_library(uv SHARED ${uv_sources})
target_compile_definitions(uv
INTERFACE
USING_UV_SHARED=1
PRIVATE
BUILDING_UV_SHARED=1
${uv_defines})
target_compile_options(uv PRIVATE ${uv_cflags})
target_include_directories(uv
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<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})
target_compile_definitions(uv_a PRIVATE ${uv_defines})
target_compile_options(uv_a PRIVATE ${uv_cflags})
target_include_directories(uv_a
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<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-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/dns-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
test/run-tests.c
test/runner.c
test/test-active.c
test/test-async-null-cb.c
test/test-async.c
test/test-barrier.c
test/test-callback-order.c
test/test-callback-stack.c
test/test-close-fd.c
test/test-close-order.c
test/test-condvar.c
test/test-connect-unspecified.c
test/test-connection-fail.c
test/test-cwd-and-chdir.c
test/test-default-loop-close.c
test/test-delayed-accept.c
test/test-dlerror.c
test/test-eintr-handling.c
test/test-embed.c
test/test-emfile.c
test/test-env-vars.c
test/test-error.c
test/test-fail-always.c
test/test-fork.c
test/test-fs-copyfile.c
test/test-fs-event.c
test/test-fs-poll.c
test/test-fs.c
test/test-fs-readdir.c
test/test-fs-fd-hash.c
test/test-fs-open-flags.c
test/test-get-currentexe.c
test/test-get-loadavg.c
test/test-get-memory.c
test/test-get-passwd.c
test/test-getaddrinfo.c
test/test-gethostname.c
test/test-getnameinfo.c
test/test-getsockname.c
test/test-getters-setters.c
test/test-gettimeofday.c
test/test-handle-fileno.c
test/test-homedir.c
test/test-hrtime.c
test/test-idle.c
test/test-idna.c
test/test-ip4-addr.c
test/test-ip6-addr.c
test/test-ipc-heavy-traffic-deadlock-bug.c
test/test-ipc-send-recv.c
test/test-ipc.c
test/test-loop-alive.c
test/test-loop-close.c
test/test-loop-configure.c
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-readable-on-eof.c
test/test-not-writable-after-shutdown.c
test/test-osx-select.c
test/test-pass-always.c
test/test-ping-pong.c
test/test-pipe-bind-error.c
test/test-pipe-close-stdout-read-stdin.c
test/test-pipe-connect-error.c
test/test-pipe-connect-multiple.c
test/test-pipe-connect-prepare.c
test/test-pipe-getsockname.c
test/test-pipe-pending-instances.c
test/test-pipe-sendmsg.c
test/test-pipe-server-close.c
test/test-pipe-set-fchmod.c
test/test-pipe-set-non-blocking.c
test/test-platform-output.c
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
test/test-process-title-threadsafe.c
test/test-process-title.c
test/test-queue-foreach-delete.c
test/test-random.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
test/test-signal.c
test/test-socket-buffer-size.c
test/test-spawn.c
test/test-stdio-over-pipes.c
test/test-strscpy.c
test/test-tcp-alloc-cb-fail.c
test/test-tcp-bind-error.c
test/test-tcp-bind6-error.c
test/test-tcp-close-accept.c
test/test-tcp-close-while-connecting.c
test/test-tcp-close.c
test/test-tcp-close-reset.c
test/test-tcp-connect-error-after-write.c
test/test-tcp-connect-error.c
test/test-tcp-connect-timeout.c
test/test-tcp-connect6-error.c
test/test-tcp-create-socket-early.c
test/test-tcp-flags.c
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
test/test-tcp-unexpected-read.c
test/test-tcp-write-after-connect.c
test/test-tcp-write-fail.c
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
test/test-threadpool.c
test/test-timer-again.c
test/test-timer-from-check.c
test/test-timer.c
test/test-tmpdir.c
test/test-tty-duplicate-key.c
test/test-tty-escape-sequence-processing.c
test/test-tty.c
test/test-udp-alloc-cb-fail.c
test/test-udp-bind.c
test/test-udp-connect.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
test/test-udp-multicast-join6.c
test/test-udp-multicast-ttl.c
test/test-udp-open.c
test/test-udp-options.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
test/test-walk-handles.c
test/test-watcher-cross-stop.c)
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})
target_link_libraries(uv_run_tests uv ${uv_test_libraries})
add_test(NAME uv_test
COMMAND uv_run_tests
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
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})
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 OR MINGW)
# 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 ${PROJECT_BINARY_DIR}/libuv-static.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
if(MSVC)
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}
CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
")

@ -1,171 +0,0 @@
# CONTRIBUTING
The libuv project welcomes new contributors. This document will guide you
through the process.
### FORK
Fork the project [on GitHub](https://github.com/libuv/libuv) and check out
your copy.
```
$ git clone https://github.com/username/libuv.git
$ cd libuv
$ git remote add upstream https://github.com/libuv/libuv.git
```
Now decide if you want your feature or bug fix to go into the master branch
or the stable branch. As a rule of thumb, bug fixes go into the stable branch
while new features go into the master branch.
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 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 the [project maintainers].
### BRANCH
Okay, so you have decided on the proper branch. Create a feature branch
and start hacking:
```
$ git checkout -b my-feature-branch -t origin/v1.x
```
(Where v1.x is the latest stable branch as of this writing.)
### CODE
Please adhere to libuv's code style. In general it follows the conventions from
the [Google C/C++ style guide]. Some of the key points, as well as some
additional guidelines, are enumerated below.
* Code that is specific to unix-y platforms should be placed in `src/unix`, and
declarations go into `include/uv/unix.h`.
* Source code that is Windows-specific goes into `src/win`, and related
publicly exported types, functions and macro declarations should generally
be declared in `include/uv/win.h`.
* Names should be descriptive and concise.
* All the symbols and types that libuv makes available publicly should be
prefixed with `uv_` (or `UV_` in case of macros).
* Internal, non-static functions should be prefixed with `uv__`.
* Use two spaces and no tabs.
* Lines should be wrapped at 80 characters.
* Ensure that lines have no trailing whitespace, and use unix-style (LF) line
endings.
* Use C89-compliant syntax. In other words, variables can only be declared at
the top of a scope (function, if/for/while-block).
* When writing comments, use properly constructed sentences, including
punctuation.
* When documenting APIs and/or source code, don't make assumptions or make
implications about race, gender, religion, political orientation or anything
else that isn't relevant to the project.
* Remember that source code usually gets written once and read often: ensure
the reader doesn't have to make guesses. Make sure that the purpose and inner
logic are either obvious to a reasonably skilled professional, or add a
comment that explains it.
### COMMIT
Make sure git knows your name and email address:
```
$ git config --global user.name "J. Random User"
$ git config --global user.email "j.random.user@example.com"
```
Writing good commit logs is important. A commit log should describe what
changed and why. Follow these guidelines when writing one:
1. The first line should be 50 characters or less and contain a short
description of the change prefixed with the name of the changed
subsystem (e.g. "net: add localAddress and localPort to Socket").
2. Keep the second line blank.
3. Wrap all other lines at 72 columns.
A good commit log looks like this:
```
subsystem: explaining the commit in one line
Body of commit message is a few lines of text, explaining things
in more detail, possibly giving some background about the issue
being fixed, etc etc.
The body of the commit message can be several paragraphs, and
please do proper word-wrap and keep columns shorter than about
72 characters or so. That way `git log` will show things
nicely even when it is indented.
```
The header line should be meaningful; it is what other people see when they
run `git shortlog` or `git log --oneline`.
Check the output of `git log --oneline files_that_you_changed` to find out
what subsystem (or subsystems) your changes touch.
### REBASE
Use `git rebase` (not `git merge`) to sync your work from time to time.
```
$ git fetch upstream
$ git rebase upstream/v1.x # or upstream/master
```
### TEST
Bug fixes and features should come with tests. Add your tests in the
`test/` directory. Each new test needs to be registered in `test/test-list.h`.
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.
Look at other tests to see how they should be structured (license boilerplate,
the way entry points are declared, etc.).
Check README.md file to find out how to run the test suite and make sure that
there are no test regressions.
### PUSH
```
$ git push origin my-feature-branch
```
Go to https://github.com/username/libuv and select your feature branch. Click
the 'Pull Request' button and fill out the form.
Pull requests are usually reviewed within a few days. If there are comments
to address, apply your changes in a separate commit and push that to your
feature branch. Post a comment in the pull request afterwards; GitHub does
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
[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

File diff suppressed because it is too large Load Diff

@ -1,70 +0,0 @@
libuv is licensed for use as follows:
====
Copyright (c) 2015-present libuv project contributors.
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.
====
This license applies to parts of libuv originating from the
https://github.com/joyent/libuv repository:
====
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
====
This license applies to all parts of libuv that are not externally
maintained libraries.
The externally maintained libraries used by libuv are:
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
- inet_pton and inet_ntop implementations, contained in src/inet.c, are
copyright the Internet Systems Consortium, Inc., and licensed under the ISC
license.
- stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
clause BSD license.
- 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.

@ -1,396 +0,0 @@
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

@ -1,101 +0,0 @@
### 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)

@ -1,51 +0,0 @@
# Project Maintainers
libuv is currently managed by the following individuals:
* **Anna Henningsen** ([@addaleax](https://github.com/addaleax))
* **Bartosz Sosnowski** ([@bzoz](https://github.com/bzoz))
* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis))
- GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis)
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
* **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig))
- GPG key: 94AE 3667 5C46 4D64 BAFA 68DD 7434 390B DBE9 B9C5 (pubkey-cjihrig)
- GPG key: 5735 3E0D BDAA A7E8 39B6 6A1A FF47 D5E4 AD8B 4FDC (pubkey-cjihrig-kb)
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
* **Jameson Nash** ([@vtjnash](https://github.com/vtjnash))
- GPG key: AEAD 0A4B 6867 6775 1A0E 4AEF 34A2 5FB1 2824 6514 (pubkey-vtjnash)
* **John Barboza** ([@jbarz](https://github.com/jbarz))
* **Kaoru Takanashi** ([@erw7](https://github.com/erw7))
- GPG Key: 5804 F999 8A92 2AFB A398 47A0 7183 5090 6134 887F (pubkey-erw7)
* **Richard Lau** ([@richardlau](https://github.com/richardlau))
- GPG key: C82F A3AE 1CBE DC6B E46B 9360 C43C EC45 C17A B93C (pubkey-richardlau)
* **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno))
- GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno)
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
- GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul)
## Storing a maintainer key in Git
It's quite handy to store a maintainer's signature as a git blob, and have
that object tagged and signed with such key.
Export your public key:
$ gpg --armor --export saghul@gmail.com > saghul.asc
Store it as a blob on the repo:
$ git hash-object -w saghul.asc
The previous command returns a hash, copy it. For the sake of this explanation,
we'll assume it's 'abcd1234'. Storing the blob in git is not enough, it could
be garbage collected since nothing references it, so we'll create a tag for it:
$ git tag -s pubkey-saghul abcd1234
Commit the changes and push:
$ git push origin pubkey-saghul

@ -1,549 +0,0 @@
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_srcdir)/src
include_HEADERS=include/uv.h
uvincludedir = $(includedir)/uv
uvinclude_HEADERS = include/uv/errno.h \
include/uv/threadpool.h \
include/uv/version.h
CLEANFILES =
lib_LTLIBRARIES = libuv.la
libuv_la_CFLAGS = @CFLAGS@
libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0
libuv_la_SOURCES = src/fs-poll.c \
src/heap-inl.h \
src/idna.c \
src/idna.h \
src/inet.c \
src/queue.h \
src/random.c \
src/strscpy.c \
src/strscpy.h \
src/threadpool.c \
src/timer.c \
src/uv-data-getter-setters.c \
src/uv-common.c \
src/uv-common.h \
src/version.c
if SUNOS
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
# on other platforms complain that the argument is unused during compilation.
libuv_la_CFLAGS += -pthreads
endif
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=0x0602
libuv_la_SOURCES += src/win/async.c \
src/win/atomicops-inl.h \
src/win/core.c \
src/win/detect-wakeup.c \
src/win/dl.c \
src/win/error.c \
src/win/fs-event.c \
src/win/fs.c \
src/win/getaddrinfo.c \
src/win/getnameinfo.c \
src/win/handle.c \
src/win/handle-inl.h \
src/win/internal.h \
src/win/loop-watcher.c \
src/win/pipe.c \
src/win/poll.c \
src/win/process-stdio.c \
src/win/process.c \
src/win/req-inl.h \
src/win/signal.c \
src/win/stream.c \
src/win/stream-inl.h \
src/win/tcp.c \
src/win/thread.c \
src/win/tty.c \
src/win/udp.c \
src/win/util.c \
src/win/winapi.c \
src/win/winapi.h \
src/win/winsock.c \
src/win/winsock.h
else # WINNT
uvinclude_HEADERS += include/uv/unix.h
AM_CPPFLAGS += -I$(top_srcdir)/src/unix
libuv_la_SOURCES += src/unix/async.c \
src/unix/atomic-ops.h \
src/unix/core.c \
src/unix/dl.c \
src/unix/fs.c \
src/unix/getaddrinfo.c \
src/unix/getnameinfo.c \
src/unix/internal.h \
src/unix/loop-watcher.c \
src/unix/loop.c \
src/unix/pipe.c \
src/unix/poll.c \
src/unix/process.c \
src/unix/random-devurandom.c \
src/unix/signal.c \
src/unix/spinlock.h \
src/unix/stream.c \
src/unix/tcp.c \
src/unix/thread.c \
src/unix/tty.c \
src/unix/udp.c
endif # WINNT
EXTRA_DIST = test/fixtures/empty_file \
test/fixtures/load_error.node \
test/fixtures/lorem_ipsum.txt \
include \
docs \
img \
CONTRIBUTING.md \
LICENSE \
README.md
TESTS = test/run-tests
check_PROGRAMS = test/run-tests
test_run_tests_CFLAGS =
if SUNOS
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
# on other platforms complain that the argument is unused during compilation.
test_run_tests_CFLAGS += -pthreads
endif
test_run_tests_LDFLAGS =
test_run_tests_SOURCES = test/blackhole-server.c \
test/dns-server.c \
test/echo-server.c \
test/run-tests.c \
test/runner.c \
test/runner.h \
test/task.h \
test/test-active.c \
test/test-async.c \
test/test-async-null-cb.c \
test/test-barrier.c \
test/test-callback-order.c \
test/test-callback-stack.c \
test/test-close-fd.c \
test/test-close-order.c \
test/test-condvar.c \
test/test-connect-unspecified.c \
test/test-connection-fail.c \
test/test-cwd-and-chdir.c \
test/test-default-loop-close.c \
test/test-delayed-accept.c \
test/test-dlerror.c \
test/test-eintr-handling.c \
test/test-embed.c \
test/test-emfile.c \
test/test-env-vars.c \
test/test-error.c \
test/test-fail-always.c \
test/test-fs-copyfile.c \
test/test-fs-event.c \
test/test-fs-poll.c \
test/test-fs.c \
test/test-fs-readdir.c \
test/test-fs-fd-hash.c \
test/test-fs-open-flags.c \
test/test-fork.c \
test/test-getters-setters.c \
test/test-get-currentexe.c \
test/test-get-loadavg.c \
test/test-get-memory.c \
test/test-get-passwd.c \
test/test-getaddrinfo.c \
test/test-gethostname.c \
test/test-getnameinfo.c \
test/test-getsockname.c \
test/test-gettimeofday.c \
test/test-handle-fileno.c \
test/test-homedir.c \
test/test-hrtime.c \
test/test-idle.c \
test/test-idna.c \
test/test-ip4-addr.c \
test/test-ip6-addr.c \
test/test-ipc-heavy-traffic-deadlock-bug.c \
test/test-ipc-send-recv.c \
test/test-ipc.c \
test/test-list.h \
test/test-loop-handles.c \
test/test-loop-alive.c \
test/test-loop-close.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-readable-on-eof.c \
test/test-not-writable-after-shutdown.c \
test/test-osx-select.c \
test/test-pass-always.c \
test/test-ping-pong.c \
test/test-pipe-bind-error.c \
test/test-pipe-connect-error.c \
test/test-pipe-connect-multiple.c \
test/test-pipe-connect-prepare.c \
test/test-pipe-getsockname.c \
test/test-pipe-pending-instances.c \
test/test-pipe-sendmsg.c \
test/test-pipe-server-close.c \
test/test-pipe-close-stdout-read-stdin.c \
test/test-pipe-set-non-blocking.c \
test/test-pipe-set-fchmod.c \
test/test-platform-output.c \
test/test-poll.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-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 \
test/test-signal.c \
test/test-socket-buffer-size.c \
test/test-spawn.c \
test/test-stdio-over-pipes.c \
test/test-strscpy.c \
test/test-tcp-alloc-cb-fail.c \
test/test-tcp-bind-error.c \
test/test-tcp-bind6-error.c \
test/test-tcp-close-accept.c \
test/test-tcp-close-while-connecting.c \
test/test-tcp-close.c \
test/test-tcp-close-reset.c \
test/test-tcp-create-socket-early.c \
test/test-tcp-connect-error-after-write.c \
test/test-tcp-connect-error.c \
test/test-tcp-connect-timeout.c \
test/test-tcp-connect6-error.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 \
test/test-tcp-write-to-half-open-connection.c \
test/test-tcp-write-after-connect.c \
test/test-tcp-writealot.c \
test/test-tcp-write-fail.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 \
test/test-threadpool.c \
test/test-timer-again.c \
test/test-timer-from-check.c \
test/test-timer.c \
test/test-tmpdir.c \
test/test-tty-duplicate-key.c \
test/test-tty-escape-sequence-processing.c \
test/test-tty.c \
test/test-udp-alloc-cb-fail.c \
test/test-udp-bind.c \
test/test-udp-connect.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 \
test/test-udp-multicast-join6.c \
test/test-udp-multicast-ttl.c \
test/test-udp-open.c \
test/test-udp-options.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 \
test/test-walk-handles.c \
test/test-watcher-cross-stop.c
test_run_tests_LDADD = libuv.la
if WINNT
test_run_tests_SOURCES += test/runner-win.c \
test/runner-win.h
else
test_run_tests_SOURCES += test/runner-unix.c \
test/runner-unix.h
endif
if AIX
test_run_tests_CFLAGS += -D_ALL_SOURCE \
-D_XOPEN_SOURCE=500 \
-D_LINUX_SOURCE_COMPAT
endif
if OS400
test_run_tests_CFLAGS += -D_ALL_SOURCE \
-D_XOPEN_SOURCE=500 \
-D_LINUX_SOURCE_COMPAT
endif
if HAIKU
test_run_tests_CFLAGS += -D_BSD_SOURCE
endif
if LINUX
test_run_tests_CFLAGS += -D_GNU_SOURCE
endif
if SUNOS
test_run_tests_CFLAGS += -D__EXTENSIONS__ \
-D_XOPEN_SOURCE=500 \
-D_REENTRANT
endif
if OS390
test_run_tests_CFLAGS += -D_ISOC99_SOURCE \
-D_UNIX03_THREADS \
-D_UNIX03_SOURCE \
-D_OPEN_SYS_IF_EXT=1 \
-D_OPEN_SYS_SOCK_IPV6 \
-D_OPEN_MSGQ_EXT \
-D_XOPEN_SOURCE_EXTENDED \
-D_ALL_SOURCE \
-D_LARGE_TIME_API \
-D_OPEN_SYS_FILE_EXT \
-DPATH_MAX=255 \
-qCHARS=signed \
-qXPLINK \
-qFLOAT=IEEE
endif
if AIX
libuv_la_CFLAGS += -D_ALL_SOURCE \
-D_XOPEN_SOURCE=500 \
-D_LINUX_SOURCE_COMPAT \
-D_THREAD_SAFE \
-DHAVE_SYS_AHAFS_EVPRODS_H
uvinclude_HEADERS += include/uv/aix.h
libuv_la_SOURCES += src/unix/aix.c src/unix/aix-common.c
endif
if OS400
libuv_la_CFLAGS += -D_ALL_SOURCE \
-D_XOPEN_SOURCE=500 \
-D_LINUX_SOURCE_COMPAT \
-D_THREAD_SAFE
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
endif
if ANDROID
uvinclude_HEADERS += include/uv/android-ifaddrs.h
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
src/unix/pthread-fixes.c \
src/unix/random-getrandom.c \
src/unix/random-sysctl-linux.c \
src/unix/epoll.c
endif
if CYGWIN
uvinclude_HEADERS += include/uv/posix.h
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/cygwin.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 \
src/unix/procfs-exepath.c \
src/unix/sysinfo-loadavg.c \
src/unix/sysinfo-memory.c
endif
if DARWIN
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-proctitle.c \
src/unix/darwin-stub.h \
src/unix/darwin.c \
src/unix/fsevents.c \
src/unix/kqueue.c \
src/unix/proctitle.c \
src/unix/random-getentropy.c
test_run_tests_LDFLAGS += -lutil
endif
if DRAGONFLY
uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/bsd-proctitle.c \
src/unix/freebsd.c \
src/unix/kqueue.c \
src/unix/posix-hrtime.c
test_run_tests_LDFLAGS += -lutil
endif
if FREEBSD
uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/bsd-proctitle.c \
src/unix/freebsd.c \
src/unix/kqueue.c \
src/unix/posix-hrtime.c \
src/unix/random-getrandom.c
test_run_tests_LDFLAGS += -lutil
endif
if HAIKU
uvinclude_HEADERS += include/uv/posix.h
libuv_la_CFLAGS += -D_BSD_SOURCE
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/haiku.c \
src/unix/no-fsevents.c \
src/unix/no-proctitle.c \
src/unix/posix-hrtime.c \
src/unix/posix-poll.c
endif
if HURD
uvinclude_HEADERS += include/uv/posix.h
libuv_la_SOURCES += src/unix/no-fsevents.c \
src/unix/posix-hrtime.c \
src/unix/posix-poll.c
endif
if LINUX
uvinclude_HEADERS += include/uv/linux.h
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/linux-core.c \
src/unix/linux-inotify.c \
src/unix/linux-syscalls.c \
src/unix/linux-syscalls.h \
src/unix/procfs-exepath.c \
src/unix/proctitle.c \
src/unix/random-getrandom.c \
src/unix/random-sysctl-linux.c \
src/unix/epoll.c
test_run_tests_LDFLAGS += -lutil
endif
if MSYS
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/cygwin.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 \
src/unix/procfs-exepath.c \
src/unix/sysinfo-loadavg.c \
src/unix/sysinfo-memory.c
endif
if NETBSD
uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/bsd-proctitle.c \
src/unix/kqueue.c \
src/unix/netbsd.c \
src/unix/posix-hrtime.c
test_run_tests_LDFLAGS += -lutil
endif
if OPENBSD
uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/bsd-proctitle.c \
src/unix/kqueue.c \
src/unix/openbsd.c \
src/unix/posix-hrtime.c \
src/unix/random-getentropy.c
test_run_tests_LDFLAGS += -lutil
endif
if SUNOS
uvinclude_HEADERS += include/uv/sunos.h
libuv_la_CFLAGS += -D__EXTENSIONS__ \
-D_XOPEN_SOURCE=500 \
-D_REENTRANT
libuv_la_SOURCES += src/unix/no-proctitle.c \
src/unix/sunos.c
endif
if OS390
libuv_la_CFLAGS += -D_UNIX03_THREADS \
-D_UNIX03_SOURCE \
-D_OPEN_SYS_IF_EXT=1 \
-D_OPEN_MSGQ_EXT \
-D_XOPEN_SOURCE_EXTENDED \
-D_ALL_SOURCE \
-D_LARGE_TIME_API \
-D_OPEN_SYS_SOCK_EXT3 \
-D_OPEN_SYS_SOCK_IPV6 \
-D_OPEN_SYS_FILE_EXT \
-DUV_PLATFORM_SEM_T=int \
-DPATH_MAX=255 \
-qCHARS=signed \
-qXPLINK \
-qFLOAT=IEEE
libuv_la_LDFLAGS += -qXPLINK
libuv_la_SOURCES += src/unix/pthread-fixes.c \
src/unix/os390.c \
src/unix/os390-syscalls.c \
src/unix/proctitle.c
endif
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = @PACKAGE_NAME@.pc

@ -1,333 +0,0 @@
![libuv][libuv_banner]
## 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](http://luvit.io/), [Julia](http://julialang.org/),
[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/blob/v1.x/LINKS.md).
## Feature highlights
* Full-featured event loop backed by epoll, kqueue, IOCP, event ports.
* Asynchronous TCP and UDP sockets
* Asynchronous DNS resolution
* Asynchronous file and file system operations
* File system events
* ANSI escape code controlled TTY
* IPC with socket sharing, using Unix domain sockets or named pipes (Windows)
* Child processes
* Thread pool
* Signal handling
* High resolution clock
* Threading and synchronization primitives
## Versioning
Starting with version 1.0.0 libuv follows the [semantic versioning](http://semver.org/)
scheme. The API change and backwards compatibility rules are those indicated by
SemVer. libuv will keep a stable ABI across major releases.
The ABI/API changes can be tracked [here](http://abi-laboratory.pro/tracker/timeline/libuv/).
## Licensing
libuv is licensed under the MIT license. Check the [LICENSE file](LICENSE).
The documentation is licensed under the CC BY 4.0 license. Check the [LICENSE-docs file](LICENSE-docs).
## Community
* [Support](https://github.com/libuv/libuv/discussions)
* [Mailing list](http://groups.google.com/group/libuv)
## Documentation
### Official documentation
Located in the docs/ subdirectory. It uses the [Sphinx](http://sphinx-doc.org/)
framework, which makes it possible to build the documentation in multiple
formats.
Show different supported building options:
```bash
$ make help
```
Build documentation as HTML:
```bash
$ make html
```
Build documentation as HTML and live reload it when it changes (this requires
sphinx-autobuild to be installed and is only supported on Unix):
```bash
$ make livehtml
```
Build documentation as man pages:
```bash
$ make man
```
Build documentation as ePub:
```bash
$ make epub
```
NOTE: Windows users need to use make.bat instead of plain 'make'.
Documentation can be browsed online [here](http://docs.libuv.org).
The [tests and benchmarks](https://github.com/libuv/libuv/tree/master/test)
also serve as API specification and usage examples.
### Other resources
* [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4)
&mdash; High-level introductory talk about libuv.
* [libuv-dox](https://github.com/thlorenz/libuv-dox)
&mdash; Documenting types and methods of libuv, mostly by reading uv.h.
* [learnuv](https://github.com/thlorenz/learnuv)
&mdash; Learn uv for fun and profit, a self guided workshop to libuv.
These resources are not handled by libuv maintainers and might be out of
date. Please verify it before opening new issues.
## Downloading
libuv can be downloaded either from the
[GitHub repository](https://github.com/libuv/libuv)
or from the [downloads site](http://dist.libuv.org/dist/).
Before verifying the git tags or signature files, importing the relevant keys
is necessary. Key IDs are listed in the
[MAINTAINERS](https://github.com/libuv/libuv/blob/master/MAINTAINERS.md)
file, but are also available as git blob objects for easier use.
Importing a key the usual way:
```bash
$ gpg --keyserver pool.sks-keyservers.net --recv-keys AE9BC059
```
Importing a key from a git blob object:
```bash
$ git show pubkey-saghul | gpg --import
```
### Verifying releases
Git tags are signed with the developer's key, they can be verified as follows:
```bash
$ git verify-tag v1.6.1
```
Starting with libuv 1.7.0, the tarballs stored in the
[downloads site](http://dist.libuv.org/dist/) are signed and an accompanying
signature file sit alongside each. Once both the release tarball and the
signature file are downloaded, the file can be verified as follows:
```bash
$ gpg --verify libuv-1.7.0.tar.gz.sign
```
## Build Instructions
For UNIX-like platforms, including macOS, there are two build methods:
autotools or [CMake][].
For Windows, [CMake][] is the only supported build method and has the
following prerequisites:
<details>
* One of:
* [Visual C++ Build Tools][]
* [Visual Studio 2015 Update 3][], all editions
including the Community edition (remember to select
"Common Tools for Visual C++ 2015" feature during installation).
* [Visual Studio 2017][], any edition (including the Build Tools SKU).
**Required Components:** "MSbuild", "VC++ 2017 v141 toolset" and one of the
Windows SDKs (10 or 8.1).
* Basic Unix tools required for some tests,
[Git for Windows][] includes Git Bash
and tools which can be included in the global `PATH`.
</details>
To build with autotools:
```bash
$ sh autogen.sh
$ ./configure
$ make
$ make check
$ make install
```
To build with [CMake][]:
```bash
$ 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
```
To cross-compile with [CMake][] (unsupported but generally works):
```bash
$ cmake ../.. \
-DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_SYSTEM_VERSION=6.1 \
-DCMAKE_C_COMPILER=i686-w64-mingw32-gcc
```
### Install with Homebrew
```bash
$ brew install --HEAD libuv
```
Note to OS X users:
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").
### Running tests
Some tests are timing sensitive. Relaxing test timeouts may be necessary
on slow or overloaded machines:
```bash
$ 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 test driver to fork and execute `TEST_NAME` in
a child process:
```bash
$ build/uv_run_tests_a TEST_NAME
```
This invocation will cause the test driver to execute the test in
the same process:
```bash
$ build/uv_run_tests_a TEST_NAME TEST_NAME
```
#### Debugging tools
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 build/uv_run_tests_a TEST_NAME
(gdb) set follow-fork-mode child
...
```
##### Fork-aware valgrind
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 build/uv_run_tests_a TEST_NAME
```
### Running benchmarks
See the section on running tests.
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.
AIX support for filesystem events requires the non-default IBM `bos.ahafs`
package to be installed. This package provides the AIX Event Infrastructure
that is detected by `autoconf`.
[IBM documentation](http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/)
describes the package in more detail.
### z/OS Notes
z/OS compilation requires [ZOSLIB](https://github.com/ibmruntimes/zoslib) to be installed. When building with [CMake][], use the flag `-DZOSLIB_DIR` to specify the path to [ZOSLIB](https://github.com/ibmruntimes/zoslib):
```bash
$ (cd build && cmake .. -DBUILD_TESTING=ON -DZOSLIB_DIR=/path/to/zoslib)
$ cmake --build build
```
z/OS creates System V semaphores and message queues. These persist on the system
after the process terminates unless the event loop is closed.
Use the `ipcrm` command to manually clear up System V resources.
## Patches
See the [guidelines for contributing][].
[CMake]: https://cmake.org/
[node.js]: http://nodejs.org/
[guidelines for contributing]: https://github.com/libuv/libuv/blob/master/CONTRIBUTING.md
[libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png
[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/
[Git for Windows]: http://git-scm.com/download/win

@ -1,69 +0,0 @@
# Supported platforms
| 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 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 | |
| MinGW | Tier 3 | MinGW32 and MinGW-w64 | |
| SunOS | Tier 3 | Solaris 121 and later | |
| Other | Tier 3 | N/A | |
## Support types
* **Tier 1**: Officially supported and tested with CI. Any contributed patch
MUST NOT break such systems. These are supported by @libuv/collaborators.
* **Tier 2**: Officially supported, but not necessarily tested with CI. These
systems are maintained to the best of @libuv/collaborators ability,
without being a top priority.
* **Tier 3**: Community maintained. These systems may inadvertently break and the
community and interested parties are expected to help with the maintenance.
## Adding support for a new platform
**IMPORTANT**: Before attempting to add support for a new platform please open
an issue about it for discussion.
### Unix
I/O handling is abstracted by an internal `uv__io_t` handle. The new platform
will need to implement some of the functions, the prototypes are in
``src/unix/internal.h``.
If the new platform requires extra fields for any handle structure, create a
new include file in ``include/`` with the name ``uv-theplatform.h`` and add
the appropriate defines there.
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 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
Windows is treated as a single platform, so adding support for a new platform
would mean adding support for a new version.
Compilation and runtime must succeed for the minimum supported version. If a
new API is to be used, it must be done optionally, only in supported versions.
### Common
Some common notes when adding support for new platforms:
* Generally libuv tries to avoid compile time checks. Do not add any to the
autotools based build system or use version checking macros.
Dynamically load functions and symbols if they are not supported by the
minimum supported version.

@ -1,46 +0,0 @@
#!/bin/sh
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
cd `dirname "$0"`
if [ "$LIBTOOLIZE" = "" ] && [ "`uname`" = "Darwin" ]; then
LIBTOOLIZE=glibtoolize
fi
ACLOCAL=${ACLOCAL:-aclocal}
AUTOCONF=${AUTOCONF:-autoconf}
AUTOMAKE=${AUTOMAKE:-automake}
LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
automake_version=`"$AUTOMAKE" --version | head -n 1 | sed 's/[^.0-9]//g'`
automake_version_major=`echo "$automake_version" | cut -d. -f1`
automake_version_minor=`echo "$automake_version" | cut -d. -f2`
UV_EXTRA_AUTOMAKE_FLAGS=
if test "$automake_version_major" -gt 1 || \
test "$automake_version_major" -eq 1 && \
test "$automake_version_minor" -gt 11; then
# serial-tests is available in v1.12 and newer.
UV_EXTRA_AUTOMAKE_FLAGS="$UV_EXTRA_AUTOMAKE_FLAGS serial-tests"
fi
echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \
> m4/libuv-extra-automake-flags.m4
set -ex
"$LIBTOOLIZE" --copy
"$ACLOCAL" -I m4
"$AUTOCONF"
"$AUTOMAKE" --add-missing --copy

@ -1,88 +0,0 @@
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
AC_INIT([libuv], [1.42.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
m4_include([m4/libuv-check-flags.m4])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS)
AC_CANONICAL_HOST
AC_ENABLE_SHARED
AC_ENABLE_STATIC
AC_PROG_CC
AM_PROG_CC_C_O
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])
CC_CHECK_CFLAGS_APPEND([-Wextra])
CC_CHECK_CFLAGS_APPEND([-Wno-long-long])
CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes])
# AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12.
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
# autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR.
AC_PROG_LIBTOOL
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
LT_INIT
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])])
AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])])
AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])])
AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])])
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])])
AM_CONDITIONAL([HAIKU], [AS_CASE([$host_os],[haiku], [true], [false])])
AM_CONDITIONAL([HURD], [AS_CASE([$host_os],[gnu*], [true], [false])])
AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])])
AM_CONDITIONAL([MSYS], [AS_CASE([$host_os],[msys*], [true], [false])])
AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])])
AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])])
AM_CONDITIONAL([OS390], [AS_CASE([$host_os],[openedition*], [true], [false])])
AM_CONDITIONAL([OS400], [AS_CASE([$host_os],[os400], [true], [false])])
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
AS_CASE([$host_os],[mingw*], [
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32"
])
AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])])
AS_CASE([$host_os], [kfreebsd*], [
LIBS="$LIBS -lfreebsd-glue"
])
AS_CASE([$host_os], [haiku], [
LIBS="$LIBS -lnetwork"
])
AC_CHECK_HEADERS([sys/ahafs_evProds.h])
AC_CONFIG_FILES([Makefile libuv.pc])
AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file])
AC_CONFIG_LINKS([test/fixtures/load_error.node:test/fixtures/load_error.node])
AC_CONFIG_LINKS([test/fixtures/lorem_ipsum.txt:test/fixtures/lorem_ipsum.txt])
AC_OUTPUT

@ -1,81 +0,0 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
uv_loop_t *loop;
uv_process_t child_req;
uv_process_options_t options;
void cleanup_handles(uv_process_t *req, int64_t exit_status, int term_signal) {
fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
uv_close((uv_handle_t*) req->data, NULL);
uv_close((uv_handle_t*) req, NULL);
}
void invoke_cgi_script(uv_tcp_t *client) {
size_t size = 500;
char path[size];
uv_exepath(path, &size);
strcpy(path + (strlen(path) - strlen("cgi")), "tick");
char* args[2];
args[0] = path;
args[1] = NULL;
/* ... finding the executable path and setting up arguments ... */
options.stdio_count = 3;
uv_stdio_container_t child_stdio[3];
child_stdio[0].flags = UV_IGNORE;
child_stdio[1].flags = UV_INHERIT_STREAM;
child_stdio[1].data.stream = (uv_stream_t*) client;
child_stdio[2].flags = UV_IGNORE;
options.stdio = child_stdio;
options.exit_cb = cleanup_handles;
options.file = args[0];
options.args = args;
// Set this so we can close the socket after the child process exits.
child_req.data = (void*) client;
int r;
if ((r = uv_spawn(loop, &child_req, &options))) {
fprintf(stderr, "%s\n", uv_strerror(r));
return;
}
}
void on_new_connection(uv_stream_t *server, int status) {
if (status == -1) {
// error!
return;
}
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
uv_tcp_init(loop, client);
if (uv_accept(server, (uv_stream_t*) client) == 0) {
invoke_cgi_script(client);
}
else {
uv_close((uv_handle_t*) client, NULL);
}
}
int main() {
loop = uv_default_loop();
uv_tcp_t server;
uv_tcp_init(loop, &server);
struct sockaddr_in bind_addr;
uv_ip4_addr("0.0.0.0", 7000, &bind_addr);
uv_tcp_bind(&server, (const struct sockaddr *)&bind_addr, 0);
int r = uv_listen((uv_stream_t*) &server, 128, on_new_connection);
if (r) {
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
return 1;
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,13 +0,0 @@
#include <stdio.h>
#include <unistd.h>
int main() {
int i;
for (i = 0; i < 10; i++) {
printf("tick\n");
fflush(stdout);
sleep(1);
}
printf("BOOM!\n");
return 0;
}

@ -1,31 +0,0 @@
#include <stdio.h>
#include <uv.h>
uv_loop_t *loop;
uv_process_t child_req;
uv_process_options_t options;
int main() {
loop = uv_default_loop();
char* args[3];
args[0] = "sleep";
args[1] = "100";
args[2] = NULL;
options.exit_cb = NULL;
options.file = "sleep";
options.args = args;
options.flags = UV_PROCESS_DETACHED;
int r;
if ((r = uv_spawn(loop, &child_req, &options))) {
fprintf(stderr, "%s\n", uv_strerror(r));
return 1;
}
fprintf(stderr, "Launched sleep with PID %d\n", child_req.pid);
uv_unref((uv_handle_t*) &child_req);
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,80 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
uv_loop_t *loop;
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
void on_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
if (nread < 0) {
if (nread != UV_EOF)
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) client, NULL);
free(buf->base);
free(client);
return;
}
char *data = (char*) malloc(sizeof(char) * (nread+1));
data[nread] = '\0';
strncpy(data, buf->base, nread);
fprintf(stderr, "%s", data);
free(data);
free(buf->base);
}
void on_connect(uv_connect_t *req, int status) {
if (status < 0) {
fprintf(stderr, "connect failed error %s\n", uv_err_name(status));
free(req);
return;
}
uv_read_start((uv_stream_t*) req->handle, alloc_buffer, on_read);
free(req);
}
void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) {
if (status < 0) {
fprintf(stderr, "getaddrinfo callback error %s\n", uv_err_name(status));
return;
}
char addr[17] = {'\0'};
uv_ip4_name((struct sockaddr_in*) res->ai_addr, addr, 16);
fprintf(stderr, "%s\n", addr);
uv_connect_t *connect_req = (uv_connect_t*) malloc(sizeof(uv_connect_t));
uv_tcp_t *socket = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
uv_tcp_init(loop, socket);
uv_tcp_connect(connect_req, socket, (const struct sockaddr*) res->ai_addr, on_connect);
uv_freeaddrinfo(res);
}
int main() {
loop = uv_default_loop();
struct addrinfo hints;
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = 0;
uv_getaddrinfo_t resolver;
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));
return 1;
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,15 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
int main() {
uv_loop_t *loop = malloc(sizeof(uv_loop_t));
uv_loop_init(loop);
printf("Now quitting.\n");
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_close(loop);
free(loop);
return 0;
}

@ -1,24 +0,0 @@
#include <stdio.h>
#include <uv.h>
int64_t counter = 0;
void wait_for_a_while(uv_idle_t* handle) {
counter++;
if (counter >= 10e6)
uv_idle_stop(handle);
}
int main() {
uv_idle_t idler;
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for_a_while);
printf("Idling...\n");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
return 0;
}

@ -1,43 +0,0 @@
#include <stdio.h>
#include <uv.h>
uv_loop_t *loop;
uv_fs_t stdin_watcher;
uv_idle_t idler;
char buffer[1024];
void crunch_away(uv_idle_t* handle) {
// Compute extra-terrestrial life
// fold proteins
// computer another digit of PI
// or similar
fprintf(stderr, "Computing PI...\n");
// just to avoid overwhelming your terminal emulator
uv_idle_stop(handle);
}
void on_type(uv_fs_t *req) {
if (stdin_watcher.result > 0) {
buffer[stdin_watcher.result] = '\0';
printf("Typed %s\n", buffer);
uv_buf_t buf = uv_buf_init(buffer, 1024);
uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, -1, on_type);
uv_idle_start(&idler, crunch_away);
}
else if (stdin_watcher.result < 0) {
fprintf(stderr, "error opening file: %s\n", uv_strerror(req->result));
}
}
int main() {
loop = uv_default_loop();
uv_idle_init(loop, &idler);
uv_buf_t buf = uv_buf_init(buffer, 1024);
uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, -1, on_type);
uv_idle_start(&idler, crunch_away);
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,33 +0,0 @@
#include <stdio.h>
#include <uv.h>
int main() {
char buf[512];
uv_interface_address_t *info;
int count, i;
uv_interface_addresses(&info, &count);
i = count;
printf("Number of interfaces: %d\n", count);
while (i--) {
uv_interface_address_t interface = info[i];
printf("Name: %s\n", interface.name);
printf("Internal? %s\n", interface.is_internal ? "Yes" : "No");
if (interface.address.address4.sin_family == AF_INET) {
uv_ip4_name(&interface.address.address4, buf, sizeof(buf));
printf("IPv4 address: %s\n", buf);
}
else if (interface.address.address4.sin_family == AF_INET6) {
uv_ip6_name(&interface.address.address6, buf, sizeof(buf));
printf("IPv6 address: %s\n", buf);
}
printf("\n");
}
uv_free_interface_addresses(info, count);
return 0;
}

@ -1,57 +0,0 @@
#include <stdio.h>
#include <uv.h>
uv_barrier_t blocker;
uv_rwlock_t numlock;
int shared_num;
void reader(void *n)
{
int num = *(int *)n;
int i;
for (i = 0; i < 20; i++) {
uv_rwlock_rdlock(&numlock);
printf("Reader %d: acquired lock\n", num);
printf("Reader %d: shared num = %d\n", num, shared_num);
uv_rwlock_rdunlock(&numlock);
printf("Reader %d: released lock\n", num);
}
uv_barrier_wait(&blocker);
}
void writer(void *n)
{
int num = *(int *)n;
int i;
for (i = 0; i < 20; i++) {
uv_rwlock_wrlock(&numlock);
printf("Writer %d: acquired lock\n", num);
shared_num++;
printf("Writer %d: incremented shared num = %d\n", num, shared_num);
uv_rwlock_wrunlock(&numlock);
printf("Writer %d: released lock\n", num);
}
uv_barrier_wait(&blocker);
}
int main()
{
uv_barrier_init(&blocker, 4);
shared_num = 0;
uv_rwlock_init(&numlock);
uv_thread_t threads[3];
int thread_nums[] = {1, 2, 1};
uv_thread_create(&threads[0], reader, &thread_nums[0]);
uv_thread_create(&threads[1], reader, &thread_nums[1]);
uv_thread_create(&threads[2], writer, &thread_nums[2]);
uv_barrier_wait(&blocker);
uv_barrier_destroy(&blocker);
uv_rwlock_destroy(&numlock);
return 0;
}

@ -1,20 +0,0 @@
var net = require('net');
var PHRASE = "hello world";
var write = function(socket) {
socket.write(PHRASE, 'utf8');
}
for (var i = 0; i < 1000; i++) {
(function() {
var socket = net.connect(7000, 'localhost', function() {
socket.on('data', function(reply) {
if (reply.toString().indexOf(PHRASE) != 0)
console.error("Problem! '" + reply + "'" + " '" + PHRASE + "'");
else
write(socket);
});
write(socket);
});
})();
}

@ -1,114 +0,0 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
uv_loop_t *loop;
struct child_worker {
uv_process_t req;
uv_process_options_t options;
uv_pipe_t pipe;
} *workers;
int round_robin_counter;
int child_worker_count;
uv_buf_t dummy_buf;
char worker_path[500];
void close_process_handle(uv_process_t *req, int64_t exit_status, int term_signal) {
fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
uv_close((uv_handle_t*) req, NULL);
}
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
void on_new_connection(uv_stream_t *server, int status) {
if (status == -1) {
// error!
return;
}
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
uv_tcp_init(loop, client);
if (uv_accept(server, (uv_stream_t*) client) == 0) {
uv_write_t *write_req = (uv_write_t*) malloc(sizeof(uv_write_t));
dummy_buf = uv_buf_init("a", 1);
struct child_worker *worker = &workers[round_robin_counter];
uv_write2(write_req, (uv_stream_t*) &worker->pipe, &dummy_buf, 1, (uv_stream_t*) client, NULL);
round_robin_counter = (round_robin_counter + 1) % child_worker_count;
}
else {
uv_close((uv_handle_t*) client, NULL);
}
}
void setup_workers() {
size_t path_size = 500;
uv_exepath(worker_path, &path_size);
strcpy(worker_path + (strlen(worker_path) - strlen("multi-echo-server")), "worker");
fprintf(stderr, "Worker path: %s\n", worker_path);
char* args[2];
args[0] = worker_path;
args[1] = NULL;
round_robin_counter = 0;
// ...
// launch same number of workers as number of CPUs
uv_cpu_info_t *info;
int cpu_count;
uv_cpu_info(&info, &cpu_count);
uv_free_cpu_info(info, cpu_count);
child_worker_count = 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);
uv_stdio_container_t child_stdio[3];
child_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
child_stdio[0].data.stream = (uv_stream_t*) &worker->pipe;
child_stdio[1].flags = UV_IGNORE;
child_stdio[2].flags = UV_INHERIT_FD;
child_stdio[2].data.fd = 2;
worker->options.stdio = child_stdio;
worker->options.stdio_count = 3;
worker->options.exit_cb = close_process_handle;
worker->options.file = args[0];
worker->options.args = args;
uv_spawn(loop, &worker->req, &worker->options);
fprintf(stderr, "Started worker %d\n", worker->req.pid);
}
}
int main() {
loop = uv_default_loop();
setup_workers();
uv_tcp_t server;
uv_tcp_init(loop, &server);
struct sockaddr_in bind_addr;
uv_ip4_addr("0.0.0.0", 7000, &bind_addr);
uv_tcp_bind(&server, (const struct sockaddr *)&bind_addr, 0);
int r;
if ((r = uv_listen((uv_stream_t*) &server, 128, on_new_connection))) {
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
return 2;
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,88 +0,0 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <uv.h>
uv_loop_t *loop;
uv_pipe_t queue;
typedef struct {
uv_write_t req;
uv_buf_t buf;
} write_req_t;
void free_write_req(uv_write_t *req) {
write_req_t *wr = (write_req_t*) req;
free(wr->buf.base);
free(wr);
}
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
void echo_write(uv_write_t *req, int status) {
if (status) {
fprintf(stderr, "Write error %s\n", uv_err_name(status));
}
free_write_req(req);
}
void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
if (nread > 0) {
write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
req->buf = uv_buf_init(buf->base, nread);
uv_write((uv_write_t*) req, client, &req->buf, 1, echo_write);
return;
}
if (nread < 0) {
if (nread != UV_EOF)
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) client, NULL);
}
free(buf->base);
}
void on_new_connection(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf) {
if (nread < 0) {
if (nread != UV_EOF)
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) q, NULL);
return;
}
uv_pipe_t *pipe = (uv_pipe_t*) q;
if (!uv_pipe_pending_count(pipe)) {
fprintf(stderr, "No pending count\n");
return;
}
uv_handle_type pending = uv_pipe_pending_type(pipe);
assert(pending == UV_TCP);
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
uv_tcp_init(loop, client);
if (uv_accept(q, (uv_stream_t*) client) == 0) {
uv_os_fd_t fd;
uv_fileno((const uv_handle_t*) client, &fd);
fprintf(stderr, "Worker %d: Accepted fd %d\n", getpid(), fd);
uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
}
else {
uv_close((uv_handle_t*) client, NULL);
}
}
int main() {
loop = uv_default_loop();
uv_pipe_init(loop, &queue, 1 /* ipc */);
uv_pipe_open(&queue, 0);
uv_read_start((uv_stream_t*)&queue, alloc_buffer, on_new_connection);
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,44 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
uv_loop_t *loop;
const char *command;
void run_command(uv_fs_event_t *handle, const char *filename, int events, int status) {
char path[1024];
size_t size = 1023;
// Does not handle error if path is longer than 1023.
uv_fs_event_getpath(handle, path, &size);
path[size] = '\0';
fprintf(stderr, "Change detected in %s: ", path);
if (events & UV_RENAME)
fprintf(stderr, "renamed");
if (events & UV_CHANGE)
fprintf(stderr, "changed");
fprintf(stderr, " %s\n", filename ? filename : "");
system(command);
}
int main(int argc, char **argv) {
if (argc <= 2) {
fprintf(stderr, "Usage: %s <command> <file1> [file2 ...]\n", argv[0]);
return 1;
}
loop = uv_default_loop();
command = argv[1];
while (argc-- > 2) {
fprintf(stderr, "Adding watch on %s\n", argv[argc]);
uv_fs_event_t *fs_event_req = malloc(sizeof(uv_fs_event_t));
uv_fs_event_init(loop, fs_event_req);
// The recursive flag watches subdirectories too.
uv_fs_event_start(fs_event_req, run_command, argv[argc], UV_FS_EVENT_RECURSIVE);
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,94 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#ifdef _WIN32
#define PIPENAME "\\\\?\\pipe\\echo.sock"
#else
#define PIPENAME "/tmp/echo.sock"
#endif
uv_loop_t *loop;
typedef struct {
uv_write_t req;
uv_buf_t buf;
} write_req_t;
void free_write_req(uv_write_t *req) {
write_req_t *wr = (write_req_t*) req;
free(wr->buf.base);
free(wr);
}
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
void echo_write(uv_write_t *req, int status) {
if (status < 0) {
fprintf(stderr, "Write error %s\n", uv_err_name(status));
}
free_write_req(req);
}
void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
if (nread > 0) {
write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
req->buf = uv_buf_init(buf->base, nread);
uv_write((uv_write_t*) req, client, &req->buf, 1, echo_write);
return;
}
if (nread < 0) {
if (nread != UV_EOF)
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) client, NULL);
}
free(buf->base);
}
void on_new_connection(uv_stream_t *server, int status) {
if (status == -1) {
// error!
return;
}
uv_pipe_t *client = (uv_pipe_t*) malloc(sizeof(uv_pipe_t));
uv_pipe_init(loop, client, 0);
if (uv_accept(server, (uv_stream_t*) client) == 0) {
uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
}
else {
uv_close((uv_handle_t*) client, NULL);
}
}
void remove_sock(int sig) {
uv_fs_t req;
uv_fs_unlink(loop, &req, PIPENAME, NULL);
exit(0);
}
int main() {
loop = uv_default_loop();
uv_pipe_t server;
uv_pipe_init(loop, &server, 0);
signal(SIGINT, remove_sock);
int r;
if ((r = uv_pipe_bind(&server, PIPENAME))) {
fprintf(stderr, "Bind error %s\n", uv_err_name(r));
return 1;
}
if ((r = uv_listen((uv_stream_t*) &server, 128, on_new_connection))) {
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
return 2;
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,5 +0,0 @@
#include "plugin.h"
void initialize() {
mfp_register("Hello World!");
}

@ -1,39 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <uv.h>
#include "plugin.h"
typedef void (*init_plugin_function)();
void mfp_register(const char *name) {
fprintf(stderr, "Registered plugin \"%s\"\n", name);
}
int main(int argc, char **argv) {
if (argc == 1) {
fprintf(stderr, "Usage: %s [plugin1] [plugin2] ...\n", argv[0]);
return 0;
}
uv_lib_t *lib = (uv_lib_t*) malloc(sizeof(uv_lib_t));
while (--argc) {
fprintf(stderr, "Loading %s\n", argv[argc]);
if (uv_dlopen(argv[argc], lib)) {
fprintf(stderr, "Error: %s\n", uv_dlerror(lib));
continue;
}
init_plugin_function init_plugin;
if (uv_dlsym(lib, "initialize", (void **) &init_plugin)) {
fprintf(stderr, "dlsym error: %s\n", uv_dlerror(lib));
continue;
}
init_plugin();
}
return 0;
}

@ -1,7 +0,0 @@
#ifndef UVBOOK_PLUGIN_SYSTEM
#define UVBOOK_PLUGIN_SYSTEM
// Plugin authors should use this to register their plugins with mfp.
void mfp_register(const char *name);
#endif

@ -1,49 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <uv.h>
uv_loop_t *loop;
uv_process_t child_req;
uv_process_options_t options;
void on_exit(uv_process_t *req, int64_t exit_status, int term_signal) {
fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
uv_close((uv_handle_t*) req, NULL);
}
int main() {
loop = uv_default_loop();
size_t size = 500;
char path[size];
uv_exepath(path, &size);
strcpy(path + (strlen(path) - strlen("proc-streams")), "test");
char* args[2];
args[0] = path;
args[1] = NULL;
/* ... */
options.stdio_count = 3;
uv_stdio_container_t child_stdio[3];
child_stdio[0].flags = UV_IGNORE;
child_stdio[1].flags = UV_IGNORE;
child_stdio[2].flags = UV_INHERIT_FD;
child_stdio[2].data.fd = 2;
options.stdio = child_stdio;
options.exit_cb = on_exit;
options.file = args[0];
options.args = args;
int r;
if ((r = uv_spawn(loop, &child_req, &options))) {
fprintf(stderr, "%s\n", uv_strerror(r));
return 1;
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,8 +0,0 @@
#include <stdio.h>
int main()
{
fprintf(stderr, "This is stderr\n");
printf("This is stdout\n");
return 0;
}

@ -1,47 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <uv.h>
uv_loop_t *loop;
uv_async_t async;
double percentage;
void fake_download(uv_work_t *req) {
int size = *((int*) req->data);
int downloaded = 0;
while (downloaded < size) {
percentage = downloaded*100.0/size;
async.data = (void*) &percentage;
uv_async_send(&async);
sleep(1);
downloaded += (200+random())%1000; // can only download max 1000bytes/sec,
// but at least a 200;
}
}
void after(uv_work_t *req, int status) {
fprintf(stderr, "Download complete\n");
uv_close((uv_handle_t*) &async, NULL);
}
void print_progress(uv_async_t *handle) {
double percentage = *((double*) handle->data);
fprintf(stderr, "Downloaded %.2f%%\n", percentage);
}
int main() {
loop = uv_default_loop();
uv_work_t req;
int size = 10240;
req.data = (void*) &size;
uv_async_init(loop, &async, print_progress);
uv_queue_work(loop, &req, fake_download, after);
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,59 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <uv.h>
#define FIB_UNTIL 25
uv_loop_t *loop;
uv_work_t fib_reqs[FIB_UNTIL];
long fib_(long t) {
if (t == 0 || t == 1)
return 1;
else
return fib_(t-1) + fib_(t-2);
}
void fib(uv_work_t *req) {
int n = *(int *) req->data;
if (random() % 2)
sleep(1);
else
sleep(3);
long fib = fib_(n);
fprintf(stderr, "%dth fibonacci is %lu\n", n, fib);
}
void after_fib(uv_work_t *req, int status) {
if (status == UV_ECANCELED)
fprintf(stderr, "Calculation of %d cancelled.\n", *(int *) req->data);
}
void signal_handler(uv_signal_t *req, int signum)
{
printf("Signal received!\n");
int i;
for (i = 0; i < FIB_UNTIL; i++) {
uv_cancel((uv_req_t*) &fib_reqs[i]);
}
uv_signal_stop(req);
}
int main() {
loop = uv_default_loop();
int data[FIB_UNTIL];
int i;
for (i = 0; i < FIB_UNTIL; i++) {
data[i] = i;
fib_reqs[i].data = (void *) &data[i];
uv_queue_work(loop, &fib_reqs[i], fib, after_fib);
}
uv_signal_t sig;
uv_signal_init(loop, &sig);
uv_signal_start(&sig, signal_handler, SIGINT);
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,44 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <uv.h>
#define FIB_UNTIL 25
uv_loop_t *loop;
long fib_(long t) {
if (t == 0 || t == 1)
return 1;
else
return fib_(t-1) + fib_(t-2);
}
void fib(uv_work_t *req) {
int n = *(int *) req->data;
if (random() % 2)
sleep(1);
else
sleep(3);
long fib = fib_(n);
fprintf(stderr, "%dth fibonacci is %lu\n", n, fib);
}
void after_fib(uv_work_t *req, int status) {
fprintf(stderr, "Done calculating %dth fibonacci\n", *(int *) req->data);
}
int main() {
loop = uv_default_loop();
int data[FIB_UNTIL];
uv_work_t req[FIB_UNTIL];
int i;
for (i = 0; i < FIB_UNTIL; i++) {
data[i] = i;
req[i].data = (void *) &data[i];
uv_queue_work(loop, &req[i], fib, after_fib);
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,29 +0,0 @@
#include <stdio.h>
#include <uv.h>
uv_loop_t *loop;
uv_timer_t gc_req;
uv_timer_t fake_job_req;
void gc(uv_timer_t *handle) {
fprintf(stderr, "Freeing unused objects\n");
}
void fake_job(uv_timer_t *handle) {
fprintf(stdout, "Fake job done\n");
}
int main() {
loop = uv_default_loop();
uv_timer_init(loop, &gc_req);
uv_unref((uv_handle_t*) &gc_req);
uv_timer_start(&gc_req, gc, 0, 2000);
// could actually be a TCP download or something
uv_timer_init(loop, &fake_job_req);
uv_timer_start(&fake_job_req, fake_job, 9000, 0);
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,66 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <uv.h>
uv_loop_t* create_loop()
{
uv_loop_t *loop = malloc(sizeof(uv_loop_t));
if (loop) {
uv_loop_init(loop);
}
return loop;
}
void signal_handler(uv_signal_t *handle, int signum)
{
printf("Signal received: %d\n", signum);
uv_signal_stop(handle);
}
// two signal handlers in one loop
void thread1_worker(void *userp)
{
uv_loop_t *loop1 = create_loop();
uv_signal_t sig1a, sig1b;
uv_signal_init(loop1, &sig1a);
uv_signal_start(&sig1a, signal_handler, SIGUSR1);
uv_signal_init(loop1, &sig1b);
uv_signal_start(&sig1b, signal_handler, SIGUSR1);
uv_run(loop1, UV_RUN_DEFAULT);
}
// two signal handlers, each in its own loop
void thread2_worker(void *userp)
{
uv_loop_t *loop2 = create_loop();
uv_loop_t *loop3 = create_loop();
uv_signal_t sig2;
uv_signal_init(loop2, &sig2);
uv_signal_start(&sig2, signal_handler, SIGUSR1);
uv_signal_t sig3;
uv_signal_init(loop3, &sig3);
uv_signal_start(&sig3, signal_handler, SIGUSR1);
while (uv_run(loop2, UV_RUN_NOWAIT) || uv_run(loop3, UV_RUN_NOWAIT)) {
}
}
int main()
{
printf("PID %d\n", getpid());
uv_thread_t thread1, thread2;
uv_thread_create(&thread1, thread1_worker, 0);
uv_thread_create(&thread2, thread2_worker, 0);
uv_thread_join(&thread1);
uv_thread_join(&thread2);
return 0;
}

@ -1,36 +0,0 @@
#include <stdio.h>
#include <inttypes.h>
#include <uv.h>
uv_loop_t *loop;
uv_process_t child_req;
uv_process_options_t options;
void on_exit(uv_process_t *req, int64_t exit_status, int term_signal) {
fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
uv_close((uv_handle_t*) req, NULL);
}
int main() {
loop = uv_default_loop();
char* args[3];
args[0] = "mkdir";
args[1] = "test-dir";
args[2] = NULL;
options.exit_cb = on_exit;
options.file = "mkdir";
options.args = args;
int r;
if ((r = uv_spawn(loop, &child_req, &options))) {
fprintf(stderr, "%s\n", uv_strerror(r));
return 1;
} else {
fprintf(stderr, "Launched process with ID %d\n", child_req.pid);
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,87 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#define DEFAULT_PORT 7000
#define DEFAULT_BACKLOG 128
uv_loop_t *loop;
struct sockaddr_in addr;
typedef struct {
uv_write_t req;
uv_buf_t buf;
} write_req_t;
void free_write_req(uv_write_t *req) {
write_req_t *wr = (write_req_t*) req;
free(wr->buf.base);
free(wr);
}
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = (char*) malloc(suggested_size);
buf->len = suggested_size;
}
void on_close(uv_handle_t* handle) {
free(handle);
}
void echo_write(uv_write_t *req, int status) {
if (status) {
fprintf(stderr, "Write error %s\n", uv_strerror(status));
}
free_write_req(req);
}
void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
if (nread > 0) {
write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
req->buf = uv_buf_init(buf->base, nread);
uv_write((uv_write_t*) req, client, &req->buf, 1, echo_write);
return;
}
if (nread < 0) {
if (nread != UV_EOF)
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) client, on_close);
}
free(buf->base);
}
void on_new_connection(uv_stream_t *server, int status) {
if (status < 0) {
fprintf(stderr, "New connection error %s\n", uv_strerror(status));
// error!
return;
}
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
uv_tcp_init(loop, client);
if (uv_accept(server, (uv_stream_t*) client) == 0) {
uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
}
else {
uv_close((uv_handle_t*) client, on_close);
}
}
int main() {
loop = uv_default_loop();
uv_tcp_t server;
uv_tcp_init(loop, &server);
uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);
uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);
int r = uv_listen((uv_stream_t*) &server, DEFAULT_BACKLOG, on_new_connection);
if (r) {
fprintf(stderr, "Listen error %s\n", uv_strerror(r));
return 1;
}
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,36 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <uv.h>
void hare(void *arg) {
int tracklen = *((int *) arg);
while (tracklen) {
tracklen--;
sleep(1);
fprintf(stderr, "Hare ran another step\n");
}
fprintf(stderr, "Hare done running!\n");
}
void tortoise(void *arg) {
int tracklen = *((int *) arg);
while (tracklen) {
tracklen--;
fprintf(stderr, "Tortoise ran another step\n");
sleep(3);
}
fprintf(stderr, "Tortoise done running!\n");
}
int main() {
int tracklen = 10;
uv_thread_t hare_id;
uv_thread_t tortoise_id;
uv_thread_create(&hare_id, hare, &tracklen);
uv_thread_create(&tortoise_id, tortoise, &tracklen);
uv_thread_join(&hare_id);
uv_thread_join(&tortoise_id);
return 0;
}

@ -1,48 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <uv.h>
uv_loop_t *loop;
uv_tty_t tty;
uv_timer_t tick;
uv_write_t write_req;
int width, height;
int pos = 0;
char *message = " Hello TTY ";
void update(uv_timer_t *req) {
char data[500];
uv_buf_t buf;
buf.base = data;
buf.len = sprintf(data, "\033[2J\033[H\033[%dB\033[%luC\033[42;37m%s",
pos,
(unsigned long) (width-strlen(message))/2,
message);
uv_write(&write_req, (uv_stream_t*) &tty, &buf, 1, NULL);
pos++;
if (pos > height) {
uv_tty_reset_mode();
uv_timer_stop(&tick);
}
}
int main() {
loop = uv_default_loop();
uv_tty_init(loop, &tty, STDOUT_FILENO, 0);
uv_tty_set_mode(&tty, 0);
if (uv_tty_get_winsize(&tty, &width, &height)) {
fprintf(stderr, "Could not get TTY information\n");
uv_tty_reset_mode();
return 1;
}
fprintf(stderr, "Width %d, height %d\n", width, height);
uv_timer_init(loop, &tick);
uv_timer_start(&tick, update, 200, 200);
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,29 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <uv.h>
uv_loop_t *loop;
uv_tty_t tty;
int main() {
loop = uv_default_loop();
uv_tty_init(loop, &tty, STDOUT_FILENO, 0);
uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL);
if (uv_guess_handle(1) == UV_TTY) {
uv_write_t req;
uv_buf_t buf;
buf.base = "\033[41;37m";
buf.len = strlen(buf.base);
uv_write(&req, (uv_stream_t*) &tty, &buf, 1, NULL);
}
uv_write_t req;
uv_buf_t buf;
buf.base = "Hello TTY\n";
buf.len = strlen(buf.base);
uv_write(&req, (uv_stream_t*) &tty, &buf, 1, NULL);
uv_tty_reset_mode();
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,127 +0,0 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
uv_loop_t *loop;
uv_udp_t send_socket;
uv_udp_t recv_socket;
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) {
if (nread < 0) {
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) req, NULL);
free(buf->base);
return;
}
char sender[17] = { 0 };
uv_ip4_name((const struct sockaddr_in*) addr, sender, 16);
fprintf(stderr, "Recv from %s\n", sender);
// ... DHCP specific code
unsigned int *as_integer = (unsigned int*)buf->base;
unsigned int ipbin = ntohl(as_integer[4]);
unsigned char ip[4] = {0};
int i;
for (i = 0; i < 4; i++)
ip[i] = (ipbin >> i*8) & 0xff;
fprintf(stderr, "Offered IP %d.%d.%d.%d\n", ip[3], ip[2], ip[1], ip[0]);
free(buf->base);
uv_udp_recv_stop(req);
}
uv_buf_t make_discover_msg() {
uv_buf_t buffer;
alloc_buffer(NULL, 256, &buffer);
memset(buffer.base, 0, buffer.len);
// BOOTREQUEST
buffer.base[0] = 0x1;
// HTYPE ethernet
buffer.base[1] = 0x1;
// HLEN
buffer.base[2] = 0x6;
// HOPS
buffer.base[3] = 0x0;
// XID 4 bytes
buffer.base[4] = (unsigned int) random();
// SECS
buffer.base[8] = 0x0;
// FLAGS
buffer.base[10] = 0x80;
// CIADDR 12-15 is all zeros
// YIADDR 16-19 is all zeros
// SIADDR 20-23 is all zeros
// GIADDR 24-27 is all zeros
// CHADDR 28-43 is the MAC address, use your own
buffer.base[28] = 0xe4;
buffer.base[29] = 0xce;
buffer.base[30] = 0x8f;
buffer.base[31] = 0x13;
buffer.base[32] = 0xf6;
buffer.base[33] = 0xd4;
// SNAME 64 bytes zero
// FILE 128 bytes zero
// OPTIONS
// - magic cookie
buffer.base[236] = 99;
buffer.base[237] = 130;
buffer.base[238] = 83;
buffer.base[239] = 99;
// DHCP Message type
buffer.base[240] = 53;
buffer.base[241] = 1;
buffer.base[242] = 1; // DHCPDISCOVER
// DHCP Parameter request list
buffer.base[243] = 55;
buffer.base[244] = 4;
buffer.base[245] = 1;
buffer.base[246] = 3;
buffer.base[247] = 15;
buffer.base[248] = 6;
return buffer;
}
void on_send(uv_udp_send_t *req, int status) {
if (status) {
fprintf(stderr, "Send error %s\n", uv_strerror(status));
return;
}
}
int main() {
loop = uv_default_loop();
uv_udp_init(loop, &recv_socket);
struct sockaddr_in recv_addr;
uv_ip4_addr("0.0.0.0", 68, &recv_addr);
uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
uv_udp_recv_start(&recv_socket, alloc_buffer, on_read);
uv_udp_init(loop, &send_socket);
struct sockaddr_in broadcast_addr;
uv_ip4_addr("0.0.0.0", 0, &broadcast_addr);
uv_udp_bind(&send_socket, (const struct sockaddr *)&broadcast_addr, 0);
uv_udp_set_broadcast(&send_socket, 1);
uv_udp_send_t send_req;
uv_buf_t discover_msg = make_discover_msg();
struct sockaddr_in send_addr;
uv_ip4_addr("255.255.255.255", 67, &send_addr);
uv_udp_send(&send_req, &send_socket, &discover_msg, 1, (const struct sockaddr *)&send_addr, on_send);
return uv_run(loop, UV_RUN_DEFAULT);
}

@ -1,63 +0,0 @@
#include <assert.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <uv.h>
void on_read(uv_fs_t *req);
uv_fs_t open_req;
uv_fs_t read_req;
uv_fs_t write_req;
static char buffer[1024];
static uv_buf_t iov;
void on_write(uv_fs_t *req) {
if (req->result < 0) {
fprintf(stderr, "Write error: %s\n", uv_strerror((int)req->result));
}
else {
uv_fs_read(uv_default_loop(), &read_req, open_req.result, &iov, 1, -1, on_read);
}
}
void on_read(uv_fs_t *req) {
if (req->result < 0) {
fprintf(stderr, "Read error: %s\n", uv_strerror(req->result));
}
else if (req->result == 0) {
uv_fs_t close_req;
// synchronous
uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
}
else if (req->result > 0) {
iov.len = req->result;
uv_fs_write(uv_default_loop(), &write_req, 1, &iov, 1, -1, on_write);
}
}
void on_open(uv_fs_t *req) {
// The request passed to the callback is the same as the one the call setup
// function was passed.
assert(req == &open_req);
if (req->result >= 0) {
iov = uv_buf_init(buffer, sizeof(buffer));
uv_fs_read(uv_default_loop(), &read_req, req->result,
&iov, 1, -1, on_read);
}
else {
fprintf(stderr, "error opening file: %s\n", uv_strerror((int)req->result));
}
}
int main(int argc, char **argv) {
uv_fs_open(uv_default_loop(), &open_req, argv[1], O_RDONLY, 0, on_open);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_fs_req_cleanup(&open_req);
uv_fs_req_cleanup(&read_req);
uv_fs_req_cleanup(&write_req);
return 0;
}

@ -1,33 +0,0 @@
#include <stdio.h>
#include <uv.h>
int64_t counter = 0;
void idle_cb(uv_idle_t *handle) {
printf("Idle callback\n");
counter++;
if (counter >= 5) {
uv_stop(uv_default_loop());
printf("uv_stop() called\n");
}
}
void prep_cb(uv_prepare_t *handle) {
printf("Prep callback\n");
}
int main() {
uv_idle_t idler;
uv_prepare_t prep;
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, idle_cb);
uv_prepare_init(uv_default_loop(), &prep);
uv_prepare_start(&prep, prep_cb);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
return 0;
}

@ -1,80 +0,0 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <uv.h>
typedef struct {
uv_write_t req;
uv_buf_t buf;
} write_req_t;
uv_loop_t *loop;
uv_pipe_t stdin_pipe;
uv_pipe_t stdout_pipe;
uv_pipe_t file_pipe;
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
*buf = uv_buf_init((char*) malloc(suggested_size), suggested_size);
}
void free_write_req(uv_write_t *req) {
write_req_t *wr = (write_req_t*) req;
free(wr->buf.base);
free(wr);
}
void on_stdout_write(uv_write_t *req, int status) {
free_write_req(req);
}
void on_file_write(uv_write_t *req, int status) {
free_write_req(req);
}
void write_data(uv_stream_t *dest, size_t size, uv_buf_t buf, uv_write_cb cb) {
write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
req->buf = uv_buf_init((char*) malloc(size), size);
memcpy(req->buf.base, buf.base, size);
uv_write((uv_write_t*) req, (uv_stream_t*)dest, &req->buf, 1, cb);
}
void read_stdin(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
if (nread < 0){
if (nread == UV_EOF){
// end of file
uv_close((uv_handle_t *)&stdin_pipe, NULL);
uv_close((uv_handle_t *)&stdout_pipe, NULL);
uv_close((uv_handle_t *)&file_pipe, NULL);
}
} else if (nread > 0) {
write_data((uv_stream_t *)&stdout_pipe, nread, *buf, on_stdout_write);
write_data((uv_stream_t *)&file_pipe, nread, *buf, on_file_write);
}
// OK to free buffer as write_data copies it.
if (buf->base)
free(buf->base);
}
int main(int argc, char **argv) {
loop = uv_default_loop();
uv_pipe_init(loop, &stdin_pipe, 0);
uv_pipe_open(&stdin_pipe, 0);
uv_pipe_init(loop, &stdout_pipe, 0);
uv_pipe_open(&stdout_pipe, 1);
uv_fs_t file_req;
int fd = uv_fs_open(loop, &file_req, argv[1], O_CREAT | O_RDWR, 0644, NULL);
uv_pipe_init(loop, &file_pipe, 0);
uv_pipe_open(&file_pipe, fd);
uv_read_start((uv_stream_t*)&stdin_pipe, alloc_buffer, read_stdin);
uv_run(loop, UV_RUN_DEFAULT);
return 0;
}

@ -1,166 +0,0 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
#include <curl/curl.h>
uv_loop_t *loop;
CURLM *curl_handle;
uv_timer_t timeout;
typedef struct curl_context_s {
uv_poll_t poll_handle;
curl_socket_t sockfd;
} curl_context_t;
curl_context_t *create_curl_context(curl_socket_t sockfd) {
curl_context_t *context;
context = (curl_context_t*) malloc(sizeof *context);
context->sockfd = sockfd;
int r = uv_poll_init_socket(loop, &context->poll_handle, sockfd);
assert(r == 0);
context->poll_handle.data = context;
return context;
}
void curl_close_cb(uv_handle_t *handle) {
curl_context_t *context = (curl_context_t*) handle->data;
free(context);
}
void destroy_curl_context(curl_context_t *context) {
uv_close((uv_handle_t*) &context->poll_handle, curl_close_cb);
}
void add_download(const char *url, int num) {
char filename[50];
sprintf(filename, "%d.download", num);
FILE *file;
file = fopen(filename, "w");
if (file == NULL) {
fprintf(stderr, "Error opening %s\n", filename);
return;
}
CURL *handle = curl_easy_init();
curl_easy_setopt(handle, CURLOPT_WRITEDATA, file);
curl_easy_setopt(handle, CURLOPT_URL, url);
curl_multi_add_handle(curl_handle, handle);
fprintf(stderr, "Added download %s -> %s\n", url, filename);
}
void check_multi_info(void) {
char *done_url;
CURLMsg *message;
int pending;
while ((message = curl_multi_info_read(curl_handle, &pending))) {
switch (message->msg) {
case CURLMSG_DONE:
curl_easy_getinfo(message->easy_handle, CURLINFO_EFFECTIVE_URL,
&done_url);
printf("%s DONE\n", done_url);
curl_multi_remove_handle(curl_handle, message->easy_handle);
curl_easy_cleanup(message->easy_handle);
break;
default:
fprintf(stderr, "CURLMSG default\n");
abort();
}
}
}
void curl_perform(uv_poll_t *req, int status, int events) {
uv_timer_stop(&timeout);
int running_handles;
int flags = 0;
if (status < 0) flags = CURL_CSELECT_ERR;
if (!status && events & UV_READABLE) flags |= CURL_CSELECT_IN;
if (!status && events & UV_WRITABLE) flags |= CURL_CSELECT_OUT;
curl_context_t *context;
context = (curl_context_t*)req;
curl_multi_socket_action(curl_handle, context->sockfd, flags, &running_handles);
check_multi_info();
}
void on_timeout(uv_timer_t *req) {
int running_handles;
curl_multi_socket_action(curl_handle, CURL_SOCKET_TIMEOUT, 0, &running_handles);
check_multi_info();
}
void start_timeout(CURLM *multi, long timeout_ms, void *userp) {
if (timeout_ms <= 0)
timeout_ms = 1; /* 0 means directly call socket_action, but we'll do it in a bit */
uv_timer_start(&timeout, on_timeout, timeout_ms, 0);
}
int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) {
curl_context_t *curl_context;
if (action == CURL_POLL_IN || action == CURL_POLL_OUT) {
if (socketp) {
curl_context = (curl_context_t*) socketp;
}
else {
curl_context = create_curl_context(s);
curl_multi_assign(curl_handle, s, (void *) curl_context);
}
}
switch (action) {
case CURL_POLL_IN:
uv_poll_start(&curl_context->poll_handle, UV_READABLE, curl_perform);
break;
case CURL_POLL_OUT:
uv_poll_start(&curl_context->poll_handle, UV_WRITABLE, curl_perform);
break;
case CURL_POLL_REMOVE:
if (socketp) {
uv_poll_stop(&((curl_context_t*)socketp)->poll_handle);
destroy_curl_context((curl_context_t*) socketp);
curl_multi_assign(curl_handle, s, NULL);
}
break;
default:
abort();
}
return 0;
}
int main(int argc, char **argv) {
loop = uv_default_loop();
if (argc <= 1)
return 0;
if (curl_global_init(CURL_GLOBAL_ALL)) {
fprintf(stderr, "Could not init cURL\n");
return 1;
}
uv_timer_init(loop, &timeout);
curl_handle = curl_multi_init();
curl_multi_setopt(curl_handle, CURLMOPT_SOCKETFUNCTION, handle_socket);
curl_multi_setopt(curl_handle, CURLMOPT_TIMERFUNCTION, start_timeout);
while (argc-- > 1) {
add_download(argv[argc], argc);
}
uv_run(loop, UV_RUN_DEFAULT);
curl_multi_cleanup(curl_handle);
return 0;
}

@ -1,243 +0,0 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=build
set SRCDIR=src
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SRCDIR%
set I18NSPHINXOPTS=%SPHINXOPTS% %SRCDIR%
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\libuv.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\libuv.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end

@ -1,42 +0,0 @@
# 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

@ -1,36 +0,0 @@
.. _api:
API documentation
=================
.. toctree::
:maxdepth: 1
errors
version
loop
handle
request
timer
prepare
check
idle
async
poll
signal
process
stream
tcp
pipe
tty
udp
fs_event
fs_poll
fs
threadpool
dns
dll
threading
misc
metrics

@ -1,65 +0,0 @@
.. _async:
:c:type:`uv_async_t` --- Async handle
=====================================
Async handles allow the user to "wakeup" the event loop and get a callback
called from another thread.
Data types
----------
.. c:type:: uv_async_t
Async handle type.
.. c:type:: void (*uv_async_cb)(uv_async_t* handle)
Type definition for callback passed to :c:func:`uv_async_init`.
Public members
^^^^^^^^^^^^^^
N/A
.. seealso:: The :c:type:`uv_handle_t` members also apply.
API
---
.. c:function:: int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb)
Initialize the handle. A NULL callback is allowed.
:returns: 0 on success, or an error code < 0 on failure.
.. note::
Unlike other handle initialization functions, it immediately starts the handle.
.. c:function:: int uv_async_send(uv_async_t* async)
Wake up the event loop and call the async handle's callback.
:returns: 0 on success, or an error code < 0 on failure.
.. note::
It's safe to call this function from any thread. The callback will be called on the
loop thread.
.. note::
: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::
libuv will coalesce calls to :c:func:`uv_async_send`, that is, not every call to it will
yield an execution of the callback. For example: if :c:func:`uv_async_send` is called 5
times in a row before the callback is called, the callback will only be called once. If
:c:func:`uv_async_send` is called again after the callback was called, it will be called
again.
.. seealso::
The :c:type:`uv_handle_t` API functions also apply.

@ -1,54 +0,0 @@
.. _check:
:c:type:`uv_check_t` --- Check handle
=====================================
Check handles will run the given callback once per loop iteration, right
after polling for i/o.
Data types
----------
.. c:type:: uv_check_t
Check handle type.
.. c:type:: void (*uv_check_cb)(uv_check_t* handle)
Type definition for callback passed to :c:func:`uv_check_start`.
Public members
^^^^^^^^^^^^^^
N/A
.. seealso:: The :c:type:`uv_handle_t` members also apply.
API
---
.. c:function:: int uv_check_init(uv_loop_t* loop, uv_check_t* check)
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. 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.

@ -1,348 +0,0 @@
# -*- coding: utf-8 -*-
#
# libuv documentation documentation build configuration file, created by
# sphinx-quickstart on Sun Jul 27 11:47:51 2014.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
import re
import sys
def get_libuv_version():
with open('../../include/uv/version.h') as f:
data = f.read()
try:
m = re.search(r"""^#define UV_VERSION_MAJOR (\d+)$""", data, re.MULTILINE)
major = int(m.group(1))
m = re.search(r"""^#define UV_VERSION_MINOR (\d+)$""", data, re.MULTILINE)
minor = int(m.group(1))
m = re.search(r"""^#define UV_VERSION_PATCH (\d+)$""", data, re.MULTILINE)
patch = int(m.group(1))
m = re.search(r"""^#define UV_VERSION_IS_RELEASE (\d)$""", data, re.MULTILINE)
is_release = int(m.group(1))
m = re.search(r"""^#define UV_VERSION_SUFFIX \"(\w*)\"$""", data, re.MULTILINE)
suffix = m.group(1)
return '%d.%d.%d%s' % (major, minor, patch, '-%s' % suffix if not is_release else '')
except Exception:
return 'unknown'
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('sphinx-plugins'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['manpage']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'libuv API documentation'
copyright = u'2014-present, libuv contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = get_libuv_version()
# The full version, including alpha/beta/rc tags.
release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'nature'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = 'libuv documentation'
# A shorter title for the navigation bar. Default is the same as html_title.
html_short_title = 'libuv %s documentation' % version
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = 'static/logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = 'static/favicon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'libuv'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'libuv.tex', u'libuv documentation',
u'libuv contributors', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'libuv', u'libuv documentation',
[u'libuv contributors'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'libuv', u'libuv documentation',
u'libuv contributors', 'libuv', 'Cross-platform asynchronous I/O',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# -- Options for Epub output ----------------------------------------------
# Bibliographic Dublin Core info.
epub_title = u'libuv documentation'
epub_author = u'libuv contributors'
epub_publisher = u'libuv contributors'
epub_copyright = u'2014-present, libuv contributors'
# The basename for the epub file. It defaults to the project name.
epub_basename = u'libuv'
# The HTML theme for the epub output. Since the default themes are not optimized
# for small screen space, using the same theme for HTML and epub output is
# usually not wise. This defaults to 'epub', a theme designed to save visual
# space.
#epub_theme = 'epub'
# The language of the text. It defaults to the language option
# or en if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#epub_cover = ()
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
#epub_guide = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_pre_files = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
# Allow duplicate toc entries.
#epub_tocdup = True
# Choose between 'default' and 'includehidden'.
#epub_tocscope = 'default'
# Fix unsupported image types using the PIL.
#epub_fix_images = False
# Scale large images.
#epub_max_image_width = 0
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#epub_show_urls = 'inline'
# If false, no index is generated.
#epub_use_index = True

@ -1,140 +0,0 @@
.. _design:
Design overview
===============
libuv is cross-platform support library which was originally written for `Node.js`_. It's designed
around the event-driven asynchronous I/O model.
.. _Node.js: https://nodejs.org
The library provides much more than a simple abstraction over different I/O polling mechanisms:
'handles' and 'streams' provide a high level abstraction for sockets and other entities;
cross-platform file I/O and threading functionality is also provided, amongst other things.
Here is a diagram illustrating the different parts that compose libuv and what subsystem they
relate to:
.. image:: static/architecture.png
:scale: 75%
:align: center
Handles and requests
^^^^^^^^^^^^^^^^^^^^
libuv provides users with 2 abstractions to work with, in combination with the event loop:
handles and requests.
Handles represent long-lived objects capable of performing certain operations while active. Some examples:
- A prepare handle gets its callback called once every loop iteration when active.
- A TCP server handle that gets its connection callback called every time there is a new connection.
Requests represent (typically) short-lived operations. These operations can be performed over a
handle: write requests are used to write data on a handle; or standalone: getaddrinfo requests
don't need a handle they run directly on the loop.
The I/O loop
^^^^^^^^^^^^
The I/O (or event) loop is the central part of libuv. It establishes the content for all I/O
operations, and it's meant to be tied to a single thread. One can run multiple event loops
as long as each runs in a different thread. The libuv event loop (or any other API involving
the loop or handles, for that matter) **is not thread-safe** except where stated otherwise.
The event loop follows the rather usual single threaded asynchronous I/O approach: all (network)
I/O is performed on non-blocking sockets which are polled using the best mechanism available
on the given platform: epoll on Linux, kqueue on OSX and other BSDs, event ports on SunOS and IOCP
on Windows. As part of a loop iteration the loop will block waiting for I/O activity on sockets
which have been added to the poller and callbacks will be fired indicating socket conditions
(readable, writable hangup) so handles can read, write or perform the desired I/O operation.
In order to better understand how the event loop operates, the following diagram illustrates all
stages of a loop iteration:
.. image:: static/loop_iteration.png
:scale: 75%
:align: center
#. The loop concept of 'now' is updated. The event loop caches the current time at the start of
the event loop tick in order to reduce the number of time-related system calls.
#. If the loop is *alive* an iteration is started, otherwise the loop will exit immediately. So,
when is a loop considered to be *alive*? If a loop has active and ref'd handles, active
requests or closing handles it's considered to be *alive*.
#. Due timers are run. All active timers scheduled for a time before the loop's concept of *now*
get their callbacks called.
#. Pending callbacks are called. All I/O callbacks are called right after polling for I/O, for the
most part. There are cases, however, in which calling such a callback is deferred for the next
loop iteration. If the previous iteration deferred any I/O callback it will be run at this point.
#. Idle handle callbacks are called. Despite the unfortunate name, idle handles are run on every
loop iteration, if they are active.
#. Prepare handle callbacks are called. Prepare handles get their callbacks called right before
the loop will block for I/O.
#. Poll timeout is calculated. Before blocking for I/O the loop calculates for how long it should
block. These are the rules when calculating the timeout:
* If the loop was run with the ``UV_RUN_NOWAIT`` flag, the timeout is 0.
* If the loop is going to be stopped (:c:func:`uv_stop` was called), the timeout is 0.
* If there are no active handles or requests, the timeout is 0.
* If there are any idle handles active, the timeout is 0.
* If there are any handles pending to be closed, the timeout is 0.
* If none of the above cases matches, the timeout of the closest timer is taken, or
if there are no active timers, infinity.
#. The loop blocks for I/O. At this point the loop will block for I/O for the duration calculated
in the previous step. All I/O related handles that were monitoring a given file descriptor
for a read or write operation get their callbacks called at this point.
#. Check handle callbacks are called. Check handles get their callbacks called right after the
loop has blocked for I/O. Check handles are essentially the counterpart of prepare handles.
#. Close callbacks are called. If a handle was closed by calling :c:func:`uv_close` it will
get the close callback called.
#. Special case in case the loop was run with ``UV_RUN_ONCE``, as it implies forward progress.
It's possible that no I/O callbacks were fired after blocking for I/O, but some time has passed
so there might be timers which are due, those timers get their callbacks called.
#. Iteration ends. If the loop was run with ``UV_RUN_NOWAIT`` or ``UV_RUN_ONCE`` modes the
iteration ends and :c:func:`uv_run` will return. If the loop was run with ``UV_RUN_DEFAULT``
it will continue from the start if it's still *alive*, otherwise it will also end.
.. important::
libuv uses a thread pool to make asynchronous file I/O operations possible, but
network I/O is **always** performed in a single thread, each loop's thread.
.. note::
While the polling mechanism is different, libuv makes the execution model consistent
across Unix systems and Windows.
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
`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
operations are currently run on this pool:
* File system operations
* DNS functions (getaddrinfo and getnameinfo)
* User specified code via :c:func:`uv_queue_work`
.. warning::
See the :c:ref:`threadpool` section for more details, but keep in mind the thread pool size
is quite limited.

@ -1,44 +0,0 @@
.. _dll:
Shared library handling
=======================
libuv provides cross platform utilities for loading shared libraries and
retrieving symbols from them, using the following API.
Data types
----------
.. c:type:: uv_lib_t
Shared library data type.
Public members
^^^^^^^^^^^^^^
N/A
API
---
.. c:function:: int uv_dlopen(const char* filename, uv_lib_t* lib)
Opens a shared library. The filename is in utf-8. Returns 0 on success and
-1 on error. Call :c:func:`uv_dlerror` to get the error message.
.. c:function:: void uv_dlclose(uv_lib_t* lib)
Close the shared library.
.. c:function:: int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr)
Retrieves a data pointer from a dynamic library. It is legal for a symbol
to map to NULL. Returns 0 on success and -1 if the symbol was not found.
.. c:function:: const char* uv_dlerror(const uv_lib_t* lib)
Returns the last uv_dlopen() or uv_dlsym() error message.

@ -1,108 +0,0 @@
.. _dns:
DNS utility functions
=====================
libuv provides asynchronous variants of `getaddrinfo` and `getnameinfo`.
Data types
----------
.. c:type:: uv_getaddrinfo_t
`getaddrinfo` request type.
.. c:type:: void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, int status, struct addrinfo* res)
Callback which will be called with the getaddrinfo request result once
complete. In case it was cancelled, `status` will have a value of
``UV_ECANCELED``.
.. c:type:: uv_getnameinfo_t
`getnameinfo` request type.
.. c:type:: void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, int status, const char* hostname, const char* service)
Callback which will be called with the getnameinfo request result once
complete. In case it was cancelled, `status` will have a value of
``UV_ECANCELED``.
Public members
^^^^^^^^^^^^^^
.. c:member:: uv_loop_t* uv_getaddrinfo_t.loop
Loop that started this getaddrinfo request and where completion will be
reported. Readonly.
.. c:member:: struct addrinfo* uv_getaddrinfo_t.addrinfo
Pointer to a `struct addrinfo` containing the result. Must be freed by the user
with :c:func:`uv_freeaddrinfo`.
.. versionchanged:: 1.3.0 the field is declared as public.
.. c:member:: uv_loop_t* uv_getnameinfo_t.loop
Loop that started this getnameinfo request and where completion will be
reported. Readonly.
.. c:member:: char[NI_MAXHOST] uv_getnameinfo_t.host
Char array containing the resulting host. It's null terminated.
.. versionchanged:: 1.3.0 the field is declared as public.
.. c:member:: char[NI_MAXSERV] uv_getnameinfo_t.service
Char array containing the resulting service. It's null terminated.
.. versionchanged:: 1.3.0 the field is declared as public.
.. seealso:: The :c:type:`uv_req_t` members also apply.
API
---
.. c:function:: int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints)
Asynchronous :man:`getaddrinfo(3)`.
Either node or service may be NULL but not both.
`hints` is a pointer to a struct addrinfo with additional address type
constraints, or NULL. Consult `man -s 3 getaddrinfo` for more details.
Returns 0 on success or an error code < 0 on failure. If successful, the
callback will get called sometime in the future with the lookup result,
which is either:
* status == 0, the res argument points to a valid `struct addrinfo`, or
* status < 0, the res argument is NULL. See the UV_EAI_* constants.
Call :c:func:`uv_freeaddrinfo` to free the addrinfo structure.
.. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL,
in which case the request will run **synchronously**.
.. c:function:: void uv_freeaddrinfo(struct addrinfo* ai)
Free the struct addrinfo. Passing NULL is allowed and is a no-op.
.. c:function:: int uv_getnameinfo(uv_loop_t* loop, uv_getnameinfo_t* req, uv_getnameinfo_cb getnameinfo_cb, const struct sockaddr* addr, int flags)
Asynchronous :man:`getnameinfo(3)`.
Returns 0 on success or an error code < 0 on failure. If successful, the
callback will get called sometime in the future with the lookup result.
Consult `man -s 3 getnameinfo` for more details.
.. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL,
in which case the request will run **synchronously**.
.. seealso:: The :c:type:`uv_req_t` API functions also apply.

@ -1,385 +0,0 @@
.. _errors:
Error handling
==============
In libuv errors are negative numbered constants. As a rule of thumb, whenever
there is a status parameter, or an API functions returns an integer, a negative
number will imply an error.
When a function which takes a callback returns an error, the callback will never
be called.
.. note::
Implementation detail: on Unix error codes are the negated `errno` (or `-errno`), while on
Windows they are defined by libuv to arbitrary negative numbers.
Error constants
---------------
.. c:macro:: UV_E2BIG
argument list too long
.. c:macro:: UV_EACCES
permission denied
.. c:macro:: UV_EADDRINUSE
address already in use
.. c:macro:: UV_EADDRNOTAVAIL
address not available
.. c:macro:: UV_EAFNOSUPPORT
address family not supported
.. c:macro:: UV_EAGAIN
resource temporarily unavailable
.. c:macro:: UV_EAI_ADDRFAMILY
address family not supported
.. c:macro:: UV_EAI_AGAIN
temporary failure
.. c:macro:: UV_EAI_BADFLAGS
bad ai_flags value
.. c:macro:: UV_EAI_BADHINTS
invalid value for hints
.. c:macro:: UV_EAI_CANCELED
request canceled
.. c:macro:: UV_EAI_FAIL
permanent failure
.. c:macro:: UV_EAI_FAMILY
ai_family not supported
.. c:macro:: UV_EAI_MEMORY
out of memory
.. c:macro:: UV_EAI_NODATA
no address
.. c:macro:: UV_EAI_NONAME
unknown node or service
.. c:macro:: UV_EAI_OVERFLOW
argument buffer overflow
.. c:macro:: UV_EAI_PROTOCOL
resolved protocol is unknown
.. c:macro:: UV_EAI_SERVICE
service not available for socket type
.. c:macro:: UV_EAI_SOCKTYPE
socket type not supported
.. c:macro:: UV_EALREADY
connection already in progress
.. c:macro:: UV_EBADF
bad file descriptor
.. c:macro:: UV_EBUSY
resource busy or locked
.. c:macro:: UV_ECANCELED
operation canceled
.. c:macro:: UV_ECHARSET
invalid Unicode character
.. c:macro:: UV_ECONNABORTED
software caused connection abort
.. c:macro:: UV_ECONNREFUSED
connection refused
.. c:macro:: UV_ECONNRESET
connection reset by peer
.. c:macro:: UV_EDESTADDRREQ
destination address required
.. c:macro:: UV_EEXIST
file already exists
.. c:macro:: UV_EFAULT
bad address in system call argument
.. c:macro:: UV_EFBIG
file too large
.. c:macro:: UV_EHOSTUNREACH
host is unreachable
.. c:macro:: UV_EINTR
interrupted system call
.. c:macro:: UV_EINVAL
invalid argument
.. c:macro:: UV_EIO
i/o error
.. c:macro:: UV_EISCONN
socket is already connected
.. c:macro:: UV_EISDIR
illegal operation on a directory
.. c:macro:: UV_ELOOP
too many symbolic links encountered
.. c:macro:: UV_EMFILE
too many open files
.. c:macro:: UV_EMSGSIZE
message too long
.. c:macro:: UV_ENAMETOOLONG
name too long
.. c:macro:: UV_ENETDOWN
network is down
.. c:macro:: UV_ENETUNREACH
network is unreachable
.. c:macro:: UV_ENFILE
file table overflow
.. c:macro:: UV_ENOBUFS
no buffer space available
.. c:macro:: UV_ENODEV
no such device
.. c:macro:: UV_ENOENT
no such file or directory
.. c:macro:: UV_ENOMEM
not enough memory
.. c:macro:: UV_ENONET
machine is not on the network
.. c:macro:: UV_ENOPROTOOPT
protocol not available
.. c:macro:: UV_ENOSPC
no space left on device
.. c:macro:: UV_ENOSYS
function not implemented
.. c:macro:: UV_ENOTCONN
socket is not connected
.. c:macro:: UV_ENOTDIR
not a directory
.. c:macro:: UV_ENOTEMPTY
directory not empty
.. c:macro:: UV_ENOTSOCK
socket operation on non-socket
.. c:macro:: UV_ENOTSUP
operation not supported on socket
.. c:macro:: UV_EOVERFLOW
value too large for defined data type
.. c:macro:: UV_EPERM
operation not permitted
.. c:macro:: UV_EPIPE
broken pipe
.. c:macro:: UV_EPROTO
protocol error
.. c:macro:: UV_EPROTONOSUPPORT
protocol not supported
.. c:macro:: UV_EPROTOTYPE
protocol wrong type for socket
.. c:macro:: UV_ERANGE
result too large
.. c:macro:: UV_EROFS
read-only file system
.. c:macro:: UV_ESHUTDOWN
cannot send after transport endpoint shutdown
.. c:macro:: UV_ESPIPE
invalid seek
.. c:macro:: UV_ESRCH
no such process
.. c:macro:: UV_ETIMEDOUT
connection timed out
.. c:macro:: UV_ETXTBSY
text file is busy
.. c:macro:: UV_EXDEV
cross-device link not permitted
.. c:macro:: UV_UNKNOWN
unknown error
.. c:macro:: UV_EOF
end of file
.. c:macro:: UV_ENXIO
no such device or address
.. c:macro:: UV_EMLINK
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: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
arguments: the name of the error constant without the `UV_` prefix,
and the error message string literal.
.. c:function:: const char* uv_strerror(int err)
Returns the error message for the given error code. Leaks a few bytes
of memory when you call it with an unknown error code.
.. c:function:: char* uv_strerror_r(int err, char* buf, size_t buflen)
Returns the error message for the given error code. The zero-terminated
message is stored in the user-supplied buffer `buf` of at most `buflen` bytes.
.. versionadded:: 1.22.0
.. c:function:: const char* uv_err_name(int err)
Returns the error name for the given error code. Leaks a few bytes
of memory when you call it with an unknown error code.
.. c:function:: char* uv_err_name_r(int err, char* buf, size_t buflen)
Returns the error name for the given error code. The zero-terminated
name is stored in the user-supplied buffer `buf` of at most `buflen` bytes.
.. versionadded:: 1.22.0
.. c:function:: int uv_translate_sys_error(int sys_errno)
Returns the libuv error code equivalent to the given platform dependent error
code: POSIX error codes on Unix (the ones stored in `errno`), and Win32 error
codes on Windows (those returned by `GetLastError()` or `WSAGetLastError()`).
If `sys_errno` is already a libuv error, it is simply returned.
.. versionchanged:: 1.10.0 function declared public.

@ -1,702 +0,0 @@
.. _fs:
File system operations
======================
libuv provides a wide variety of cross-platform sync and async file system
operations. All functions defined in this document take a callback, which is
allowed to be NULL. If the callback is NULL the request is completed synchronously,
otherwise it will be performed asynchronously.
All file operations are run on the threadpool. See :ref:`threadpool` for information
on the threadpool size.
.. note::
On Windows `uv_fs_*` functions use utf-8 encoding.
Data types
----------
.. c:type:: uv_fs_t
File system request type.
.. c:type:: uv_timespec_t
Portable equivalent of ``struct timespec``.
::
typedef struct {
long tv_sec;
long tv_nsec;
} uv_timespec_t;
.. c:type:: uv_stat_t
Portable equivalent of ``struct stat``.
::
typedef struct {
uint64_t st_dev;
uint64_t st_mode;
uint64_t st_nlink;
uint64_t st_uid;
uint64_t st_gid;
uint64_t st_rdev;
uint64_t st_ino;
uint64_t st_size;
uint64_t st_blksize;
uint64_t st_blocks;
uint64_t st_flags;
uint64_t st_gen;
uv_timespec_t st_atim;
uv_timespec_t st_mtim;
uv_timespec_t st_ctim;
uv_timespec_t st_birthtim;
} uv_stat_t;
.. c:enum:: uv_fs_type
File system request type.
::
typedef enum {
UV_FS_UNKNOWN = -1,
UV_FS_CUSTOM,
UV_FS_OPEN,
UV_FS_CLOSE,
UV_FS_READ,
UV_FS_WRITE,
UV_FS_SENDFILE,
UV_FS_STAT,
UV_FS_LSTAT,
UV_FS_FSTAT,
UV_FS_FTRUNCATE,
UV_FS_UTIME,
UV_FS_FUTIME,
UV_FS_ACCESS,
UV_FS_CHMOD,
UV_FS_FCHMOD,
UV_FS_FSYNC,
UV_FS_FDATASYNC,
UV_FS_UNLINK,
UV_FS_RMDIR,
UV_FS_MKDIR,
UV_FS_MKDTEMP,
UV_FS_RENAME,
UV_FS_SCANDIR,
UV_FS_LINK,
UV_FS_SYMLINK,
UV_FS_READLINK,
UV_FS_CHOWN,
UV_FS_FCHOWN,
UV_FS_REALPATH,
UV_FS_COPYFILE,
UV_FS_LCHOWN,
UV_FS_OPENDIR,
UV_FS_READDIR,
UV_FS_CLOSEDIR,
UV_FS_MKSTEMP,
UV_FS_LUTIME
} uv_fs_type;
.. c:type:: uv_statfs_t
Reduced cross platform equivalent of ``struct statfs``.
Used in :c:func:`uv_fs_statfs`.
::
typedef struct uv_statfs_s {
uint64_t f_type;
uint64_t f_bsize;
uint64_t f_blocks;
uint64_t f_bfree;
uint64_t f_bavail;
uint64_t f_files;
uint64_t f_ffree;
uint64_t f_spare[4];
} uv_statfs_t;
.. c:enum:: uv_dirent_t
Cross platform (reduced) equivalent of ``struct dirent``.
Used in :c:func:`uv_fs_scandir_next`.
::
typedef enum {
UV_DIRENT_UNKNOWN,
UV_DIRENT_FILE,
UV_DIRENT_DIR,
UV_DIRENT_LINK,
UV_DIRENT_FIFO,
UV_DIRENT_SOCKET,
UV_DIRENT_CHAR,
UV_DIRENT_BLOCK
} uv_dirent_type_t;
typedef struct uv_dirent_s {
const char* name;
uv_dirent_type_t type;
} uv_dirent_t;
.. c:type:: uv_dir_t
Data type used for streaming directory iteration.
Used by :c:func:`uv_fs_opendir()`, :c:func:`uv_fs_readdir()`, and
:c:func:`uv_fs_closedir()`. `dirents` represents a user provided array of
`uv_dirent_t`s used to hold results. `nentries` is the user provided maximum
array size of `dirents`.
::
typedef struct uv_dir_s {
uv_dirent_t* dirents;
size_t nentries;
} uv_dir_t;
Public members
^^^^^^^^^^^^^^
.. c:member:: uv_loop_t* uv_fs_t.loop
Loop that started this request and where completion will be reported.
Readonly.
.. c:member:: uv_fs_type uv_fs_t.fs_type
FS request type.
.. c:member:: const char* uv_fs_t.path
Path affecting the request.
.. c:member:: ssize_t uv_fs_t.result
Result of the request. < 0 means error, success otherwise. On requests such
as :c:func:`uv_fs_read` or :c:func:`uv_fs_write` it indicates the amount of
data that was read or written, respectively.
.. c:member:: uv_stat_t uv_fs_t.statbuf
Stores the result of :c:func:`uv_fs_stat` and other stat requests.
.. c:member:: void* uv_fs_t.ptr
Stores the result of :c:func:`uv_fs_readlink` and
:c:func:`uv_fs_realpath` and serves as an alias to `statbuf`.
.. seealso:: The :c:type:`uv_req_t` members also apply.
API
---
.. c:function:: void uv_fs_req_cleanup(uv_fs_t* req)
Cleanup request. Must be called after a request is finished to deallocate
any memory libuv might have allocated.
.. c:function:: int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
Equivalent to :man:`close(2)`.
.. c:function:: int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb)
Equivalent to :man:`open(2)`.
.. note::
On Windows libuv uses `CreateFileW` and thus the file is always opened
in binary mode. Because of this the O_BINARY and O_TEXT flags are not
supported.
.. c:function:: int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
Equivalent to :man:`preadv(2)`.
.. warning::
On Windows, under non-MSVC environments (e.g. when GCC or Clang is used
to build libuv), files opened using ``UV_FS_O_FILEMAP`` may cause a fatal
crash if the memory mapped read operation fails.
.. c:function:: int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Equivalent to :man:`unlink(2)`.
.. c:function:: int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
Equivalent to :man:`pwritev(2)`.
.. warning::
On Windows, under non-MSVC environments (e.g. when GCC or Clang is used
to build libuv), files opened using ``UV_FS_O_FILEMAP`` may cause a fatal
crash if the memory mapped write operation fails.
.. c:function:: int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
Equivalent to :man:`mkdir(2)`.
.. note::
`mode` is currently not implemented on Windows.
.. c:function:: int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb)
Equivalent to :man:`mkdtemp(3)`. The result can be found as a null terminated string at `req->path`.
.. c:function:: int uv_fs_mkstemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb)
Equivalent to :man:`mkstemp(3)`. The created file path can be found as a null terminated string at `req->path`.
The file descriptor can be found as an integer at `req->result`.
.. versionadded:: 1.34.0
.. c:function:: int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Equivalent to :man:`rmdir(2)`.
.. c:function:: int uv_fs_opendir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Opens `path` as a directory stream. On success, a `uv_dir_t` is allocated
and returned via `req->ptr`. This memory is not freed by
`uv_fs_req_cleanup()`, although `req->ptr` is set to `NULL`. The allocated
memory must be freed by calling `uv_fs_closedir()`. On failure, no memory
is allocated.
The contents of the directory can be iterated over by passing the resulting
`uv_dir_t` to `uv_fs_readdir()`.
.. versionadded:: 1.28.0
.. c:function:: int uv_fs_closedir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb)
Closes the directory stream represented by `dir` and frees the memory
allocated by `uv_fs_opendir()`.
.. versionadded:: 1.28.0
.. c:function:: int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb)
Iterates over the directory stream, `dir`, returned by a successful
`uv_fs_opendir()` call. Prior to invoking `uv_fs_readdir()`, the caller
must set `dir->dirents` and `dir->nentries`, representing the array of
:c:type:`uv_dirent_t` elements used to hold the read directory entries and
its size.
On success, the result is an integer >= 0 representing the number of entries
read from the stream.
.. versionadded:: 1.28.0
.. warning::
`uv_fs_readdir()` is not thread safe.
.. note::
This function does not return the "." and ".." entries.
.. note::
On success this function allocates memory that must be freed using
`uv_fs_req_cleanup()`. `uv_fs_req_cleanup()` must be called before
closing the directory with `uv_fs_closedir()`.
.. c:function:: int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb)
.. c:function:: int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent)
Equivalent to :man:`scandir(3)`, with a slightly different API. Once the callback
for the request is called, the user can use :c:func:`uv_fs_scandir_next` to
get `ent` populated with the next directory entry data. When there are no
more entries ``UV_EOF`` will be returned.
.. note::
Unlike `scandir(3)`, this function does not return the "." and ".." entries.
.. note::
On Linux, getting the type of an entry is only supported by some file systems (btrfs, ext2,
ext3 and ext4 at the time of this writing), check the :man:`getdents(2)` man page.
.. c:function:: int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
.. c:function:: int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
.. c:function:: int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Equivalent to :man:`stat(2)`, :man:`fstat(2)` and :man:`lstat(2)` respectively.
.. c:function:: int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Equivalent to :man:`statfs(2)`. On success, a `uv_statfs_t` is allocated
and returned via `req->ptr`. This memory is freed by `uv_fs_req_cleanup()`.
.. note::
Any fields in the resulting `uv_statfs_t` that are not supported by the
underlying operating system are set to zero.
.. versionadded:: 1.31.0
.. c:function:: int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb)
Equivalent to :man:`rename(2)`.
.. c:function:: int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
Equivalent to :man:`fsync(2)`.
.. note::
For AIX, `uv_fs_fsync` returns `UV_EBADF` on file descriptors referencing
non regular files.
.. c:function:: int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
Equivalent to :man:`fdatasync(2)`.
.. c:function:: int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb)
Equivalent to :man:`ftruncate(2)`.
.. c:function:: 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)
Copies a file from `path` to `new_path`. Supported `flags` are described below.
- `UV_FS_COPYFILE_EXCL`: If present, `uv_fs_copyfile()` will fail with
`UV_EEXIST` if the destination path already exists. The default behavior
is to overwrite the destination if it exists.
- `UV_FS_COPYFILE_FICLONE`: If present, `uv_fs_copyfile()` will attempt to
create a copy-on-write reflink. If the underlying platform does not
support copy-on-write, or an error occurs while attempting to use
copy-on-write, a fallback copy mechanism based on
:c:func:`uv_fs_sendfile()` is used.
- `UV_FS_COPYFILE_FICLONE_FORCE`: If present, `uv_fs_copyfile()` will
attempt to create a copy-on-write reflink. If the underlying platform does
not support copy-on-write, or an error occurs while attempting to use
copy-on-write, then an error is returned.
.. warning::
If the destination path is created, but an error occurs while copying
the data, then the destination path is removed. There is a brief window
of time between closing and removing the file where another process
could access the file.
.. versionadded:: 1.14.0
.. versionchanged:: 1.20.0 `UV_FS_COPYFILE_FICLONE` and
`UV_FS_COPYFILE_FICLONE_FORCE` are supported.
.. versionchanged:: 1.33.0 If an error occurs while using
`UV_FS_COPYFILE_FICLONE_FORCE`, that error is returned. Previously,
all errors were mapped to `UV_ENOTSUP`.
.. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb)
Limited equivalent to :man:`sendfile(2)`.
.. c:function:: int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
Equivalent to :man:`access(2)` on Unix. Windows uses ``GetFileAttributesW()``.
.. c:function:: int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
.. c:function:: int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb)
Equivalent to :man:`chmod(2)` and :man:`fchmod(2)` respectively.
.. 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)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively.
.. note::
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
.. c:function:: int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb)
Equivalent to :man:`link(2)`.
.. c:function:: 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)
Equivalent to :man:`symlink(2)`.
.. note::
On Windows the `flags` parameter can be specified to control how the symlink will
be created:
* ``UV_FS_SYMLINK_DIR``: indicates that `path` points to a directory.
* ``UV_FS_SYMLINK_JUNCTION``: request that the symlink is created
using junction points.
.. c:function:: int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Equivalent to :man:`readlink(2)`.
The resulting string is stored in `req->ptr`.
.. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Equivalent to :man:`realpath(3)` on Unix. Windows uses `GetFinalPathNameByHandle <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlea>`_.
The resulting string is stored in `req->ptr`.
.. warning::
This function has certain platform-specific caveats that were discovered when used in Node.
* macOS and other BSDs: this function will fail with UV_ELOOP if more than 32 symlinks are
found while resolving the given path. This limit is hardcoded and cannot be sidestepped.
* Windows: while this function works in the common case, there are a number of corner cases
where it doesn't:
- Paths in ramdisk volumes created by tools which sidestep the Volume Manager (such as ImDisk)
cannot be resolved.
- Inconsistent casing when using drive letters.
- Resolved path bypasses subst'd drives.
While this function can still be used, it's not recommended if scenarios such as the
above need to be supported.
The background story and some more details on these issues can be checked
`here <https://github.com/nodejs/node/issues/7726>`_.
.. note::
This function is not implemented on Windows XP and Windows Server 2003.
On these systems, UV_ENOSYS is returned.
.. versionadded:: 1.8.0
.. c:function:: 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)
.. c:function:: 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)
.. c:function:: 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)
Equivalent to :man:`chown(2)`, :man:`fchown(2)` and :man:`lchown(2)` respectively.
.. note::
These functions are not implemented on Windows.
.. versionchanged:: 1.21.0 implemented uv_fs_lchown
.. c:function:: uv_fs_type uv_fs_get_type(const uv_fs_t* req)
Returns `req->fs_type`.
.. versionadded:: 1.19.0
.. c:function:: ssize_t uv_fs_get_result(const uv_fs_t* req)
Returns `req->result`.
.. 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`.
.. versionadded:: 1.19.0
.. c:function:: const char* uv_fs_get_path(const uv_fs_t* req)
Returns `req->path`.
.. versionadded:: 1.19.0
.. c:function:: uv_stat_t* uv_fs_get_statbuf(uv_fs_t* req)
Returns `&req->statbuf`.
.. versionadded:: 1.19.0
.. seealso:: The :c:type:`uv_req_t` API functions also apply.
Helper functions
----------------
.. c:function:: uv_os_fd_t uv_get_osfhandle(int fd)
For a file descriptor in the C runtime, get the OS-dependent handle.
On UNIX, returns the ``fd`` intact. On Windows, this calls `_get_osfhandle <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=vs-2019>`_.
Note that the return value is still owned by the C runtime,
any attempts to close it or to use it after closing the fd may lead to malfunction.
.. versionadded:: 1.12.0
.. c:function:: int uv_open_osfhandle(uv_os_fd_t os_fd)
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 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
File open constants
-------------------
.. c:macro:: UV_FS_O_APPEND
The file is opened in append mode. Before each write, the file offset is
positioned at the end of the file.
.. c:macro:: UV_FS_O_CREAT
The file is created if it does not already exist.
.. c:macro:: UV_FS_O_DIRECT
File I/O is done directly to and from user-space buffers, which must be
aligned. Buffer size and address should be a multiple of the physical sector
size of the block device.
.. note::
`UV_FS_O_DIRECT` is supported on Linux, and on Windows via
`FILE_FLAG_NO_BUFFERING <https://docs.microsoft.com/en-us/windows/win32/fileio/file-buffering>`_.
`UV_FS_O_DIRECT` is not supported on macOS.
.. c:macro:: UV_FS_O_DIRECTORY
If the path is not a directory, fail the open.
.. note::
`UV_FS_O_DIRECTORY` is not supported on Windows.
.. c:macro:: UV_FS_O_DSYNC
The file is opened for synchronous I/O. Write operations will complete once
all data and a minimum of metadata are flushed to disk.
.. note::
`UV_FS_O_DSYNC` is supported on Windows via
`FILE_FLAG_WRITE_THROUGH <https://docs.microsoft.com/en-us/windows/win32/fileio/file-buffering>`_.
.. c:macro:: UV_FS_O_EXCL
If the `O_CREAT` flag is set and the file already exists, fail the open.
.. note::
In general, the behavior of `O_EXCL` is undefined if it is used without
`O_CREAT`. There is one exception: on Linux 2.6 and later, `O_EXCL` can
be used without `O_CREAT` if pathname refers to a block device. If the
block device is in use by the system (e.g., mounted), the open will fail
with the error `EBUSY`.
.. c:macro:: UV_FS_O_EXLOCK
Atomically obtain an exclusive lock.
.. note::
`UV_FS_O_EXLOCK` is only supported on macOS and Windows.
.. versionchanged:: 1.17.0 support is added for Windows.
.. c:macro:: UV_FS_O_FILEMAP
Use a memory file mapping to access the file. When using this flag, the
file cannot be open multiple times concurrently.
.. note::
`UV_FS_O_FILEMAP` is only supported on Windows.
.. c:macro:: UV_FS_O_NOATIME
Do not update the file access time when the file is read.
.. note::
`UV_FS_O_NOATIME` is not supported on Windows.
.. c:macro:: UV_FS_O_NOCTTY
If the path identifies a terminal device, opening the path will not cause
that terminal to become the controlling terminal for the process (if the
process does not already have one).
.. note::
`UV_FS_O_NOCTTY` is not supported on Windows.
.. c:macro:: UV_FS_O_NOFOLLOW
If the path is a symbolic link, fail the open.
.. note::
`UV_FS_O_NOFOLLOW` is not supported on Windows.
.. c:macro:: UV_FS_O_NONBLOCK
Open the file in nonblocking mode if possible.
.. note::
`UV_FS_O_NONBLOCK` is not supported on Windows.
.. c:macro:: UV_FS_O_RANDOM
Access is intended to be random. The system can use this as a hint to
optimize file caching.
.. note::
`UV_FS_O_RANDOM` is only supported on Windows via
`FILE_FLAG_RANDOM_ACCESS <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea>`_.
.. c:macro:: UV_FS_O_RDONLY
Open the file for read-only access.
.. c:macro:: UV_FS_O_RDWR
Open the file for read-write access.
.. c:macro:: UV_FS_O_SEQUENTIAL
Access is intended to be sequential from beginning to end. The system can
use this as a hint to optimize file caching.
.. note::
`UV_FS_O_SEQUENTIAL` is only supported on Windows via
`FILE_FLAG_SEQUENTIAL_SCAN <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea>`_.
.. c:macro:: UV_FS_O_SHORT_LIVED
The file is temporary and should not be flushed to disk if possible.
.. note::
`UV_FS_O_SHORT_LIVED` is only supported on Windows via
`FILE_ATTRIBUTE_TEMPORARY <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea>`_.
.. c:macro:: UV_FS_O_SYMLINK
Open the symbolic link itself rather than the resource it points to.
.. c:macro:: UV_FS_O_SYNC
The file is opened for synchronous I/O. Write operations will complete once
all data and all metadata are flushed to disk.
.. note::
`UV_FS_O_SYNC` is supported on Windows via
`FILE_FLAG_WRITE_THROUGH <https://docs.microsoft.com/en-us/windows/win32/fileio/file-buffering>`_.
.. c:macro:: UV_FS_O_TEMPORARY
The file is temporary and should not be flushed to disk if possible.
.. note::
`UV_FS_O_TEMPORARY` is only supported on Windows via
`FILE_ATTRIBUTE_TEMPORARY <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea>`_.
.. c:macro:: UV_FS_O_TRUNC
If the file exists and is a regular file, and the file is opened
successfully for write access, its length shall be truncated to zero.
.. c:macro:: UV_FS_O_WRONLY
Open the file for write-only access.

@ -1,132 +0,0 @@
.. _fs_event:
:c:type:`uv_fs_event_t` --- FS Event handle
===========================================
FS Event handles allow the user to monitor a given path for changes, for example,
if the file was renamed or there was a generic change in it. This handle uses
the best backend for the job on each platform.
.. note::
For AIX, the non default IBM bos.ahafs package has to be installed.
The AIX Event Infrastructure file system (ahafs) has some limitations:
- ahafs tracks monitoring per process and is not thread safe. A separate process
must be spawned for each monitor for the same event.
- Events for file modification (writing to a file) are not received if only the
containing folder is watched.
See documentation_ for more details.
The z/OS file system events monitoring infrastructure does not notify of file
creation/deletion within a directory that is being monitored.
See the `IBM Knowledge centre`_ for more details.
.. _documentation: https://developer.ibm.com/articles/au-aix_event_infrastructure/
.. _`IBM Knowledge centre`: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.2.0/com.ibm.zos.v2r1.bpxb100/ioc.htm
Data types
----------
.. c:type:: uv_fs_event_t
FS Event handle type.
.. c:type:: void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status)
Callback passed to :c:func:`uv_fs_event_start` which will be called repeatedly
after the handle is started. If the handle was started with a directory the
`filename` parameter will be a relative path to a file contained in the directory.
The `events` parameter is an ORed mask of :c:type:`uv_fs_event` elements.
.. c:type:: uv_fs_event
Event types that :c:type:`uv_fs_event_t` handles monitor.
::
enum uv_fs_event {
UV_RENAME = 1,
UV_CHANGE = 2
};
.. c:type:: uv_fs_event_flags
Flags that can be passed to :c:func:`uv_fs_event_start` to control its
behavior.
::
enum uv_fs_event_flags {
/*
* By default, if the fs event watcher is given a directory name, we will
* watch for all events in that directory. This flags overrides this behavior
* and makes fs_event report only changes to the directory entry itself. This
* flag does not affect individual files watched.
* This flag is currently not implemented yet on any backend.
*/
UV_FS_EVENT_WATCH_ENTRY = 1,
/*
* By default uv_fs_event will try to use a kernel interface such as inotify
* or kqueue to detect events. This may not work on remote file systems such
* as NFS mounts. This flag makes fs_event fall back to calling stat() on a
* regular interval.
* This flag is currently not implemented yet on any backend.
*/
UV_FS_EVENT_STAT = 2,
/*
* By default, event watcher, when watching directory, is not registering
* (is ignoring) changes in its subdirectories.
* This flag will override this behaviour on platforms that support it.
*/
UV_FS_EVENT_RECURSIVE = 4
};
Public members
^^^^^^^^^^^^^^
N/A
.. seealso:: The :c:type:`uv_handle_t` members also apply.
API
---
.. c:function:: int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle)
Initialize the handle.
.. c:function:: int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags)
Start the handle with the given callback, which will watch the specified
`path` for changes. `flags` can be an ORed mask of :c:type:`uv_fs_event_flags`.
.. note:: Currently the only supported flag is ``UV_FS_EVENT_RECURSIVE`` and
only on OSX and Windows.
.. c:function:: int uv_fs_event_stop(uv_fs_event_t* handle)
Stop the handle, the callback will no longer be called.
.. c:function:: int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size)
Get the path being monitored by the handle. The buffer must be preallocated
by the user. Returns 0 on success or an error code < 0 in case of failure.
On success, `buffer` will contain the path and `size` its length. If the buffer
is not big enough `UV_ENOBUFS` will be returned and `size` will be set to
the required size, including the null terminator.
.. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
and the buffer is not null terminated.
.. versionchanged:: 1.9.0 the returned length includes the terminating null
byte on `UV_ENOBUFS`, and the buffer is null terminated
on success.
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.

@ -1,77 +0,0 @@
.. _fs_poll:
:c:type:`uv_fs_poll_t` --- FS Poll handle
=========================================
FS Poll handles allow the user to monitor a given path for changes. Unlike
:c:type:`uv_fs_event_t`, fs poll handles use `stat` to detect when a file has
changed so they can work on file systems where fs event handles can't.
Data types
----------
.. c:type:: uv_fs_poll_t
FS Poll handle type.
.. c:type:: void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, int status, const uv_stat_t* prev, const uv_stat_t* curr)
Callback passed to :c:func:`uv_fs_poll_start` which will be called repeatedly
after the handle is started, when any change happens to the monitored path.
The callback is invoked with `status < 0` if `path` does not exist
or is inaccessible. The watcher is *not* stopped but your callback is
not called again until something changes (e.g. when the file is created
or the error reason changes).
When `status == 0`, the callback receives pointers to the old and new
:c:type:`uv_stat_t` structs. They are valid for the duration of the
callback only.
Public members
^^^^^^^^^^^^^^
N/A
.. seealso:: The :c:type:`uv_handle_t` members also apply.
API
---
.. c:function:: int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle)
Initialize the handle.
.. c:function:: int uv_fs_poll_start(uv_fs_poll_t* handle, uv_fs_poll_cb poll_cb, const char* path, unsigned int interval)
Check the file at `path` for changes every `interval` milliseconds.
.. note::
For maximum portability, use multi-second intervals. Sub-second intervals will not detect
all changes on many file systems.
.. c:function:: int uv_fs_poll_stop(uv_fs_poll_t* handle)
Stop the handle, the callback will no longer be called.
.. c:function:: int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size)
Get the path being monitored by the handle. The buffer must be preallocated
by the user. Returns 0 on success or an error code < 0 in case of failure.
On success, `buffer` will contain the path and `size` its length. If the buffer
is not big enough `UV_ENOBUFS` will be returned and `size` will be set to
the required size.
.. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
and the buffer is not null terminated.
.. versionchanged:: 1.9.0 the returned length includes the terminating null
byte on `UV_ENOBUFS`, and the buffer is null terminated
on success.
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.

@ -1,22 +0,0 @@
.. _guide:
User guide
==========
.. warning::
The contents of this guide have been recently incorporated into the libuv documentation
and it hasn't gone through thorough review yet. If you spot a mistake please file an
issue, or better yet, open a pull request!
.. toctree::
:maxdepth: 2
guide/introduction
guide/basics
guide/filesystem
guide/networking
guide/threads
guide/processes
guide/eventloops
guide/utilities
guide/about

@ -1,22 +0,0 @@
About
=====
`Nikhil Marathe <https://nikhilism.com>`_ started writing this book one
afternoon (June 16, 2012) when he didn't feel like programming. He had recently
been stung by the lack of good documentation on libuv while working on
`node-taglib <https://github.com/nikhilm/node-taglib>`_. Although reference
documentation was present, there were no comprehensive tutorials. This book is
the output of that need and tries to be accurate. That said, the book may have
mistakes. Pull requests are encouraged.
Nikhil is indebted to Marc Lehmann's comprehensive `man page
<http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod>`_ about libev which
describes much of the semantics of the two libraries.
This book was made using `Sphinx <https://www.sphinx-doc.org>`_ and `vim
<https://www.vim.org>`_.
.. note::
In 2017 the libuv project incorporated the Nikhil's work into the official
documentation and it's maintained there henceforth.

@ -1,221 +0,0 @@
Basics of libuv
===============
libuv enforces an **asynchronous**, **event-driven** style of programming. Its
core job is to provide an event loop and callback based notifications of I/O
and other activities. libuv offers core utilities like timers, non-blocking
networking support, asynchronous file system access, child processes and more.
Event loops
-----------
In event-driven programming, an application expresses interest in certain events
and respond to them when they occur. The responsibility of gathering events
from the operating system or monitoring other sources of events is handled by
libuv, and the user can register callbacks to be invoked when an event occurs.
The event-loop usually keeps running *forever*. In pseudocode:
.. code-block:: python
while there are still events to process:
e = get the next event
if there is a callback associated with e:
call the callback
Some examples of events are:
* File is ready for writing
* A socket has data ready to be read
* A timer has timed out
This event loop is encapsulated by ``uv_run()`` -- the end-all function when using
libuv.
The most common activity of systems programs is to deal with input and output,
rather than a lot of number-crunching. The problem with using conventional
input/output functions (``read``, ``fprintf``, etc.) is that they are
**blocking**. The actual write to a hard disk or reading from a network, takes
a disproportionately long time compared to the speed of the processor. The
functions don't return until the task is done, so that your program is doing
nothing. For programs which require high performance this is a major roadblock
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 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,
non-blocking** style. Most modern operating systems provide event notification
subsystems. For example, a normal ``read`` call on a socket would block until
the sender actually sent something. Instead, the application can request the
operating system to watch the socket and put an event notification in the
queue. The application can inspect the events at its convenience (perhaps doing
some number crunching before to use the processor to the maximum) and grab the
data. It is **asynchronous** because the application expressed interest at one
point, then used the data at another point (in time and space). It is
**non-blocking** because the application process was free to do other tasks.
This fits in well with libuv's event-loop approach, since the operating system
events can be treated as just another libuv event. The non-blocking ensures
that other events can continue to be handled as fast as they come in [#]_.
.. NOTE::
How the I/O is run in the background is not of our concern, but due to the
way our computer hardware works, with the thread as the basic unit of the
processor, libuv and OSes will usually run background/worker threads and/or
polling to perform tasks in a non-blocking manner.
Bert Belder, one of the libuv core developers has a small video explaining the
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>`_.
.. raw:: html
<iframe width="560" height="315"
src="https://www.youtube-nocookie.com/embed/nGn60vDSxQ4" frameborder="0"
allowfullscreen></iframe>
Hello World
-----------
With the basics out of the way, let's write our first libuv program. It does
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
event loop has to be told to watch out for events using the various API
functions.
Starting with libuv v1.0, users should allocate the memory for the loops before
initializing it with ``uv_loop_init(uv_loop_t *)``. This allows you to plug in
custom memory management. Remember to de-initialize the loop using
``uv_loop_close(uv_loop_t *)`` and then delete the storage. The examples never
close loops since the program quits after the loop ends and the system will
reclaim memory. Production grade projects, especially long running systems
programs, should take care to release correctly.
Default loop
++++++++++++
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.
.. note::
node.js uses the default loop as its main loop. If you are writing bindings
you should be aware of this.
.. _libuv-error-handling:
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`_.
.. _constants: http://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.
I/O read callbacks (such as for files and sockets) are passed a parameter ``nread``. If ``nread`` is less than 0, there was an error (UV_EOF is the end of file error, which you may want to handle differently).
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.
.. rubric:: libuv watchers
.. code-block:: c
/* Handle types. */
typedef struct uv_loop_s uv_loop_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_dir_s uv_dir_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t;
typedef struct uv_pipe_s uv_pipe_t;
typedef struct uv_tty_s uv_tty_t;
typedef struct uv_poll_s uv_poll_t;
typedef struct uv_timer_s uv_timer_t;
typedef struct uv_prepare_s uv_prepare_t;
typedef struct uv_check_s uv_check_t;
typedef struct uv_idle_s uv_idle_t;
typedef struct uv_async_s uv_async_t;
typedef struct uv_process_s uv_process_t;
typedef struct uv_fs_event_s uv_fs_event_t;
typedef struct uv_fs_poll_s uv_fs_poll_t;
typedef struct uv_signal_s uv_signal_t;
/* Request types. */
typedef struct uv_req_s uv_req_t;
typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
typedef struct uv_getnameinfo_s uv_getnameinfo_t;
typedef struct uv_shutdown_s uv_shutdown_t;
typedef struct uv_write_s uv_write_t;
typedef struct uv_connect_s uv_connect_t;
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;
Handles represent long-lived objects. Async operations on such handles are
identified using **requests**. A request is short-lived (usually used across
only one callback) and usually indicates one I/O operation on a handle.
Requests are used to preserve context between the initiation and the callback
of individual actions. For example, an UDP socket is represented by
a ``uv_udp_t``, while individual writes to the socket use a ``uv_udp_send_t``
structure that is passed to the callback after the write is done.
Handles are setup by a corresponding::
uv_TYPE_init(uv_loop_t *, uv_TYPE_t *)
function.
Callbacks are functions which are called by libuv whenever an event the watcher
is interested in has taken place. Application specific logic will usually be
implemented in the callback. For example, an IO watcher's callback will receive
the data read from a file, a timer callback will be triggered on timeout and so
on.
Idling
++++++
Here is an example of using an idle handle. The callback is called once on
every turn of the event loop. A use case for idle handles is discussed in
:doc:`utilities`. Let us use an idle watcher to look at the watcher life cycle
and see how ``uv_run()`` will now block because a watcher is present. The idle
watcher is stopped when the count is reached and ``uv_run()`` exits since no
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
+++++++++++++++
In callback based programming style you'll often want to pass some 'context' --
application specific information -- between the call site and the callback. All
handles and requests have a ``void* data`` member which you can set to the
context and cast back in the callback. This is a common pattern used throughout
the C library ecosystem. In addition ``uv_loop_t`` also has a similar data
member.
----
.. [#] Depending on the capacity of the hardware of course.

@ -1,50 +0,0 @@
Advanced event loops
====================
libuv provides considerable user control over event loops, and you can achieve
interesting results by juggling multiple loops. You can also embed libuv's
event loop into another event loop based library -- imagine a Qt based UI, and
Qt's event loop driving a libuv backend which does intensive system level
tasks.
Stopping an event loop
~~~~~~~~~~~~~~~~~~~~~~
``uv_stop()`` can be used to stop an event loop. The earliest the loop will
stop running is *on the next iteration*, possibly later. This means that events
that are ready to be processed in this iteration of the loop will still be
processed, so ``uv_stop()`` can't be used as a kill switch. When ``uv_stop()``
is called, the loop **won't** block for i/o on this iteration. The semantics of
these things can be a bit difficult to understand, so let's look at
``uv_run()`` where all the control flow occurs.
.. rubric:: src/unix/core.c - uv_run
.. literalinclude:: ../../../src/unix/core.c
:language: c
:linenos:
:lines: 304-324
:emphasize-lines: 10,19,21
``stop_flag`` is set by ``uv_stop()``. Now all libuv callbacks are invoked
within the event loop, which is why invoking ``uv_stop()`` in them will still
lead to this iteration of the loop occurring. First libuv updates timers, then
runs pending timer, idle and prepare callbacks, and invokes any pending I/O
callbacks. If you were to call ``uv_stop()`` in any of them, ``stop_flag``
would be set. This causes ``uv_backend_timeout()`` to return ``0``, which is
why the loop does not block on I/O. If on the other hand, you called
``uv_stop()`` in one of the check handlers, I/O has already finished and is not
affected.
``uv_stop()`` is useful to shutdown a loop when a result has been computed or
there is an error, without having to ensure that all handlers are stopped one
by one.
Here is a simple example that stops the loop and demonstrates how the current
iteration of the loop still takes places.
.. rubric:: uvstop/main.c
.. literalinclude:: ../../code/uvstop/main.c
:language: c
:linenos:
:emphasize-lines: 11

@ -1,339 +0,0 @@
Filesystem
==========
Simple filesystem read/write is achieved using the ``uv_fs_*`` functions and the
``uv_fs_t`` struct.
.. note::
The libuv filesystem operations are different from :doc:`socket operations
<networking>`. Socket operations use the non-blocking operations provided
by the operating system. Filesystem operations use blocking functions
internally, but invoke these functions in a `thread pool`_ and notify
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
All filesystem functions have two forms - *synchronous* and *asynchronous*.
The *synchronous* forms automatically get called (and **block**) if the
callback is null. The return value of functions is a :ref:`libuv error code
<libuv-error-handling>`. This is usually only useful for synchronous calls.
The *asynchronous* form is called when a callback is passed and the return
value is 0.
Reading/Writing files
---------------------
A file descriptor is obtained using
.. code-block:: c
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 <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
.. code-block:: c
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
Filesystem operation callbacks have the signature:
.. code-block:: c
void callback(uv_fs_t* req);
Let's see a simple implementation of ``cat``. We start with registering
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
The ``result`` field of a ``uv_fs_t`` is the file descriptor in case of the
``uv_fs_open`` callback. If the file is successfully opened, we start reading it.
.. rubric:: uvcat/main.c - read callback
.. literalinclude:: ../../code/uvcat/main.c
:language: c
:linenos:
:lines: 26-40
:emphasize-lines: 2,8,12
In the case of a read call, you should pass an *initialized* buffer which will
be filled with data before the read callback is triggered. The ``uv_fs_*``
operations map almost directly to certain POSIX functions, so EOF is indicated
in this case by ``result`` being 0. In the case of streams or pipes, the
``UV_EOF`` constant would have been passed as a status instead.
Here you see a common pattern when writing asynchronous programs. The
``uv_fs_close()`` call is performed synchronously. *Usually tasks which are
one-off, or are done as part of the startup or shutdown stage are performed
synchronously, since we are interested in fast I/O when the program is going
about its primary task and dealing with multiple I/O sources*. For solo tasks
the performance difference usually is negligible and may lead to simpler code.
Filesystem writing is similarly simple using ``uv_fs_write()``. *Your callback
will be triggered after the write is complete*. In our case the callback
simply drives the next read. Thus read and write proceed in lockstep via
callbacks.
.. rubric:: uvcat/main.c - write callback
.. literalinclude:: ../../code/uvcat/main.c
:language: c
:linenos:
:lines: 16-24
:emphasize-lines: 6
.. warning::
Due to the way filesystems and disk drives are configured for performance,
a write that 'succeeds' may not be committed to disk yet.
We set the dominos rolling in ``main()``:
.. rubric:: uvcat/main.c
.. literalinclude:: ../../code/uvcat/main.c
:language: c
:linenos:
:lines: 55-
:emphasize-lines: 2
.. warning::
The ``uv_fs_req_cleanup()`` function must always be called on filesystem
requests to free internal memory allocations in libuv.
Filesystem operations
---------------------
All the standard filesystem operations like ``unlink``, ``rmdir``, ``stat`` are
supported asynchronously and have intuitive argument order. They follow the
same patterns as the read/write/open calls, returning the result in the
``uv_fs_t.result`` field. The full list:
.. rubric:: Filesystem operations
.. code-block:: c
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb);
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
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_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);
int uv_fs_opendir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb);
int uv_fs_closedir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb);
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb);
int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb);
int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
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_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);
int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb);
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);
.. _buffers-and-streams:
Buffers and Streams
-------------------
The basic I/O handle in libuv is the stream (``uv_stream_t``). TCP sockets, UDP
sockets, and pipes for file I/O and IPC are all treated as stream subclasses.
Streams are initialized using custom functions for each subclass, then operated
upon using
.. code-block:: c
int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);
int uv_read_stop(uv_stream_t*);
int uv_write(uv_write_t* req, uv_stream_t* handle,
const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
The stream based functions are simpler to use than the filesystem ones and
libuv will automatically keep reading from a stream when ``uv_read_start()`` is
called once, until ``uv_read_stop()`` is called.
The discrete unit of data is the buffer -- ``uv_buf_t``. This is simply
a collection of a pointer to bytes (``uv_buf_t.base``) and the length
(``uv_buf_t.len``). The ``uv_buf_t`` is lightweight and passed around by value.
What does require management is the actual bytes, which have to be allocated
and freed by the application.
.. ERROR::
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
asynchronously shows the power of evented I/O. The two writes won't block each
other, but we have to be careful to copy over the buffer data to ensure we don't
free a buffer until it has been written.
The program is to be executed as::
./uvtee <output_file>
We start off opening pipes on the files we require. libuv pipes to a file are
opened as bidirectional by default.
.. rubric:: uvtee/main.c - read on pipes
.. literalinclude:: ../../code/uvtee/main.c
:language: c
:linenos:
:lines: 61-80
:emphasize-lines: 4,5,15
The third argument of ``uv_pipe_init()`` should be set to 1 for IPC using named
pipes. This is covered in :doc:`processes`. The ``uv_pipe_open()`` call
associates the pipe with the file descriptor, in this case ``0`` (standard
input).
We start monitoring ``stdin``. The ``alloc_buffer`` callback is invoked as new
buffers are required to hold incoming data. ``read_stdin`` will be called with
these buffers.
.. rubric:: uvtee/main.c - reading buffers
.. literalinclude:: ../../code/uvtee/main.c
:language: c
:linenos:
:lines: 19-22,44-60
The standard ``malloc`` is sufficient here, but you can use any memory allocation
scheme. For example, node.js uses its own slab allocator which associates
buffers with V8 objects.
The read callback ``nread`` parameter is less than 0 on any error. This error
might be EOF, in which case we close all the streams, using the generic close
function ``uv_close()`` which deals with the handle based on its internal type.
Otherwise ``nread`` is a non-negative number and we can attempt to write that
many bytes to the output streams. Finally remember that buffer allocation and
deallocation is application responsibility, so we free the data.
The allocation callback may return a buffer with length zero if it fails to
allocate memory. In this case, the read callback is invoked with error
UV_ENOBUFS. libuv will continue to attempt to read the stream though, so you
must explicitly call ``uv_close()`` if you want to stop when allocation fails.
The read callback may be called with ``nread = 0``, indicating that at this
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
``write_data()`` makes a copy of the buffer obtained from read. This buffer
does not get passed through to the write callback trigged on write completion. To
get around this we wrap a write request and a buffer in ``write_req_t`` and
unwrap it in the callbacks. We make a copy so we can free the two buffers from
the two calls to ``write_data`` independently of each other. While acceptable
for a demo program like this, you'll probably want smarter memory management,
like reference counted buffers or a pool of buffers in any major application.
.. WARNING::
If your program is meant to be used with other programs it may knowingly or
unknowingly be writing to a pipe. This makes it susceptible to `aborting on
receiving a SIGPIPE`_. It is a good idea to insert::
signal(SIGPIPE, SIG_IGN)
in the initialization stages of your application.
.. _aborting on receiving a SIGPIPE: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_special_problem_of_SIGPIPE
File change events
------------------
All modern operating systems provide APIs to put watches on individual files or
directories and be informed when the files are modified. libuv wraps common
file change notification libraries [#fsnotify]_. This is one of the more
inconsistent parts of libuv. File change notification systems are themselves
extremely varied across platforms so getting everything working everywhere is
difficult. To demonstrate, I'm going to build a simple utility which runs
a command whenever any of the watched files change::
./onchange <command> <file1> [file2] ...
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
The third argument is the actual file or directory to monitor. The last
argument, ``flags``, can be:
.. code-block:: c
/*
* 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,
UV_FS_EVENT_RECURSIVE = 4
};
``UV_FS_EVENT_WATCH_ENTRY`` and ``UV_FS_EVENT_STAT`` don't do anything (yet).
``UV_FS_EVENT_RECURSIVE`` will start watching subdirectories as well on
supported platforms.
The callback will receive the following arguments:
#. ``uv_fs_event_t *handle`` - The handle. The ``path`` field of the handle
is the file on which the watch was set.
#. ``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.
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
----
.. [#fsnotify] inotify on Linux, FSEvents on Darwin, kqueue on BSDs,
ReadDirectoryChangesW on Windows, event ports on Solaris, unsupported on Cygwin
.. [#] see :ref:`pipes`

@ -1,75 +0,0 @@
Introduction
============
This 'book' is a small set of tutorials about using libuv_ as
a high performance evented I/O library which offers the same API on Windows and Unix.
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/
This book is still a work in progress, so sections may be incomplete, but
I hope you will enjoy it as it grows.
Who this book is for
--------------------
If you are reading this book, you are either:
1) a systems programmer, creating low-level programs such as daemons or network
services and clients. You have found that the event loop approach is well
suited for your application and decided to use libuv.
2) a node.js module writer, who wants to wrap platform APIs
written in C or C++ with a set of (a)synchronous APIs that are exposed to
JavaScript. You will use libuv purely in the context of node.js. For
this you will require some other resources as the book does not cover parts
specific to v8/node.js.
This book assumes that you are comfortable with the C programming language.
Background
----------
The node.js_ project began in 2009 as a JavaScript environment decoupled
from the browser. Using Google's V8_ and Marc Lehmann's libev_, node.js
combined a model of I/O -- evented -- with a language that was well suited to
the style of programming; due to the way it had been shaped by browsers. As
node.js grew in popularity, it was important to make it work on Windows, but
libev ran only on Unix. The Windows equivalent of kernel event notification
mechanisms like kqueue or (e)poll is IOCP. libuv was an abstraction around libev
or IOCP depending on the platform, providing users an API based on libev.
In the node-v0.9.0 version of libuv `libev was removed`_.
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`_.
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::
cd libuv
./autogen.sh
./configure
make
There is no need to ``make install``. To build the examples run ``make`` in the
``code/`` directory.
.. _Clone: https://github.com/nikhilm/uvbook
.. _Download: https://github.com/nikhilm/uvbook/downloads
.. _v1.3.0: https://github.com/libuv/libuv/tags
.. _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/blob/v1.x/LINKS.md

@ -1,257 +0,0 @@
Networking
==========
Networking in libuv is not much different from directly using the BSD socket
interface, some things are easier, all are non-blocking, but the concepts stay
the same. In addition libuv offers utility functions to abstract the annoying,
repetitive and low-level tasks like setting up sockets using the BSD socket
structures, DNS lookup, and tweaking various socket parameters.
The ``uv_tcp_t`` and ``uv_udp_t`` structures are used for network I/O.
.. NOTE::
The code samples in this chapter exist to show certain libuv APIs. They are
not examples of good quality code. They leak memory and don't always close
connections properly.
TCP
---
TCP is a connection oriented, stream protocol and is therefore based on the
libuv streams infrastructure.
Server
++++++
Server sockets proceed by:
1. ``uv_tcp_init`` the TCP handle.
2. ``uv_tcp_bind`` it.
3. Call ``uv_listen`` on the handle to have a callback invoked whenever a new
connection is established by a client.
4. Use ``uv_accept`` to accept the connection.
5. Use :ref:`stream operations <buffers-and-streams>` to communicate with the
client.
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
You can see the utility function ``uv_ip4_addr`` being used to convert from
a human readable IP address, port pair to the sockaddr_in structure required by
the BSD socket APIs. The reverse can be obtained using ``uv_ip4_name``.
.. NOTE::
There are ``uv_ip6_*`` analogues for the ip4 functions.
Most of the setup functions are synchronous since they are CPU-bound.
``uv_listen`` is where we return to libuv's callback style. The second
arguments is the backlog queue -- the maximum length of queued connections.
When a connection is initiated by clients, the callback is required to set up
a handle for the client socket and associate the handle using ``uv_accept``.
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
The remaining set of functions is very similar to the streams example and can
be found in the code. Just remember to call ``uv_close`` when the socket isn't
required. This can be done even in the ``uv_listen`` callback if you are not
interested in accepting the connection.
Client
++++++
Where you do bind/listen/accept on the server, on the client side it's simply
a matter of calling ``uv_tcp_connect``. The same ``uv_connect_cb`` style
callback of ``uv_listen`` is used by ``uv_tcp_connect``. Try::
uv_tcp_t* socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
uv_tcp_init(loop, socket);
uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
struct sockaddr_in dest;
uv_ip4_addr("127.0.0.1", 80, &dest);
uv_tcp_connect(connect, socket, (const struct sockaddr*)&dest, on_connect);
where ``on_connect`` will be called after the connection is established. The
callback receives the ``uv_connect_t`` struct, which has a member ``.handle``
pointing to the socket.
UDP
---
The `User Datagram Protocol`_ offers connectionless, unreliable network
communication. Hence libuv doesn't offer a stream. Instead libuv provides
non-blocking UDP support via the `uv_udp_t` handle (for receiving) and
`uv_udp_send_t` request (for sending) and related functions. That said, the
actual API for reading/writing is very similar to normal stream reads. To look
at how UDP can be used, the example shows the first stage of obtaining an IP
address from a `DHCP`_ server -- DHCP Discover.
.. note::
You will have to run `udp-dhcp` as **root** since it uses well known port
numbers below 1024.
.. 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
.. note::
The IP address ``0.0.0.0`` is used to bind to all interfaces. The IP
address ``255.255.255.255`` is a broadcast address meaning that packets
will be sent to all interfaces on the subnet. port ``0`` means that the OS
randomly assigns a port.
First we setup the receiving socket to bind on all interfaces on port 68 (DHCP
client) and start a read on it. This will read back responses from any DHCP
server that replies. We use the UV_UDP_REUSEADDR flag to play nice with any
other system DHCP clients that are running on this computer on the same port.
Then we setup a similar send socket and use ``uv_udp_send`` to send
a *broadcast message* on port 67 (DHCP server).
It is **necessary** to set the broadcast flag, otherwise you will get an
``EACCES`` error [#]_. The exact message being sent is not relevant to this
book and you can study the code if you are interested. As usual the read and
write callbacks will receive a status code of < 0 if something went wrong.
Since UDP sockets are not connected to a particular peer, the read callback
receives an extra parameter about the sender of the packet.
``nread`` may be zero if there is no more data to be read. If ``addr`` is NULL,
it indicates there is nothing to read (the callback shouldn't do anything), if
not NULL, it indicates that an empty datagram was received from the host at
``addr``. The ``flags`` parameter may be ``UV_UDP_PARTIAL`` if the buffer
provided by your allocator was not large enough to hold the data. *In this case
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
UDP Options
+++++++++++
Time-to-live
~~~~~~~~~~~~
The TTL of packets sent on the socket can be changed using ``uv_udp_set_ttl``.
IPv6 stack only
~~~~~~~~~~~~~~~
IPv6 sockets can be used for both IPv4 and IPv6 communication. If you want to
restrict the socket to IPv6 only, pass the ``UV_UDP_IPV6ONLY`` flag to
``uv_udp_bind`` [#]_.
Multicast
~~~~~~~~~
A socket can (un)subscribe to a multicast group using:
.. code::block:: c
int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, uv_membership membership);
where ``membership`` is ``UV_JOIN_GROUP`` or ``UV_LEAVE_GROUP``.
The concepts of multicasting are nicely explained in `this guide`_.
.. _this guide: https://www.tldp.org/HOWTO/Multicast-HOWTO-2.html
Local loopback of multicast packets is enabled by default [#]_, use
``uv_udp_set_multicast_loop`` to switch it off.
The packet time-to-live for multicast packets can be changed using
``uv_udp_set_multicast_ttl``.
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
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
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
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
addrinfo(s)``. This also demonstrates ``uv_tcp_connect``. It is necessary to
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
libuv also provides the inverse `uv_getnameinfo`_.
.. _uv_getnameinfo: http://docs.libuv.org/en/v1.x/dns.html#c.uv_getnameinfo
Network interfaces
------------------
Information about the system's network interfaces can be obtained through libuv
using ``uv_interface_addresses``. This simple program just prints out all the
interface details so you get an idea of the fields that are available. This is
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
``is_internal`` is true for loopback interfaces. Note that if a physical
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://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
----
.. [#] https://beej.us/guide/bgnet/html/#broadcast-packetshello-world
.. [#] on Windows only supported on Windows Vista and later.
.. [#] https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html#ss6.1
.. [#] libuv use the system ``getaddrinfo`` in the libuv threadpool. libuv
v0.8.0 and earlier also included c-ares_ as an alternative, but this has been
removed in v0.9.0.

@ -1,421 +0,0 @@
Processes
=========
libuv offers considerable child process management, abstracting the platform
differences and allowing communication with the child process using streams or
named pipes.
A common idiom in Unix is for every process to do one thing and do it well. In
such a case, a process often uses multiple child processes to achieve tasks
(similar to using pipes in shells). A multi-process model with messages
may also be easier to reason about compared to one with threads and shared
memory.
A common refrain against event-based programs is that they cannot take
advantage of multiple cores in modern computers. In a multi-threaded program
the kernel can perform scheduling and assign different threads to different
cores, improving performance. But an event loop has only one thread. The
workaround can be to launch multiple processes instead, with each process
running an event loop, and each process getting assigned to a separate CPU
core.
Spawning child processes
------------------------
The simplest case is when you simply want to launch a process and know when it
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
.. NOTE::
``options`` is implicitly initialized with zeros since it is a global
variable. If you change ``options`` to a local variable, remember to
initialize it to null out all unused fields::
uv_process_options_t options = {0};
The ``uv_process_t`` struct only acts as the handle, all options are set via
``uv_process_options_t``. To simply launch a process, you need to set only the
``file`` and ``args`` fields. ``file`` is the program to execute. Since
``uv_spawn`` uses :man:`execvp(3)` internally, there is no need to supply the full
path. Finally as per underlying conventions, **the arguments array has to be
one larger than the number of arguments, with the last element being NULL**.
After the call to ``uv_spawn``, ``uv_process_t.pid`` will contain the process
ID of the child process.
The exit callback will be invoked with the *exit status* and the type of *signal*
which caused the exit.
.. rubric:: spawn/main.c
.. literalinclude:: ../../code/spawn/main.c
:language: c
:linenos:
:lines: 9-12
:emphasize-lines: 3
It is **required** to close the process watcher after the process exits.
Changing process parameters
---------------------------
Before the child process is launched you can control the execution environment
using fields in ``uv_process_options_t``.
Change execution directory
++++++++++++++++++++++++++
Set ``uv_process_options_t.cwd`` to the corresponding directory.
Set environment variables
+++++++++++++++++++++++++
``uv_process_options_t.env`` is a null-terminated array of strings, each of the
form ``VAR=VALUE`` used to set up the environment variables for the process. Set
this to ``NULL`` to inherit the environment from the parent (this) process.
Option flags
++++++++++++
Setting ``uv_process_options_t.flags`` to a bitwise OR of the following flags,
modifies the child process behaviour:
* ``UV_PROCESS_SETUID`` - sets the child's execution user ID to ``uv_process_options_t.uid``.
* ``UV_PROCESS_SETGID`` - sets the child's execution group ID to ``uv_process_options_t.gid``.
Changing the UID/GID is only supported on Unix, ``uv_spawn`` will fail on
Windows with ``UV_ENOTSUP``.
* ``UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS`` - No quoting or escaping of
``uv_process_options_t.args`` is done on Windows. Ignored on Unix.
* ``UV_PROCESS_DETACHED`` - Starts the child process in a new session, which
will keep running after the parent process exits. See example below.
Detaching processes
-------------------
Passing the flag ``UV_PROCESS_DETACHED`` can be used to launch daemons, or
child processes which are independent of the parent so that the parent exiting
does not affect it.
.. rubric:: detach/main.c
.. literalinclude:: ../../code/detach/main.c
:language: c
:linenos:
:lines: 9-30
:emphasize-lines: 12,19
Just remember that the handle is still monitoring the child, so your program
won't exit. Use ``uv_unref()`` if you want to be more *fire-and-forget*.
Sending signals to processes
----------------------------
libuv wraps the standard ``kill(2)`` system call on Unix and implements one
with similar semantics on Windows, with *one caveat*: all of ``SIGTERM``,
``SIGINT`` and ``SIGKILL``, lead to termination of the process. The signature
of ``uv_kill`` is::
uv_err_t uv_kill(int pid, int signum);
For processes started using libuv, you may use ``uv_process_kill`` instead,
which accepts the ``uv_process_t`` watcher as the first argument, rather than
the pid. In this case, **remember to call** ``uv_close`` on the watcher.
Signals
-------
libuv provides wrappers around Unix signals with `some Windows support
<http://docs.libuv.org/en/v1.x/signal.html#signal>`_ as well.
Use ``uv_signal_init()`` to initialize
a handle and associate it with a loop. To listen for particular signals on
that handler, use ``uv_signal_start()`` with the handler function. Each handler
can only be associated with one signal number, with subsequent calls to
``uv_signal_start()`` overwriting earlier associations. Use ``uv_signal_stop()`` to
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
.. NOTE::
``uv_run(loop, UV_RUN_NOWAIT)`` is similar to ``uv_run(loop, UV_RUN_ONCE)``
in that it will process only one event. UV_RUN_ONCE blocks if there are no
pending events, while UV_RUN_NOWAIT will return immediately. We use NOWAIT
so that one of the loops isn't starved because the other one has no pending
activity.
Send ``SIGUSR1`` to the process, and you'll find the handler being invoked
4 times, one for each ``uv_signal_t``. The handler just stops each handle,
so that the program exits. This sort of dispatch to all handlers is very
useful. A server using multiple event loops could ensure that all data was
safely saved before termination, simply by every loop adding a watcher for
``SIGINT``.
Child Process I/O
-----------------
A normal, newly spawned process has its own set of file descriptors, with 0,
1 and 2 being ``stdin``, ``stdout`` and ``stderr`` respectively. Sometimes you
may want to share file descriptors with the child. For example, perhaps your
applications launches a sub-command and you want any errors to go in the log
file, but ignore ``stdout``. For this you'd like to have ``stderr`` of the
child be the same as the stderr of the parent. In this case, libuv supports
*inheriting* file descriptors. In this sample, we invoke the test program,
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
``uv_process_options_t``. First set the ``stdio_count`` field to the number of
file descriptors being set. ``uv_process_options_t.stdio`` is an array of
``uv_stdio_container_t``, which is:
.. code-block:: c
typedef struct uv_stdio_container_s {
uv_stdio_flags flags;
union {
uv_stream_t* stream;
int fd;
} data;
} uv_stdio_container_t;
where flags can have several values. Use ``UV_IGNORE`` if it isn't going to be
used. If the first three ``stdio`` fields are marked as ``UV_IGNORE`` they'll
redirect to ``/dev/null``.
Since we want to pass on an existing descriptor, we'll use ``UV_INHERIT_FD``.
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
If you run ``proc-stream`` you'll see that only the line "This is stderr" will
be displayed. Try marking ``stdout`` as being inherited and see the output.
It is dead simple to apply this redirection to streams. By setting ``flags``
to ``UV_INHERIT_STREAM`` and setting ``data.stream`` to the stream in the
parent process, the child process can treat that stream as standard I/O. This
can be used to implement something like CGI_.
.. _CGI: https://en.wikipedia.org/wiki/Common_Gateway_Interface
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
Here we simply accept the TCP connection and pass on the socket (*stream*) to
``invoke_cgi_script``.
.. rubric:: cgi/main.c
.. literalinclude:: ../../code/cgi/main.c
:language: c
:linenos:
:lines: 16, 25-45
:emphasize-lines: 8-9,18,20
The ``stdout`` of the CGI script is set to the socket so that whatever our tick
script prints, gets sent to the client. By using processes, we can offload the
read/write buffering to the operating system, so in terms of convenience this
is great. Just be warned that creating processes is a costly task.
.. _pipes:
Parent-child IPC
----------------
A parent and child can have one or two way communication over a pipe created by
settings ``uv_stdio_container_t.flags`` to a bit-wise combination of
``UV_CREATE_PIPE`` and ``UV_READABLE_PIPE`` or ``UV_WRITABLE_PIPE``. The
read/write flag is from the perspective of the child process. In this case,
the ``uv_stream_t* stream`` field must be set to point to an initialized,
unopened ``uv_pipe_t`` instance.
New stdio Pipes
+++++++++++++++
The ``uv_pipe_t`` structure represents more than just `pipe(7)`_ (or ``|``),
but supports any streaming file-like objects. On Windows, the only object of
that description is the `Named Pipe`_. On Unix, this could be any of `Unix
Domain Socket`_, or derived from `mkfifo(1)`_, or it could actually be a
`pipe(7)`_. When ``uv_spawn`` initializes a ``uv_pipe_t`` due to the
`UV_CREATE_PIPE` flag, it opts for creating a `socketpair(2)`_.
This is intended for the purpose of allowing multiple libuv processes to
communicate with IPC. This is discussed below.
.. _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
Arbitrary process IPC
+++++++++++++++++++++
Since domain sockets [#]_ can have a well known name and a location in the
file-system they can be used for IPC between unrelated processes. The D-BUS_
system used by open source desktop environments uses domain sockets for event
notification. Various applications can then react when a contact comes online
or new hardware is detected. The MySQL server also runs a domain socket on
which clients can interact with it.
.. _D-BUS: https://www.freedesktop.org/wiki/Software/dbus
When using domain sockets, a client-server pattern is usually followed with the
creator/owner of the socket acting as the server. After the initial setup,
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
We name the socket ``echo.sock`` which means it will be created in the local
directory. This socket now behaves no different from TCP sockets as far as
the stream API is concerned. You can test this server using `socat`_::
$ socat - /path/to/socket
A client which wants to connect to a domain socket will use::
void uv_pipe_connect(uv_connect_t *req, uv_pipe_t *handle, const char *name, uv_connect_cb cb);
where ``name`` will be ``echo.sock`` or similar. On Unix systems, ``name`` must
point to a valid file (e.g. ``/tmp/echo.sock``). On Windows, ``name`` follows a
``\\?\pipe\echo.sock`` format.
.. _socat: http://www.dest-unreach.org/socat/
Sending file descriptors over pipes
+++++++++++++++++++++++++++++++++++
The cool thing about domain sockets is that file descriptors can be exchanged
between processes by sending them over a domain socket. This allows processes
to hand off their I/O to other processes. Applications include load-balancing
servers, worker processes and other ways to make optimum use of CPU. libuv only
supports sending **TCP sockets or other pipes** over pipes for now.
To demonstrate, we will look at a echo server implementation that hands of
clients to worker processes in a round-robin fashion. This program is a bit
involved, and while only snippets are included in the book, it is recommended
to read the full code to really understand it.
The worker process is quite simple, since the file-descriptor is handed over to
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
``queue`` is the pipe connected to the master process on the other end, along
which new file descriptors get sent. It is important to set the ``ipc``
argument of ``uv_pipe_init`` to 1 to indicate this pipe will be used for
inter-process communication! Since the master will write the file handle to the
standard input of the worker, we connect the pipe to ``stdin`` using
``uv_pipe_open``.
.. rubric:: multi-echo-server/worker.c
.. literalinclude:: ../../code/multi-echo-server/worker.c
:language: c
:linenos:
:lines: 51-79
:emphasize-lines: 10,15,20
First we call ``uv_pipe_pending_count()`` to ensure that a handle is available
to read out. If your program could deal with different types of handles,
``uv_pipe_pending_type()`` can be used to determine the type.
Although ``accept`` seems odd in this code, it actually makes sense. What
``accept`` traditionally does is get a file descriptor (the client) from
another file descriptor (The listening socket). Which is exactly what we do
here. Fetch the file descriptor (``client``) from ``queue``. From this point
the worker does standard echo server stuff.
Turning now to the master, let's take a look at how the workers are launched to
allow load balancing.
.. rubric:: multi-echo-server/main.c
.. literalinclude:: ../../code/multi-echo-server/main.c
:language: c
:linenos:
:lines: 9-13
The ``child_worker`` structure wraps the process, and the pipe between the
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
In setting up the workers, we use the nifty libuv function ``uv_cpu_info`` to
get the number of CPUs so we can launch an equal number of workers. Again it is
important to initialize the pipe acting as the IPC channel with the third
argument as 1. We then indicate that the child process' ``stdin`` is to be
a readable pipe (from the point of view of the child). Everything is
straightforward till here. The workers are launched and waiting for file
descriptors to be written to their standard input.
It is in ``on_new_connection`` (the TCP infrastructure is initialized in
``main()``), that we accept the client socket and pass it along to the next
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
The ``uv_write2`` call handles all the abstraction and it is simply a matter of
passing in the handle (``client``) as the right argument. With this our
multi-process echo server is operational.
Thanks to Kyle for `pointing out`_ that ``uv_write2()`` requires a non-empty
buffer even when sending handles.
.. _pointing out: https://github.com/nikhilm/uvbook/issues/56
----
.. [#] In this section domain sockets stands in for named pipes on Windows as
well.

@ -1,397 +0,0 @@
Threads
=======
Wait a minute? Why are we on threads? Aren't event loops supposed to be **the
way** to do *web-scale programming*? Well... no. Threads are still the medium in
which processors do their jobs. Threads are therefore mighty useful sometimes, even
though you might have to wade through various synchronization primitives.
Threads are used internally to fake the asynchronous nature of all of the system
calls. libuv also uses threads to allow you, the application, to perform a task
asynchronously that is actually blocking, by spawning a thread and collecting
the result when it is done.
Today there are two predominant thread libraries: the Windows threads
implementation and POSIX's :man:`pthreads(7)`. libuv's thread API is analogous to
the pthreads API and often has similar semantics.
A notable aspect of libuv's thread facilities is that it is a self contained
section within libuv. Whereas other features intimately depend on the event
loop and callback principles, threads are complete agnostic, they block as
required, signal errors directly via return values, and, as shown in the
:ref:`first example <thread-create-example>`, don't even require a running
event loop.
libuv's thread API is also very limited since the semantics and syntax of
threads are different on all platforms, with different levels of completeness.
This chapter makes the following assumption: **There is only one event loop,
running in one thread (the main thread)**. No other thread interacts
with the event loop (except using ``uv_async_send``).
Core thread operations
----------------------
There isn't much here, you just start a thread using ``uv_thread_create()`` and
wait for it to close using ``uv_thread_join()``.
.. _thread-create-example:
.. rubric:: thread-create/main.c
.. literalinclude:: ../../code/thread-create/main.c
:language: c
:linenos:
:lines: 26-36
:emphasize-lines: 3-7
.. tip::
``uv_thread_t`` is just an alias for ``pthread_t`` on Unix, but this is an
implementation detail, avoid depending on it to always be true.
The second parameter is the function which will serve as the entry point for
the thread, the last parameter is a ``void *`` argument which can be used to pass
custom parameters to the thread. The function ``hare`` will now run in a separate
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
Unlike ``pthread_join()`` which allows the target thread to pass back a value to
the calling thread using a second parameter, ``uv_thread_join()`` does not. To
send values use :ref:`inter-thread-communication`.
Synchronization Primitives
--------------------------
This section is purposely spartan. This book is not about threads, so I only
catalogue any surprises in the libuv APIs here. For the rest you can look at
the :man:`pthreads(7)` man pages.
Mutexes
~~~~~~~
The mutex functions are a **direct** map to the pthread equivalents.
.. rubric:: libuv mutex functions
.. code-block:: c
int uv_mutex_init(uv_mutex_t* handle);
int uv_mutex_init_recursive(uv_mutex_t* handle);
void uv_mutex_destroy(uv_mutex_t* handle);
void uv_mutex_lock(uv_mutex_t* handle);
int uv_mutex_trylock(uv_mutex_t* handle);
void uv_mutex_unlock(uv_mutex_t* handle);
The ``uv_mutex_init()``, ``uv_mutex_init_recursive()`` and ``uv_mutex_trylock()``
functions will return 0 on success, and an error code otherwise.
If `libuv` has been compiled with debugging enabled, ``uv_mutex_destroy()``,
``uv_mutex_lock()`` and ``uv_mutex_unlock()`` will ``abort()`` on error.
Similarly ``uv_mutex_trylock()`` will abort if the error is anything *other
than* ``EAGAIN`` or ``EBUSY``.
Recursive mutexes are supported, but you should not rely on them. Also, they
should not be used with ``uv_cond_t`` variables.
The default BSD mutex implementation will raise an error if a thread which has
locked a mutex attempts to lock it again. For example, a construct like::
uv_mutex_init(a_mutex);
uv_mutex_lock(a_mutex);
uv_thread_create(thread_id, entry, (void *)a_mutex);
uv_mutex_lock(a_mutex);
// more things here
can be used to wait until another thread initializes some stuff and then
unlocks ``a_mutex`` but will lead to your program crashing if in debug mode, or
return an error in the second call to ``uv_mutex_lock()``.
.. note::
Mutexes on Windows are always recursive.
Locks
~~~~~
Read-write locks are a more granular access mechanism. Two readers can access
shared memory at the same time. A writer may not acquire the lock when it is
held by a reader. A reader or writer may not acquire a lock when a writer is
holding it. Read-write locks are frequently used in databases. Here is a toy
example.
.. rubric:: locks/main.c - simple rwlocks
.. literalinclude:: ../../code/locks/main.c
:language: c
:linenos:
:emphasize-lines: 13,16,27,31,42,55
Run this and observe how the readers will sometimes overlap. In case of
multiple writers, schedulers will usually give them higher priority, so if you
add two writers, you'll see that both writers tend to finish first before the
readers get a chance again.
We also use barriers in the above example so that the main thread can wait for
all readers and writers to indicate they have ended.
Others
~~~~~~
libuv also supports semaphores_, `condition variables`_ and barriers_ with APIs
very similar to their pthread counterparts.
.. _semaphores: https://en.wikipedia.org/wiki/Semaphore_(programming)
.. _condition variables: https://en.wikipedia.org/wiki/Monitor_(synchronization)#Condition_variables_2
.. _barriers: https://en.wikipedia.org/wiki/Barrier_(computer_science)
In addition, libuv provides a convenience function ``uv_once()``. Multiple
threads can attempt to call ``uv_once()`` with a given guard and a function
pointer, **only the first one will win, the function will be called once and
only once**::
/* Initialize guard */
static uv_once_t once_only = UV_ONCE_INIT;
int i = 0;
void increment() {
i++;
}
void thread1() {
/* ... work */
uv_once(once_only, increment);
}
void thread2() {
/* ... work */
uv_once(once_only, increment);
}
int main() {
/* ... spawn threads */
}
After all threads are done, ``i == 1``.
.. _libuv-work-queue:
libuv v0.11.11 onwards also added a ``uv_key_t`` struct and api_ for
thread-local storage.
.. _api: http://docs.libuv.org/en/v1.x/threading.html#thread-local-storage
libuv work queue
----------------
``uv_queue_work()`` is a convenience function that allows an application to run
a task in a separate thread, and have a callback that is triggered when the
task is done. A seemingly simple function, what makes ``uv_queue_work()``
tempting is that it allows potentially any third-party libraries to be used
with the event-loop paradigm. When you use event loops, it is *imperative to
make sure that no function which runs periodically in the loop thread blocks
when performing I/O or is a serious CPU hog*, because this means that the loop
slows down and events are not being handled at full capacity.
However, a lot of existing code out there features blocking functions (for example
a routine which performs I/O under the hood) to be used with threads if you
want responsiveness (the classic 'one thread per client' server model), and
getting them to play with an event loop library generally involves rolling your
own system of running the task in a separate thread. libuv just provides
a convenient abstraction for this.
Here is a simple example inspired by `node.js is cancer`_. We are going to
calculate fibonacci numbers, sleeping a bit along the way, but run it in
a separate thread so that the blocking and CPU bound task does not prevent the
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
The actual task function is simple, nothing to show that it is going to be
run in a separate thread. The ``uv_work_t`` structure is the clue. You can pass
arbitrary data through it using the ``void* data`` field and use it to
communicate to and from the thread. But be sure you are using proper locks if
you are changing things while both threads may be running.
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
The thread function will be launched in a separate thread, passed the
``uv_work_t`` structure and once the function returns, the *after* function
will be called on the thread the event loop is running in. It will be passed
the same structure.
For writing wrappers to blocking libraries, a common :ref:`pattern <baton>`
is to use a baton to exchange data.
Since libuv version `0.9.4` an additional function, ``uv_cancel()``, is
available. This allows you to cancel tasks on the libuv work queue. Only tasks
that *are yet to be started* can be cancelled. If a task has *already started
executing, or it has finished executing*, ``uv_cancel()`` **will fail**.
``uv_cancel()`` is useful to cleanup pending tasks if the user requests
termination. For example, a music player may queue up multiple directories to
be scanned for audio files. If the user terminates the program, it should quit
quickly and not wait until all pending requests are run.
Let's modify the fibonacci example to demonstrate ``uv_cancel()``. We first set
up a signal handler for termination.
.. rubric:: queue-cancel/main.c
.. literalinclude:: ../../code/queue-cancel/main.c
:language: c
:linenos:
:lines: 43-
When the user triggers the signal by pressing ``Ctrl+C`` we send
``uv_cancel()`` to all the workers. ``uv_cancel()`` will return ``0`` for those that are already executing or finished.
.. rubric:: queue-cancel/main.c
.. literalinclude:: ../../code/queue-cancel/main.c
:language: c
:linenos:
:lines: 33-41
:emphasize-lines: 6
For tasks that do get cancelled successfully, the *after* function is called
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
``uv_cancel()`` can also be used with ``uv_fs_t`` and ``uv_getaddrinfo_t``
requests. For the filesystem family of functions, ``uv_fs_t.errorno`` will be
set to ``UV_ECANCELED``.
.. TIP::
A well designed program would have a way to terminate long running workers
that have already started executing. Such a worker could periodically check
for a variable that only the main process sets to signal termination.
.. _inter-thread-communication:
Inter-thread communication
--------------------------
Sometimes you want various threads to actually send each other messages *while*
they are running. For example you might be running some long duration task in
a separate thread (perhaps using ``uv_queue_work``) but want to notify progress
to the main thread. This is a simple example of having a download manager
informing the user of the status of running downloads.
.. rubric:: progress/main.c
.. literalinclude:: ../../code/progress/main.c
:language: c
:linenos:
:lines: 7-8,35-
:emphasize-lines: 2,11
The async thread communication works *on loops* so although any thread can be
the message sender, only threads with libuv loops can be receivers (or rather
the loop is the receiver). libuv will invoke the callback (``print_progress``)
with the async watcher whenever it receives a message.
.. warning::
It is important to realize that since the message send is *async*, the callback
may be invoked immediately after ``uv_async_send`` is called in another
thread, or it may be invoked after some time. libuv may also combine
multiple calls to ``uv_async_send`` and invoke your callback only once. The
only guarantee that libuv makes is -- The callback function is called *at
least once* after the call to ``uv_async_send``. If you have no pending
calls to ``uv_async_send``, the callback won't be called. If you make two
or more calls, and libuv hasn't had a chance to run the callback yet, it
*may* invoke your callback *only once* for the multiple invocations of
``uv_async_send``. Your callback will never be called twice for just one
event.
.. rubric:: progress/main.c
.. literalinclude:: ../../code/progress/main.c
:language: c
:linenos:
:lines: 10-24
:emphasize-lines: 7-8
In the download function, we modify the progress indicator and queue the message
for delivery with ``uv_async_send``. Remember: ``uv_async_send`` is also
non-blocking and will return immediately.
.. rubric:: progress/main.c
.. literalinclude:: ../../code/progress/main.c
:language: c
:linenos:
:lines: 31-34
The callback is a standard libuv pattern, extracting the data from the watcher.
Finally it is important to remember to clean up the watcher.
.. rubric:: progress/main.c
.. literalinclude:: ../../code/progress/main.c
:language: c
:linenos:
:lines: 26-29
:emphasize-lines: 3
After this example, which showed the abuse of the ``data`` field, bnoordhuis_
pointed out that using the ``data`` field is not thread safe, and
``uv_async_send()`` is actually only meant to wake up the event loop. Use
a mutex or rwlock to ensure accesses are performed in the right order.
.. note::
mutexes and rwlocks **DO NOT** work inside a signal handler, whereas
``uv_async_send`` does.
One use case where ``uv_async_send`` is required is when interoperating with
libraries that require thread affinity for their functionality. For example in
node.js, a v8 engine instance, contexts and its objects are bound to the thread
that the v8 instance was started in. Interacting with v8 data structures from
another thread can lead to undefined results. Now consider some node.js module
which binds a third party library. It may go something like this:
1. In node, the third party library is set up with a JavaScript callback to be
invoked for more information::
var lib = require('lib');
lib.on_progress(function() {
console.log("Progress");
});
lib.do();
// do other stuff
2. ``lib.do`` is supposed to be non-blocking but the third party lib is
blocking, so the binding uses ``uv_queue_work``.
3. The actual work being done in a separate thread wants to invoke the progress
callback, but cannot directly call into v8 to interact with JavaScript. So
it uses ``uv_async_send``.
4. The async callback, invoked in the main loop thread, which is the v8 thread,
then interacts with v8 to invoke the JavaScript callback.
----
.. _node.js is cancer: http://widgetsandshit.com/teddziuba/2011/10/node-js-is-cancer.html
.. _bnoordhuis: https://github.com/bnoordhuis

@ -1,450 +0,0 @@
Utilities
=========
This chapter catalogues tools and techniques which are useful for common tasks.
The `libev man page`_ already covers some patterns which can be adopted to
libuv through simple API changes. It also covers parts of the libuv API that
don't require entire chapters dedicated to them.
Timers
------
Timers invoke the callback after a certain time has elapsed since the timer was
started. libuv timers can also be set to invoke at regular intervals instead of
just once.
Simple use is to init a watcher and start it with a ``timeout``, and optional ``repeat``.
Timers can be stopped at any time.
.. code-block:: c
uv_timer_t timer_req;
uv_timer_init(loop, &timer_req);
uv_timer_start(&timer_req, callback, 5000, 2000);
will start a repeating timer, which first starts 5 seconds (the ``timeout``) after the execution
of ``uv_timer_start``, then repeats every 2 seconds (the ``repeat``). Use:
.. code-block:: c
uv_timer_stop(&timer_req);
to stop the timer. This can be used safely from within the callback as well.
The repeat interval can be modified at any time with::
uv_timer_set_repeat(uv_timer_t *timer, int64_t repeat);
which will take effect **when possible**. If this function is called from
a timer callback, it means:
* If the timer was non-repeating, the timer has already been stopped. Use
``uv_timer_start`` again.
* If the timer is repeating, the next timeout has already been scheduled, so
the old repeat interval will be used once more before the timer switches to
the new interval.
The utility function::
int uv_timer_again(uv_timer_t *)
applies **only to repeating timers** and is equivalent to stopping the timer
and then starting it with both initial ``timeout`` and ``repeat`` set to the
old ``repeat`` value. If the timer hasn't been started it fails (error code
``UV_EINVAL``) and returns -1.
An actual timer example is in the :ref:`reference count section
<reference-count>`.
.. _reference-count:
Event loop reference count
--------------------------
The event loop only runs as long as there are active handles. This system
works by having every handle increase the reference count of the event loop
when it is started and decreasing the reference count when stopped. It is also
possible to manually change the reference count of handles using::
void uv_ref(uv_handle_t*);
void uv_unref(uv_handle_t*);
These functions can be used to allow a loop to exit even when a watcher is
active or to use custom objects to keep the loop alive.
The latter can be used with interval timers. You might have a garbage collector
which runs every X seconds, or your network service might send a heartbeat to
others periodically, but you don't want to have to stop them along all clean
exit paths or error scenarios. Or you want the program to exit when all your
other watchers are done. In that case just unref the timer immediately after
creation so that if it is the only watcher running then ``uv_run`` will still
exit.
This is also used in node.js where some libuv methods are being bubbled up to
the JS API. A ``uv_handle_t`` (the superclass of all watchers) is created per
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
We initialize the garbage collector timer, then immediately ``unref`` it.
Observe how after 9 seconds, when the fake job is done, the program
automatically exits, even though the garbage collector is still running.
Idler pattern
-------------
The callbacks of idle handles are invoked once per event loop. The idle
callback can be used to perform some very low priority activity. For example,
you could dispatch a summary of the daily application performance to the
developers for analysis during periods of idleness, or use the application's
CPU time to perform SETI calculations :) An idle watcher is also useful in
a GUI application. Say you are using an event loop for a file download. If the
TCP socket is still being established and no other events are present your
event loop will pause (**block**), which means your progress bar will freeze
and the user will face an unresponsive application. In such a case queue up and
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
Here we initialize the idle watcher and queue it up along with the actual
events we are interested in. ``crunch_away`` will now be called repeatedly
until the user types something and presses Return. Then it will be interrupted
for a brief amount as the loop deals with the input data, after which it will
keep calling the idle callback again.
.. rubric:: idle-compute/main.c
.. literalinclude:: ../../code/idle-compute/main.c
:language: c
:linenos:
:lines: 10-19
.. _baton:
Passing data to worker thread
-----------------------------
When using ``uv_queue_work`` you'll usually need to pass complex data through
to the worker thread. The solution is to use a ``struct`` and set
``uv_work_t.data`` to point to it. A slight variation is to have the
``uv_work_t`` itself as the first member of this struct (called a baton [#]_).
This allows cleaning up the work request and all the data in one free call.
.. code-block:: c
:linenos:
:emphasize-lines: 2
struct ftp_baton {
uv_work_t req;
char *host;
int port;
char *username;
char *password;
}
.. code-block:: c
:linenos:
:emphasize-lines: 2
ftp_baton *baton = (ftp_baton*) malloc(sizeof(ftp_baton));
baton->req.data = (void*) baton;
baton->host = strdup("my.webhost.com");
baton->port = 21;
// ...
uv_queue_work(loop, &baton->req, ftp_session, ftp_cleanup);
Here we create the baton and queue the task.
Now the task function can extract the data it needs:
.. code-block:: c
:linenos:
:emphasize-lines: 2, 12
void ftp_session(uv_work_t *req) {
ftp_baton *baton = (ftp_baton*) req->data;
fprintf(stderr, "Connecting to %s\n", baton->host);
}
void ftp_cleanup(uv_work_t *req) {
ftp_baton *baton = (ftp_baton*) req->data;
free(baton->host);
// ...
free(baton);
}
We then free the baton which also frees the watcher.
External I/O with polling
-------------------------
Usually third-party libraries will handle their own I/O, and keep track of
their sockets and other files internally. In this case it isn't possible to use
the standard stream I/O operations, but the library can still be integrated
into the libuv event loop. All that is required is that the library allow you
to access the underlying file descriptors and provide functions that process
tasks in small increments as decided by your application. Some libraries though
will not allow such access, providing only a standard blocking function which
will perform the entire I/O transaction and only then return. It is unwise to
use these in the event loop thread, use the :ref:`threadpool` instead. Of
course, this will also mean losing granular control on the library.
The ``uv_poll`` section of libuv simply watches file descriptors using the
operating system notification mechanism. In some sense, all the I/O operations
that libuv implements itself are also backed by ``uv_poll`` like code. Whenever
the OS notices a change of state in file descriptors being polled, libuv will
invoke the associated callback.
Here we will walk through a simple download manager that will use libcurl_ to
download files. Rather than give all control to libcurl, we'll instead be
using the libuv event loop, and use the non-blocking, async multi_ interface to
progress with the download whenever libuv notifies of I/O readiness.
.. _libcurl: https://curl.haxx.se/libcurl/
.. _multi: https://curl.haxx.se/libcurl/c/libcurl-multi.html
.. rubric:: uvwget/main.c - The setup
.. literalinclude:: ../../code/uvwget/main.c
:language: c
:linenos:
:lines: 1-9,140-
:emphasize-lines: 7,21,24-25
The way each library is integrated with libuv will vary. In the case of
libcurl, we can register two callbacks. The socket callback ``handle_socket``
is invoked whenever the state of a socket changes and we have to start polling
it. ``start_timeout`` is called by libcurl to notify us of the next timeout
interval, after which we should drive libcurl forward regardless of I/O status.
This is so that libcurl can handle errors or do whatever else is required to
get the download moving.
Our downloader is to be invoked as::
$ ./uvwget [url1] [url2] ...
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
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
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
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
We are interested in the socket fd ``s``, and the ``action``. For every socket
we create a ``uv_poll_t`` handle if it doesn't exist, and associate it with the
socket using ``curl_multi_assign``. This way ``socketp`` points to it whenever
the callback is invoked.
In the case that the download is done or fails, libcurl requests removal of the
poll. So we stop and free the poll handle.
Depending on what events libcurl wishes to watch for, we start polling with
``UV_READABLE`` or ``UV_WRITABLE``. Now libuv will invoke the poll callback
whenever the socket is ready for reading or writing. Calling ``uv_poll_start``
multiple times on the same handle is acceptable, it will just update the events
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
The first thing we do is to stop the timer, since there has been some progress
in the interval. Then depending on what event triggered the callback, we set
the correct flags. Then we call ``curl_multi_socket_action`` with the socket
that progressed and the flags informing about what events happened. At this
point libcurl does all of its internal tasks in small increments, and will
attempt to return as fast as possible, which is exactly what an evented program
wants in its main thread. libcurl keeps queueing messages into its own queue
about transfer progress. In our case we are only interested in transfers that
are completed. So we extract these messages, and clean up handles whose
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
Check & Prepare watchers
------------------------
TODO
Loading libraries
-----------------
libuv provides a cross platform API to dynamically load `shared libraries`_.
This can be used to implement your own plugin/extension/module system and is
used by node.js to implement ``require()`` support for bindings. The usage is
quite simple as long as your library exports the right symbols. Be careful with
sanity and security checks when loading third party code, otherwise your
program will behave unpredictably. This example implements a very simple
plugin system which does nothing except print the name of the plugin.
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
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
which will be called by the application. This plugin is compiled as a shared
library and can be loaded by running our application::
$ ./plugin libhello.dylib
Loading libhello.dylib
Registered plugin "Hello World!"
.. NOTE::
The shared library filename will be different depending on platforms. On
Linux it is ``libhello.so``.
This is done by using ``uv_dlopen`` to first load the shared library
``libhello.dylib``. Then we get access to the ``initialize`` function using
``uv_dlsym`` and invoke it.
.. rubric:: plugin/main.c
.. literalinclude:: ../../code/plugin/main.c
:language: c
:linenos:
:lines: 7-
:emphasize-lines: 15, 18, 24
``uv_dlopen`` expects a path to the shared library and sets the opaque
``uv_lib_t`` pointer. It returns 0 on success, -1 on error. Use ``uv_dlerror``
to get the error message.
``uv_dlsym`` stores a pointer to the symbol in the second argument in the third
argument. ``init_plugin_function`` is a function pointer to the sort of
function we are looking for in the application's plugins.
.. _shared libraries: https://en.wikipedia.org/wiki/Shared_library#Shared_libraries
TTY
---
Text terminals have supported basic formatting for a long time, with a `pretty
standardised`_ command set. This formatting is often used by programs to
improve the readability of terminal output. For example ``grep --colour``.
libuv provides the ``uv_tty_t`` abstraction (a stream) and related functions to
implement the ANSI escape codes across all platforms. By this I mean that libuv
converts ANSI codes to the Windows equivalent, and provides functions to get
terminal information.
.. _pretty standardised: https://en.wikipedia.org/wiki/ANSI_escape_sequences
The first thing to do is to initialize a ``uv_tty_t`` with the file descriptor
it reads/writes from. This is achieved with::
int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int unused)
The ``unused`` parameter is now auto-detected and ignored. It previously needed
to be set to use ``uv_read_start()`` on the stream.
It is then best to use ``uv_tty_set_mode`` to set the mode to *normal*
which enables most TTY formatting, flow-control and other settings. Other_ modes
are also available.
.. _Other: http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_mode_t
Remember to call ``uv_tty_reset_mode`` when your program exits to restore the
state of the terminal. Just good manners. Another set of good manners is to be
aware of redirection. If the user redirects the output of your command to
a file, control sequences should not be written as they impede readability and
``grep``. To check if the file descriptor is indeed a TTY, call
``uv_guess_handle`` with the file descriptor and compare the return value with
``UV_TTY``.
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
The final TTY helper is ``uv_tty_get_winsize()`` which is used to get the
width and height of the terminal and returns ``0`` on success. Here is a small
program which does some animation using the function and character position
escape codes.
.. rubric:: tty-gravity/main.c
.. literalinclude:: ../../code/tty-gravity/main.c
:language: c
:linenos:
:emphasize-lines: 19,25,38
The escape codes are:
====== =======================
Code Meaning
====== =======================
*2* J Clear part of the screen, 2 is entire screen
H Moves cursor to certain position, default top-left
*n* B Moves cursor down by n lines
*n* C Moves cursor right by n columns
m Obeys string of display settings, in this case green background (40+2), white text (30+7)
====== =======================
As you can see this is very useful to produce nicely formatted output, or even
console based arcade games if that tickles your fancy. For fancier control you
can try `ncurses`_.
.. _ncurses: https://www.gnu.org/software/ncurses/ncurses.html
.. versionchanged:: 1.23.1: the `readable` parameter is now unused and ignored.
The appropriate value will now be auto-detected from the kernel.
----
.. [#] I was first introduced to the term baton in this context, in Konstantin
Käfer's excellent slides on writing node.js bindings --
https://kkaefer.com/node-cpp-modules/#baton
.. [#] mfp is My Fancy Plugin
.. _libev man page: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#COMMON_OR_USEFUL_IDIOMS_OR_BOTH

@ -1,283 +0,0 @@
.. _handle:
:c:type:`uv_handle_t` --- Base handle
=====================================
`uv_handle_t` is the base type for all libuv handle types.
Structures are aligned so that any libuv handle can be cast to `uv_handle_t`.
All API functions defined here work with any handle type.
Libuv handles are not movable. Pointers to handle structures passed to
functions must remain valid for the duration of the requested operation. Take
care when using stack allocated handles.
Data types
----------
.. c:type:: uv_handle_t
The base libuv handle type.
.. c:enum:: uv_handle_type
The kind of the libuv handle.
::
typedef enum {
UV_UNKNOWN_HANDLE = 0,
UV_ASYNC,
UV_CHECK,
UV_FS_EVENT,
UV_FS_POLL,
UV_HANDLE,
UV_IDLE,
UV_NAMED_PIPE,
UV_POLL,
UV_PREPARE,
UV_PROCESS,
UV_STREAM,
UV_TCP,
UV_TIMER,
UV_TTY,
UV_UDP,
UV_SIGNAL,
UV_FILE,
UV_HANDLE_TYPE_MAX
} uv_handle_type;
.. c:type:: uv_any_handle
Union of all handle types.
.. c:type:: void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
Type definition for callback passed to :c:func:`uv_read_start` and
:c:func:`uv_udp_recv_start`. The user must allocate memory and fill the supplied
:c:type:`uv_buf_t` structure. If NULL is assigned as the buffer's base or 0 as its length,
a ``UV_ENOBUFS`` error will be triggered in the :c:type:`uv_udp_recv_cb` or the
:c:type:`uv_read_cb` callback.
Each buffer is used only once and the user is responsible for freeing it in the
:c:type:`uv_udp_recv_cb` or the :c:type:`uv_read_cb` callback.
A suggested size (65536 at the moment in most cases) is provided, but it's just an indication,
not related in any way to the pending data to be read. The user is free to allocate the amount
of memory they decide.
As an example, applications with custom allocation schemes such as using freelists, allocation
pools or slab based allocators may decide to use a different size which matches the memory
chunks they already have.
Example:
::
static void my_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
.. c:type:: void (*uv_close_cb)(uv_handle_t* handle)
Type definition for callback passed to :c:func:`uv_close`.
Public members
^^^^^^^^^^^^^^
.. c:member:: uv_loop_t* uv_handle_t.loop
Pointer to the :c:type:`uv_loop_t` the handle is running on. Readonly.
.. c:member:: uv_handle_type uv_handle_t.type
The :c:type:`uv_handle_type`, indicating the type of the underlying handle. Readonly.
.. c:member:: void* uv_handle_t.data
Space for user-defined arbitrary data. libuv does not use this field.
API
---
.. 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
arguments: the name of the `uv_handle_type` element without the
`UV_` prefix, and the name of the corresponding structure type
without the `uv_` prefix and `_t` suffix.
.. c:function:: int uv_is_active(const uv_handle_t* handle)
Returns non-zero if the handle is active, zero if it's inactive. What
"active" means depends on the type of handle:
- A uv_async_t handle is always active and cannot be deactivated, except
by closing it with uv_close().
- A uv_pipe_t, uv_tcp_t, uv_udp_t, etc. handle - basically any handle that
deals with i/o - is active when it is doing something that involves i/o,
like reading, writing, connecting, accepting new connections, etc.
- A uv_check_t, uv_idle_t, uv_timer_t, etc. handle is active when it has
been started with a call to uv_check_start(), uv_idle_start(), etc.
Rule of thumb: if a handle of type `uv_foo_t` has a `uv_foo_start()`
function, then it's active from the moment that function is called.
Likewise, `uv_foo_stop()` deactivates the handle again.
.. c:function:: int uv_is_closing(const uv_handle_t* handle)
Returns non-zero if the handle is closing or closed, zero otherwise.
.. note::
This function should only be used between the initialization of the handle and the
arrival of the close callback.
.. c:function:: void uv_close(uv_handle_t* handle, uv_close_cb close_cb)
Request handle to be closed. `close_cb` will be called asynchronously after
this call. This MUST be called on each handle before memory is released.
Moreover, the memory can only be released in `close_cb` or after it has
returned.
Handles that wrap file descriptors are closed immediately but
`close_cb` will still be deferred to the next iteration of the event loop.
It gives you a chance to free up any resources associated with the handle.
In-progress requests, like uv_connect_t or uv_write_t, are cancelled and
have their callbacks called asynchronously with status=UV_ECANCELED.
.. c:function:: void uv_ref(uv_handle_t* handle)
Reference the given handle. References are idempotent, that is, if a handle
is already referenced calling this function again will have no effect.
See :ref:`refcount`.
.. c:function:: void uv_unref(uv_handle_t* handle)
Un-reference the given handle. References are idempotent, that is, if a handle
is not referenced calling this function again will have no effect.
See :ref:`refcount`.
.. c:function:: int uv_has_ref(const uv_handle_t* handle)
Returns non-zero if the handle referenced, zero otherwise.
See :ref:`refcount`.
.. c:function:: size_t uv_handle_size(uv_handle_type type)
Returns the size of the given handle type. Useful for FFI binding writers
who don't want to know the structure layout.
Miscellaneous API functions
---------------------------
The following API functions take a :c:type:`uv_handle_t` argument but they work
just for some handle types.
.. c:function:: int uv_send_buffer_size(uv_handle_t* handle, int* value)
Gets or sets the size of the send buffer that the operating
system uses for the socket.
If `*value` == 0, then it will set `*value` to the current send buffer size.
If `*value` > 0 then it will use `*value` to set the new send buffer size.
On success, zero is returned. On error, a negative result is
returned.
This function works for TCP, pipe and UDP handles on Unix and for TCP and
UDP handles on Windows.
.. note::
Linux will set double the size and return double the size of the original set value.
.. c:function:: int uv_recv_buffer_size(uv_handle_t* handle, int* value)
Gets or sets the size of the receive buffer that the operating
system uses for the socket.
If `*value` == 0, then it will set `*value` to the current receive buffer size.
If `*value` > 0 then it will use `*value` to set the new receive buffer size.
On success, zero is returned. On error, a negative result is
returned.
This function works for TCP, pipe and UDP handles on Unix and for TCP and
UDP handles on Windows.
.. note::
Linux will set double the size and return double the size of the original set value.
.. c:function:: int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd)
Gets the platform dependent file descriptor equivalent.
The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing
any other handle type will fail with `UV_EINVAL`.
If a handle doesn't have an attached file descriptor yet or the handle
itself has been closed, this function will return `UV_EBADF`.
.. warning::
Be very careful when using this function. libuv assumes it's in control of the file
descriptor so any change to it may lead to malfunction.
.. c:function:: uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle)
Returns `handle->loop`.
.. versionadded:: 1.19.0
.. c:function:: void* uv_handle_get_data(const uv_handle_t* handle)
Returns `handle->data`.
.. versionadded:: 1.19.0
.. c:function:: void* uv_handle_set_data(uv_handle_t* handle, void* data)
Sets `handle->data` to `data`.
.. versionadded:: 1.19.0
.. c:function:: uv_handle_type uv_handle_get_type(const uv_handle_t* handle)
Returns `handle->type`.
.. versionadded:: 1.19.0
.. c:function:: const char* uv_handle_type_name(uv_handle_type type)
Returns the name for the equivalent struct for a given handle type,
e.g. `"pipe"` (as in :c:type:`uv_pipe_t`) for `UV_NAMED_PIPE`.
If no such handle type exists, this returns `NULL`.
.. versionadded:: 1.19.0
.. _refcount:
Reference counting
------------------
The libuv event loop (if run in the default mode) will run until there are no
active `and` referenced handles left. The user can force the loop to exit early
by unreferencing handles which are active, for example by calling :c:func:`uv_unref`
after calling :c:func:`uv_timer_start`.
A handle can be referenced or unreferenced, the refcounting scheme doesn't use
a counter, so both operations are idempotent.
All handles are referenced when active by default, see :c:func:`uv_is_active`
for a more detailed explanation on what being `active` involves.

@ -1,62 +0,0 @@
.. _idle:
:c:type:`uv_idle_t` --- Idle handle
===================================
Idle handles will run the given callback once per loop iteration, right
before the :c:type:`uv_prepare_t` handles.
.. note::
The notable difference with prepare handles is that when there are active idle handles,
the loop will perform a zero timeout poll instead of blocking for i/o.
.. warning::
Despite the name, idle handles will get their callbacks called on every loop iteration,
not when the loop is actually "idle".
Data types
----------
.. c:type:: uv_idle_t
Idle handle type.
.. c:type:: void (*uv_idle_cb)(uv_idle_t* handle)
Type definition for callback passed to :c:func:`uv_idle_start`.
Public members
^^^^^^^^^^^^^^
N/A
.. seealso:: The :c:type:`uv_handle_t` members also apply.
API
---
.. c:function:: int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle)
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. 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.

@ -1,62 +0,0 @@
Welcome to the libuv documentation
==================================
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`_.
.. note::
In case you find errors in this documentation you can help by sending
`pull requests <https://github.com/libuv/libuv>`_!
.. _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/blob/v1.x/LINKS.md
Features
--------
* Full-featured event loop backed by epoll, kqueue, IOCP, event ports.
* Asynchronous TCP and UDP sockets
* Asynchronous DNS resolution
* Asynchronous file and file system operations
* File system events
* ANSI escape code controlled TTY
* IPC with socket sharing, using Unix domain sockets or named pipes (Windows)
* Child processes
* Thread pool
* Signal handling
* High resolution clock
* Threading and synchronization primitives
Documentation
-------------
.. toctree::
:maxdepth: 1
design
api
guide
upgrading
Downloads
---------
libuv can be downloaded from `here <https://dist.libuv.org/dist/>`_.
Installation
------------
Installation instructions can be found in `the README <https://github.com/libuv/libuv/blob/master/README.md>`_.

@ -1,245 +0,0 @@
.. _loop:
:c:type:`uv_loop_t` --- Event loop
==================================
The event loop is the central part of libuv's functionality. It takes care
of polling for i/o and scheduling callbacks to be run based on different sources
of events.
Data types
----------
.. c:type:: uv_loop_t
Loop data type.
.. c:enum:: uv_run_mode
Mode used to run the loop with :c:func:`uv_run`.
::
typedef enum {
UV_RUN_DEFAULT = 0,
UV_RUN_ONCE,
UV_RUN_NOWAIT
} uv_run_mode;
.. c:type:: void (*uv_walk_cb)(uv_handle_t* handle, void* arg)
Type definition for callback passed to :c:func:`uv_walk`.
Public members
^^^^^^^^^^^^^^
.. c:member:: void* uv_loop_t.data
Space for user-defined arbitrary data. libuv does not use and does not
touch this field.
API
---
.. c:function:: int uv_loop_init(uv_loop_t* loop)
Initializes the given `uv_loop_t` structure.
.. c:function:: int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...)
.. versionadded:: 1.0.2
Set additional loop options. You should normally call this before the
first call to :c:func:`uv_run` unless mentioned otherwise.
Returns 0 on success or a UV_E* error code on failure. Be prepared to
handle UV_ENOSYS; it means the loop option is not supported by the platform.
Supported options:
- UV_LOOP_BLOCK_SIGNAL: Block a signal when polling for new events. The
second argument to :c:func:`uv_loop_configure` is the signal number.
This operation is currently only implemented for SIGPROF signals,
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
has finished executing and all open handles and requests have been closed,
or it will return UV_EBUSY. After this function returns, the user can free
the memory allocated for the loop.
.. c:function:: uv_loop_t* uv_default_loop(void)
Returns the initialized default loop. It may return NULL in case of
allocation failure.
This function is just a convenient way for having a global loop throughout
an application, the default loop is in no way different than the ones
initialized with :c:func:`uv_loop_init`. As such, the default loop can (and
should) be closed with :c:func:`uv_loop_close` so the resources associated
with it are freed.
.. warning::
This function is not thread safe.
.. c:function:: int uv_run(uv_loop_t* loop, uv_run_mode mode)
This function runs the event loop. It will act differently depending on the
specified mode:
- UV_RUN_DEFAULT: Runs the event loop until there are no more active and
referenced handles or requests. Returns non-zero if :c:func:`uv_stop`
was called and there are still active handles or requests. Returns
zero in all other cases.
- UV_RUN_ONCE: Poll for i/o once. Note that this function blocks if
there are no pending callbacks. Returns zero when done (no active handles
or requests left), or non-zero if more callbacks are expected (meaning
you should run the event loop again sometime in the future).
- UV_RUN_NOWAIT: Poll for i/o once but don't block if there are no
pending callbacks. Returns zero if done (no active handles
or requests left), or non-zero if more callbacks are expected (meaning
you should run the event loop again sometime in the future).
:c:func:`uv_run` is not reentrant. It must not be called from a callback.
.. c:function:: int uv_loop_alive(const uv_loop_t* loop)
Returns non-zero if there are referenced active handles, active
requests or closing handles in the loop.
.. c:function:: void uv_stop(uv_loop_t* loop)
Stop the event loop, causing :c:func:`uv_run` to end as soon as
possible. This will happen not sooner than the next loop iteration.
If this function was called before blocking for i/o, the loop won't block
for i/o on this iteration.
.. c:function:: size_t uv_loop_size(void)
Returns the size of the `uv_loop_t` structure. Useful for FFI binding
writers who don't want to know the structure layout.
.. c:function:: int uv_backend_fd(const uv_loop_t* loop)
Get backend file descriptor. Only kqueue, epoll and event ports are
supported.
This can be used in conjunction with `uv_run(loop, UV_RUN_NOWAIT)` to
poll in one thread and run the event loop's callbacks in another see
test/test-embed.c for an example.
.. note::
Embedding a kqueue fd in another kqueue pollset doesn't work on all platforms. It's not
an error to add the fd but it never generates events.
.. c:function:: int uv_backend_timeout(const uv_loop_t* loop)
Get the poll timeout. The return value is in milliseconds, or -1 for no
timeout.
.. c:function:: uint64_t uv_now(const uv_loop_t* loop)
Return the current timestamp in milliseconds. The timestamp is cached at
the start of the event loop tick, see :c:func:`uv_update_time` for details
and rationale.
The timestamp increases monotonically from some arbitrary point in time.
Don't make assumptions about the starting point, you will only get
disappointed.
.. note::
Use :c:func:`uv_hrtime` if you need sub-millisecond granularity.
.. c:function:: void uv_update_time(uv_loop_t* loop)
Update the event loop's concept of "now". Libuv caches the current time
at the start of the event loop tick in order to reduce the number of
time-related system calls.
You won't normally need to call this function unless you have callbacks
that block the event loop for longer periods of time, where "longer" is
somewhat subjective but probably on the order of a millisecond or more.
.. c:function:: void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg)
Walk the list of handles: `walk_cb` will be executed with the given `arg`.
.. c:function:: int uv_loop_fork(uv_loop_t* loop)
.. versionadded:: 1.12.0
Reinitialize any kernel state necessary in the child process after
a :man:`fork(2)` system call.
Previously started watchers will continue to be started in the
child process.
It is necessary to explicitly call this function on every event
loop created in the parent process that you plan to continue to
use in the child, including the default loop (even if you don't
continue to use it in the parent). This function must be called
before calling :c:func:`uv_run` or any other API function using
the loop in the child. Failure to do so will result in undefined
behaviour, possibly including duplicate events delivered to both
parent and child or aborting the child process.
When possible, it is preferred to create a new loop in the child
process instead of reusing a loop created in the parent. New loops
created in the child process after the fork should not use this
function.
This function is not implemented on Windows, where it returns ``UV_ENOSYS``.
.. caution::
This function is experimental. It may contain bugs, and is subject to
change or removal. API and ABI stability is not guaranteed.
.. note::
On Mac OS X, if directory FS event handles were in use in the
parent process *for any event loop*, the child process will no
longer be able to use the most efficient FSEvent
implementation. Instead, uses of directory FS event handles in
the child will fall back to the same implementation used for
files and on other kqueue-based systems.
.. caution::
On AIX and SunOS, FS event handles that were already started in
the parent process at the time of forking will *not* deliver
events in the child process; they must be closed and restarted.
On all other platforms, they will continue to work normally
without any further intervention.
.. caution::
Any previous value returned from :c:func:`uv_backend_fd` is now
invalid. That function must be called again to determine the
correct backend file descriptor.
.. c:function:: void* uv_loop_get_data(const uv_loop_t* loop)
Returns `loop->data`.
.. versionadded:: 1.19.0
.. c:function:: void* uv_loop_set_data(uv_loop_t* loop, void* data)
Sets `loop->data` to `data`.
.. versionadded:: 1.19.0

@ -1,27 +0,0 @@
.. _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

@ -1,244 +0,0 @@
.. _migration_010_100:
libuv 0.10 -> 1.0.0 migration guide
===================================
Some APIs changed quite a bit throughout the 1.0.0 development process. Here
is a migration guide for the most significant changes that happened after 0.10
was released.
Loop initialization and closing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In libuv 0.10 (and previous versions), loops were created with `uv_loop_new`, which
allocated memory for a new loop and initialized it; and destroyed with `uv_loop_delete`,
which destroyed the loop and freed the memory. Starting with 1.0, those are deprecated
and the user is responsible for allocating the memory and then initializing the loop.
libuv 0.10
::
uv_loop_t* loop = uv_loop_new();
...
uv_loop_delete(loop);
libuv 1.0
::
uv_loop_t* loop = malloc(sizeof *loop);
uv_loop_init(loop);
...
uv_loop_close(loop);
free(loop);
.. note::
Error handling was omitted for brevity. Check the documentation for :c:func:`uv_loop_init`
and :c:func:`uv_loop_close`.
Error handling
~~~~~~~~~~~~~~
Error handling had a major overhaul in libuv 1.0. In general, functions and status parameters
would get 0 for success and -1 for failure on libuv 0.10, and the user had to use `uv_last_error`
to fetch the error code, which was a positive number.
In 1.0, functions and status parameters contain the actual error code, which is 0 for success, or
a negative number in case of error.
libuv 0.10
::
... assume 'server' is a TCP server which is already listening
r = uv_listen((uv_stream_t*) server, 511, NULL);
if (r == -1) {
uv_err_t err = uv_last_error(uv_default_loop());
/* err.code contains UV_EADDRINUSE */
}
libuv 1.0
::
... assume 'server' is a TCP server which is already listening
r = uv_listen((uv_stream_t*) server, 511, NULL);
if (r < 0) {
/* r contains UV_EADDRINUSE */
}
Threadpool changes
~~~~~~~~~~~~~~~~~~
In libuv 0.10 Unix used a threadpool which defaulted to 4 threads, while Windows used the
`QueueUserWorkItem` API, which uses a Windows internal threadpool, which defaults to 512
threads per process.
In 1.0, we unified both implementations, so Windows now uses the same implementation Unix
does. The threadpool size can be set by exporting the ``UV_THREADPOOL_SIZE`` environment
variable. See :c:ref:`threadpool`.
Allocation callback API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In libuv 0.10 the callback had to return a filled :c:type:`uv_buf_t` by value:
::
uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
return uv_buf_init(malloc(size), size);
}
In libuv 1.0 a pointer to a buffer is passed to the callback, which the user
needs to fill:
::
void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
buf->base = malloc(size);
buf->len = size;
}
Unification of IPv4 / IPv6 APIs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libuv 1.0 unified the IPv4 and IPv6 APIS. There is no longer a `uv_tcp_bind` and `uv_tcp_bind6`
duality, there is only :c:func:`uv_tcp_bind` now.
IPv4 functions took ``struct sockaddr_in`` structures by value, and IPv6 functions took
``struct sockaddr_in6``. Now functions take a ``struct sockaddr*`` (note it's a pointer).
It can be stack allocated.
libuv 0.10
::
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234);
...
uv_tcp_bind(&server, addr)
libuv 1.0
::
struct sockaddr_in addr;
uv_ip4_addr("0.0.0.0", 1234, &addr)
...
uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
The IPv4 and IPv6 struct creating functions (:c:func:`uv_ip4_addr` and :c:func:`uv_ip6_addr`)
have also changed, make sure you check the documentation.
..note::
This change applies to all functions that made a distinction between IPv4 and IPv6
addresses.
Streams / UDP data receive callback API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The streams and UDP data receive callbacks now get a pointer to a :c:type:`uv_buf_t` buffer,
not a structure by value.
libuv 0.10
::
void on_read(uv_stream_t* handle,
ssize_t nread,
uv_buf_t buf) {
...
}
void recv_cb(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
...
}
libuv 1.0
::
void on_read(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf) {
...
}
void recv_cb(uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* buf,
const struct sockaddr* addr,
unsigned flags) {
...
}
Receiving handles over pipes API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In libuv 0.10 (and earlier versions) the `uv_read2_start` function was used to start reading
data on a pipe, which could also result in the reception of handles over it. The callback
for such function looked like this:
::
void on_read(uv_pipe_t* pipe,
ssize_t nread,
uv_buf_t buf,
uv_handle_type pending) {
...
}
In libuv 1.0, `uv_read2_start` was removed, and the user needs to check if there are pending
handles using :c:func:`uv_pipe_pending_count` and :c:func:`uv_pipe_pending_type` while in
the read callback:
::
void on_read(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf) {
...
while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) {
pending = uv_pipe_pending_type((uv_pipe_t*) handle);
...
}
...
}
Extracting the file descriptor out of a handle
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
While it wasn't supported by the API, users often accessed the libuv internals in
order to get access to the file descriptor of a TCP handle, for example.
::
fd = handle->io_watcher.fd;
This is now properly exposed through the :c:func:`uv_fileno` function.
uv_fs_readdir rename and API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`uv_fs_readdir` returned a list of strings in the `req->ptr` field upon completion in
libuv 0.10. In 1.0, this function got renamed to :c:func:`uv_fs_scandir`, since it's
actually implemented using ``scandir(3)``.
In addition, instead of allocating a full list strings, the user is able to get one
result at a time by using the :c:func:`uv_fs_scandir_next` function. This function
does not need to make a roundtrip to the threadpool, because libuv will keep the
list of *dents* returned by ``scandir(3)`` around.

@ -1,755 +0,0 @@
.. _misc:
Miscellaneous utilities
=======================
This section contains miscellaneous functions that don't really belong in any
other section.
Data types
----------
.. c:type:: uv_buf_t
Buffer data type.
.. c:member:: char* uv_buf_t.base
Pointer to the base of the buffer.
.. c:member:: size_t uv_buf_t.len
Total bytes in the buffer.
.. note::
On Windows this field is ULONG.
.. c:type:: void* (*uv_malloc_func)(size_t size)
Replacement function for :man:`malloc(3)`.
See :c:func:`uv_replace_allocator`.
.. c:type:: void* (*uv_realloc_func)(void* ptr, size_t size)
Replacement function for :man:`realloc(3)`.
See :c:func:`uv_replace_allocator`.
.. c:type:: void* (*uv_calloc_func)(size_t count, size_t size)
Replacement function for :man:`calloc(3)`.
See :c:func:`uv_replace_allocator`.
.. c:type:: void (*uv_free_func)(void* ptr)
Replacement function for :man:`free(3)`.
See :c:func:`uv_replace_allocator`.
.. c:type:: void (*uv_random_cb)(uv_random_t* req, int status, void* buf, size_t buflen)
Callback passed to :c:func:`uv_random`. `status` is non-zero in case of
error. The `buf` pointer is the same pointer that was passed to
:c:func:`uv_random`.
.. c:type:: uv_file
Cross platform representation of a file handle.
.. c:type:: uv_os_sock_t
Cross platform representation of a socket handle.
.. c:type:: uv_os_fd_t
Abstract representation of a file descriptor. On Unix systems this is a
`typedef` of `int` and on Windows a `HANDLE`.
.. c:type:: uv_pid_t
Cross platform representation of a `pid_t`.
.. versionadded:: 1.16.0
.. c:type:: uv_timeval_t
Data type for storing times.
::
typedef struct {
long tv_sec;
long tv_usec;
} uv_timeval_t;
.. c:type:: uv_timeval64_t
Alternative data type for storing times.
::
typedef struct {
int64_t tv_sec;
int32_t tv_usec;
} uv_timeval64_t;
.. c:type:: uv_rusage_t
Data type for resource usage results.
::
typedef struct {
uv_timeval_t ru_utime; /* user CPU time used */
uv_timeval_t ru_stime; /* system CPU time used */
uint64_t ru_maxrss; /* maximum resident set size */
uint64_t ru_ixrss; /* integral shared memory size (X) */
uint64_t ru_idrss; /* integral unshared data size (X) */
uint64_t ru_isrss; /* integral unshared stack size (X) */
uint64_t ru_minflt; /* page reclaims (soft page faults) (X) */
uint64_t ru_majflt; /* page faults (hard page faults) */
uint64_t ru_nswap; /* swaps (X) */
uint64_t ru_inblock; /* block input operations */
uint64_t ru_oublock; /* block output operations */
uint64_t ru_msgsnd; /* IPC messages sent (X) */
uint64_t ru_msgrcv; /* IPC messages received (X) */
uint64_t ru_nsignals; /* signals received (X) */
uint64_t ru_nvcsw; /* voluntary context switches (X) */
uint64_t ru_nivcsw; /* involuntary context switches (X) */
} uv_rusage_t;
Members marked with `(X)` are unsupported on Windows.
See :man:`getrusage(2)` for supported fields on Unix
.. c:type:: uv_cpu_info_t
Data type for CPU information.
::
typedef struct uv_cpu_info_s {
char* model;
int speed;
struct uv_cpu_times_s {
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;
.. c:type:: uv_interface_address_t
Data type for interface addresses.
::
typedef struct uv_interface_address_s {
char* name;
char phys_addr[6];
int is_internal;
union {
struct sockaddr_in address4;
struct sockaddr_in6 address6;
} address;
union {
struct sockaddr_in netmask4;
struct sockaddr_in6 netmask6;
} netmask;
} uv_interface_address_t;
.. c:type:: uv_passwd_t
Data type for password file information.
::
typedef struct uv_passwd_s {
char* username;
long uid;
long gid;
char* shell;
char* homedir;
} uv_passwd_t;
.. c:type:: uv_utsname_t
Data type for operating system name and version information.
::
typedef struct uv_utsname_s {
char sysname[256];
char release[256];
char version[256];
char machine[256];
} uv_utsname_t;
.. c:type:: uv_env_item_t
Data type for environment variable storage.
::
typedef struct uv_env_item_s {
char* name;
char* value;
} uv_env_item_t;
.. c:type:: uv_random_t
Random data request type.
API
---
.. c:function:: uv_handle_type uv_guess_handle(uv_file file)
Used to detect what type of stream should be used with a given file
descriptor. Usually this will be used during initialization to guess the
type of the stdio streams.
For :man:`isatty(3)` equivalent functionality use this function and test
for ``UV_TTY``.
.. c:function:: int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, uv_free_func free_func)
.. versionadded:: 1.6.0
Override the use of the standard library's :man:`malloc(3)`,
:man:`calloc(3)`, :man:`realloc(3)`, :man:`free(3)`, memory allocation
functions.
This function must be called before any other libuv function is called or
after all resources have been freed and thus libuv doesn't reference
any allocated memory chunk.
On success, it returns 0, if any of the function pointers is NULL it
returns UV_EINVAL.
.. warning:: There is no protection against changing the allocator multiple
times. If the user changes it they are responsible for making
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`.
Due to platform differences the user cannot rely on the ordering of the
`base` and `len` members of the uv_buf_t struct. The user is responsible for
freeing `base` after the uv_buf_t is done. Return struct passed by value.
.. c:function:: char** uv_setup_args(int argc, char** argv)
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:
::
argv = uv_setup_args(argc, argv); /* May return a copy of argv. */
.. 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 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 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.
.. c:function:: int uv_getrusage(uv_rusage_t* rusage)
Gets the resource usage measures for the current process.
.. note::
On Windows not all fields are set, the unsupported fields are filled with zeroes.
See :c:type:`uv_rusage_t` for more details.
.. c:function:: uv_pid_t uv_os_getpid(void)
Returns the current process ID.
.. versionadded:: 1.18.0
.. c:function:: uv_pid_t uv_os_getppid(void)
Returns the parent process ID.
.. versionadded:: 1.16.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`.
.. 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`.
.. c:function:: int uv_interface_addresses(uv_interface_address_t** addresses, int* count)
Gets address information about the network interfaces on the system. An
array of `count` elements is allocated and returned in `addresses`. It must
be freed by the user, calling :c:func:`uv_free_interface_addresses`.
.. c:function:: void uv_free_interface_addresses(uv_interface_address_t* addresses, int count)
Free an array of :c:type:`uv_interface_address_t` which was returned by
:c:func:`uv_interface_addresses`.
.. c:function:: void uv_loadavg(double avg[3])
Gets the load average. See: `<https://en.wikipedia.org/wiki/Load_(computing)>`_
.. note::
Returns [0,0,0] on Windows (i.e., it's not implemented).
.. c:function:: int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr)
Convert a string containing an IPv4 addresses to a binary structure.
.. c:function:: int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr)
Convert a string containing an IPv6 addresses to a binary structure.
.. c:function:: int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size)
Convert a binary structure containing an IPv4 address to a string.
.. c:function:: int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size)
Convert a binary structure containing 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)
Cross-platform IPv6-capable implementation of :man:`inet_ntop(3)`
and :man:`inet_pton(3)`. On success they return 0. In case of error
the target `dst` pointer is unmodified.
.. c:macro:: UV_IF_NAMESIZE
Maximum IPv6 interface identifier name length. Defined as
`IFNAMSIZ` on Unix and `IF_NAMESIZE` on Linux and Windows.
.. versionadded:: 1.16.0
.. c:function:: int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size)
IPv6-capable implementation of :man:`if_indextoname(3)`. When called,
`*size` indicates the length of the `buffer`, which is used to store the
result.
On success, zero is returned, `buffer` contains the interface name, and
`*size` represents the string length of the `buffer`, excluding the NUL
terminator byte from `*size`. On error, a negative result is
returned. If `buffer` is not large enough to hold the result,
`UV_ENOBUFS` is returned, and `*size` represents the necessary size in
bytes, including the NUL terminator byte into the `*size`.
On Unix, the returned interface name can be used directly as an
interface identifier in scoped IPv6 addresses, e.g.
`fe80::abc:def1:2345%en0`.
On Windows, the returned interface cannot be used as an interface
identifier, as Windows uses numerical interface identifiers, e.g.
`fe80::abc:def1:2345%5`.
To get an interface identifier in a cross-platform compatible way,
use `uv_if_indextoiid()`.
Example:
::
char ifname[UV_IF_NAMESIZE];
size_t size = sizeof(ifname);
uv_if_indextoname(sin6->sin6_scope_id, ifname, &size);
.. versionadded:: 1.16.0
.. c:function:: int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size)
Retrieves a network interface identifier suitable for use in an IPv6 scoped
address. On Windows, returns the numeric `ifindex` as a string. On all other
platforms, `uv_if_indextoname()` is called. The result is written to
`buffer`, with `*size` indicating the length of `buffer`. If `buffer` is not
large enough to hold the result, then `UV_ENOBUFS` is returned, and `*size`
represents the size, including the NUL byte, required to hold the
result.
See `uv_if_indextoname` for further details.
.. versionadded:: 1.16.0
.. c:function:: int uv_exepath(char* buffer, size_t* size)
Gets the executable path. You *must* call `uv_setup_args` before calling
this function.
.. c:function:: int uv_cwd(char* buffer, size_t* size)
Gets the current working directory, and stores it in `buffer`. If the
current working directory is too large to fit in `buffer`, this function
returns `UV_ENOBUFS`, and sets `size` to the required length, including the
null terminator.
.. versionchanged:: 1.1.0
On Unix the path no longer ends in a slash.
.. versionchanged:: 1.9.0 the returned length includes the terminating null
byte on `UV_ENOBUFS`, and the buffer is null terminated
on success.
.. c:function:: int uv_chdir(const char* dir)
Changes the current working directory.
.. c:function:: int uv_os_homedir(char* buffer, size_t* size)
Gets the current user's home directory. On Windows, `uv_os_homedir()` first
checks the `USERPROFILE` environment variable using
`GetEnvironmentVariableW()`. If `USERPROFILE` is not set,
`GetUserProfileDirectoryW()` is called. On all other operating systems,
`uv_os_homedir()` first checks the `HOME` environment variable using
:man:`getenv(3)`. If `HOME` is not set, :man:`getpwuid_r(3)` is called. The
user's home directory is stored in `buffer`. When `uv_os_homedir()` is
called, `size` indicates the maximum size of `buffer`. On success `size` is set
to the string length of `buffer`. On `UV_ENOBUFS` failure `size` is set to the
required length for `buffer`, including the null byte.
.. warning::
`uv_os_homedir()` is not thread safe.
.. versionadded:: 1.6.0
.. c:function:: int uv_os_tmpdir(char* buffer, size_t* size)
Gets the temp directory. On Windows, `uv_os_tmpdir()` uses `GetTempPathW()`.
On all other operating systems, `uv_os_tmpdir()` uses the first environment
variable found in the ordered list `TMPDIR`, `TMP`, `TEMP`, and `TEMPDIR`.
If none of these are found, the path `"/tmp"` is used, or, on Android,
`"/data/local/tmp"` is used. The temp directory is stored in `buffer`. When
`uv_os_tmpdir()` is called, `size` indicates the maximum size of `buffer`.
On success `size` is set to the string length of `buffer` (which does not
include the terminating null). On `UV_ENOBUFS` failure `size` is set to the
required length for `buffer`, including the null byte.
.. warning::
`uv_os_tmpdir()` is not thread safe.
.. versionadded:: 1.9.0
.. c:function:: int uv_os_get_passwd(uv_passwd_t* pwd)
Gets a subset of the password file entry for the current effective uid (not
the real uid). The populated data includes the username, euid, gid, shell,
and home directory. On non-Windows systems, all data comes from
:man:`getpwuid_r(3)`. On Windows, uid and gid are set to -1 and have no
meaning, and shell is `NULL`. After successfully calling this function, the
memory allocated to `pwd` needs to be freed with
:c:func:`uv_os_free_passwd`.
.. versionadded:: 1.9.0
.. c:function:: void uv_os_free_passwd(uv_passwd_t* pwd)
Frees the `pwd` memory previously allocated with :c:func:`uv_os_get_passwd`.
.. versionadded:: 1.9.0
.. c:function:: uint64_t uv_get_free_memory(void)
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 the total amount of physical memory in the system (in bytes).
.. c:function:: uint64_t uv_get_constrained_memory(void)
Gets the amount of memory available to the process (in bytes) based on
limits imposed by the OS. If there is no such constraint, or the constraint
is unknown, `0` is returned. Note that it is not unusual for this value to
be less than or greater than :c:func:`uv_get_total_memory`.
.. note::
This function currently only returns a non-zero value on Linux, based
on cgroups if it is present, and on z/OS based on RLIMIT_MEMLIMIT.
.. versionadded:: 1.29.0
.. c:function:: uint64_t uv_hrtime(void)
Returns the current high-resolution real time. This is expressed in
nanoseconds. It is relative to an arbitrary time in the past. It is not
related to the time of day and therefore not subject to clock drift. The
primary use is for measuring performance between intervals.
.. note::
Not every platform can support nanosecond resolution; however, this value will always
be in nanoseconds.
.. c:function:: void uv_print_all_handles(uv_loop_t* loop, FILE* stream)
Prints all handles associated with the given `loop` to the given `stream`.
Example:
::
uv_print_all_handles(uv_default_loop(), stderr);
/*
[--I] signal 0x1a25ea8
[-AI] async 0x1a25cf0
[R--] idle 0x1a7a8c8
*/
The format is `[flags] handle-type handle-address`. For `flags`:
- `R` is printed for a handle that is referenced
- `A` is printed for a handle that is active
- `I` is printed for a handle that is internal
.. warning::
This function is meant for ad hoc debugging, there is no API/ABI
stability guarantees.
.. versionadded:: 1.8.0
.. c:function:: void uv_print_active_handles(uv_loop_t* loop, FILE* stream)
This is the same as :c:func:`uv_print_all_handles` except only active handles
are printed.
.. warning::
This function is meant for ad hoc debugging, there is no API/ABI
stability guarantees.
.. versionadded:: 1.8.0
.. c:function:: int uv_os_environ(uv_env_item_t** envitems, int* count)
Retrieves all environment variables. This function will allocate memory
which must be freed by calling :c:func:`uv_os_free_environ`.
.. warning::
This function is not thread safe.
.. versionadded:: 1.31.0
.. c:function:: void uv_os_free_environ(uv_env_item_t* envitems, int count);
Frees the memory allocated for the environment variables by
:c:func:`uv_os_environ`.
.. versionadded:: 1.31.0
.. c:function:: int uv_os_getenv(const char* name, char* buffer, size_t* size)
Retrieves the environment variable specified by `name`, copies its value
into `buffer`, and sets `size` to the string length of the value. When
calling this function, `size` must be set to the amount of storage available
in `buffer`, including the null terminator. If the environment variable
exceeds the storage available in `buffer`, `UV_ENOBUFS` is returned, and
`size` is set to the amount of storage required to hold the value. If no
matching environment variable exists, `UV_ENOENT` is returned.
.. warning::
This function is not thread safe.
.. versionadded:: 1.12.0
.. c:function:: int uv_os_setenv(const char* name, const char* value)
Creates or updates the environment variable specified by `name` with
`value`.
.. warning::
This function is not thread safe.
.. versionadded:: 1.12.0
.. c:function:: int uv_os_unsetenv(const char* name)
Deletes the environment variable specified by `name`. If no such environment
variable exists, this function returns successfully.
.. warning::
This function is not thread safe.
.. versionadded:: 1.12.0
.. c:function:: int uv_os_gethostname(char* buffer, size_t* size)
Returns the hostname as a null-terminated string in `buffer`, and sets
`size` to the string length of the hostname. When calling this function,
`size` must be set to the amount of storage available in `buffer`, including
the null terminator. If the hostname exceeds the storage available in
`buffer`, `UV_ENOBUFS` is returned, and `size` is set to the amount of
storage required to hold the value.
.. versionadded:: 1.12.0
.. versionchanged:: 1.26.0 `UV_MAXHOSTNAMESIZE` is available and represents
the maximum `buffer` size required to store a
hostname and terminating `nul` character.
.. c:function:: int uv_os_getpriority(uv_pid_t pid, int* priority)
Retrieves the scheduling priority of the process specified by `pid`. The
returned value of `priority` is between -20 (high priority) and 19 (low
priority).
.. note::
On Windows, the returned priority will equal one of the `UV_PRIORITY`
constants.
.. versionadded:: 1.23.0
.. c:function:: int uv_os_setpriority(uv_pid_t pid, int priority)
Sets the scheduling priority of the process specified by `pid`. The
`priority` value range is between -20 (high priority) and 19 (low priority).
The constants `UV_PRIORITY_LOW`, `UV_PRIORITY_BELOW_NORMAL`,
`UV_PRIORITY_NORMAL`, `UV_PRIORITY_ABOVE_NORMAL`, `UV_PRIORITY_HIGH`, and
`UV_PRIORITY_HIGHEST` are also provided for convenience.
.. note::
On Windows, this function utilizes `SetPriorityClass()`. The `priority`
argument is mapped to a Windows priority class. When retrieving the
process priority, the result will equal one of the `UV_PRIORITY`
constants, and not necessarily the exact value of `priority`.
.. note::
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)
Retrieves system information in `buffer`. The populated data includes the
operating system name, release, version, and machine. On non-Windows
systems, `uv_os_uname()` is a thin wrapper around :man:`uname(2)`. Returns
zero on success, and a non-zero error value otherwise.
.. versionadded:: 1.25.0
.. c:function:: int uv_gettimeofday(uv_timeval64_t* tv)
Cross-platform implementation of :man:`gettimeofday(2)`. The timezone
argument to `gettimeofday()` is not supported, as it is considered obsolete.
.. versionadded:: 1.28.0
.. c:function:: int uv_random(uv_loop_t* loop, uv_random_t* req, void* buf, size_t buflen, unsigned int flags, uv_random_cb cb)
Fill `buf` with exactly `buflen` cryptographically strong random bytes
acquired from the system CSPRNG. `flags` is reserved for future extension
and must currently be 0.
Short reads are not possible. When less than `buflen` random bytes are
available, a non-zero error value is returned or passed to the callback.
The synchronous version may block indefinitely when not enough entropy
is available. The asynchronous version may not ever finish when the system
is low on entropy.
Sources of entropy:
- Windows: `RtlGenRandom <https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom>_`.
- Linux, Android: :man:`getrandom(2)` if available, or :man:`urandom(4)`
after reading from `/dev/random` once, or the `KERN_RANDOM`
: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>_`
- macOS, OpenBSD: `getentropy(2) <https://man.openbsd.org/getentropy.2>_`
if available, or `/dev/urandom` after reading from `/dev/random` once.
- AIX: `/dev/random`.
- IBM i: `/dev/urandom`.
- Other UNIX: `/dev/urandom` after reading from `/dev/random` once.
:returns: 0 on success, or an error code < 0 on failure. The contents of
`buf` is undefined after an error.
.. note::
When using the synchronous version, both `loop` and `req` parameters
are not used and can be set to `NULL`.
.. versionadded:: 1.33.0
.. c:function:: void uv_sleep(unsigned int msec)
Causes the calling thread to sleep for `msec` milliseconds.
.. versionadded:: 1.34.0

@ -1,138 +0,0 @@
.. _pipe:
:c:type:`uv_pipe_t` --- Pipe handle
===================================
Pipe handles provide an abstraction over streaming files on Unix (including
local domain sockets, pipes, and FIFOs) and named pipes on Windows.
:c:type:`uv_pipe_t` is a 'subclass' of :c:type:`uv_stream_t`.
Data types
----------
.. c:type:: uv_pipe_t
Pipe handle type.
Public members
^^^^^^^^^^^^^^
.. c:member:: int uv_pipe_t.ipc
Whether this pipe is suitable for handle passing between processes.
Only a connected pipe that will be passing the handles should have this flag
set, not the listening pipe that uv_accept is called on.
.. seealso:: The :c:type:`uv_stream_t` members also apply.
API
---
.. c:function:: int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc)
Initialize a pipe handle. The `ipc` argument is a boolean to indicate if
this pipe will be used for handle passing between processes (which may
change the bytes on the wire). Only a connected pipe that will be
passing the handles should have this flag set, not the listening pipe
that uv_accept is called on.
.. c:function:: int uv_pipe_open(uv_pipe_t* handle, uv_file file)
Open an existing file descriptor or HANDLE as a pipe.
.. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode.
.. note::
The passed file descriptor or HANDLE is not checked for its type, but
it's required that it represents a valid pipe.
.. c:function:: int uv_pipe_bind(uv_pipe_t* handle, const char* name)
Bind the pipe to a file path (Unix) or a name (Windows).
.. note::
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
92 and 108 bytes.
.. c:function:: void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb)
Connect to the Unix domain socket or the named pipe.
.. note::
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
92 and 108 bytes.
.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size)
Get the name of the Unix domain socket or the named pipe.
A preallocated buffer must be provided. The size parameter holds the length
of the buffer and it's set to the number of bytes written to the buffer on
output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and
len will contain the required size.
.. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
and the buffer is not null terminated.
.. c:function:: int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size)
Get the name of the Unix domain socket or the named pipe to which the handle
is connected.
A preallocated buffer must be provided. The size parameter holds the length
of the buffer and it's set to the number of bytes written to the buffer on
output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and
len will contain the required size.
.. versionadded:: 1.3.0
.. c:function:: void uv_pipe_pending_instances(uv_pipe_t* handle, int count)
Set the number of pending pipe instance handles when the pipe server is
waiting for connections.
.. note::
This setting applies to Windows only.
.. c:function:: int uv_pipe_pending_count(uv_pipe_t* handle)
.. c:function:: uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle)
Used to receive handles over IPC pipes.
First - call :c:func:`uv_pipe_pending_count`, if it's > 0 then initialize
a handle of the given `type`, returned by :c:func:`uv_pipe_pending_type`
and call ``uv_accept(pipe, handle)``.
.. seealso:: The :c:type:`uv_stream_t` API functions also apply.
.. c:function:: int uv_pipe_chmod(uv_pipe_t* handle, int flags)
Alters pipe permissions, allowing it to be accessed from processes run by
different users. Makes the pipe writable or readable by all users. Mode can
be ``UV_WRITABLE``, ``UV_READABLE`` or ``UV_WRITABLE | UV_READABLE``. This
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

@ -1,148 +0,0 @@
.. _poll:
:c:type:`uv_poll_t` --- Poll handle
===================================
Poll handles are used to watch file descriptors for readability,
writability and disconnection similar to the purpose of :man:`poll(2)`.
The purpose of poll handles is to enable integrating external libraries that
rely on the event loop to signal it about the socket status changes, like
c-ares or libssh2. Using uv_poll_t for any other purpose is not recommended;
:c:type:`uv_tcp_t`, :c:type:`uv_udp_t`, etc. provide an implementation that is faster and
more scalable than what can be achieved with :c:type:`uv_poll_t`, especially on
Windows.
It is possible that poll handles occasionally signal that a file descriptor is
readable or writable even when it isn't. The user should therefore always
be prepared to handle EAGAIN or equivalent when it attempts to read from or
write to the fd.
It is not okay to have multiple active poll handles for the same socket, this
can cause libuv to busyloop or otherwise malfunction.
The user should not close a file descriptor while it is being polled by an
active poll handle. This can cause the handle to report an error,
but it might also start polling another socket. However the fd can be safely
closed immediately after a call to :c:func:`uv_poll_stop` or :c:func:`uv_close`.
.. note::
On windows only sockets can be polled with poll handles. On Unix any file
descriptor that would be accepted by :man:`poll(2)` can be used.
.. note::
On AIX, watching for disconnection is not supported.
Data types
----------
.. c:type:: uv_poll_t
Poll handle type.
.. c:type:: void (*uv_poll_cb)(uv_poll_t* handle, int status, int events)
Type definition for callback passed to :c:func:`uv_poll_start`.
.. c:type:: uv_poll_event
Poll event types
::
enum uv_poll_event {
UV_READABLE = 1,
UV_WRITABLE = 2,
UV_DISCONNECT = 4,
UV_PRIORITIZED = 8
};
Public members
^^^^^^^^^^^^^^
N/A
.. seealso:: The :c:type:`uv_handle_t` members also apply.
API
---
.. c:function:: int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd)
Initialize the handle using a file descriptor.
.. versionchanged:: 1.2.2 the file descriptor is set to non-blocking mode.
.. c:function:: int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t socket)
Initialize the handle using a socket descriptor. On Unix this is identical
to :c:func:`uv_poll_init`. On windows it takes a SOCKET handle.
.. versionchanged:: 1.2.2 the socket is set to non-blocking mode.
.. 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.
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.
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
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.
.. 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.
.. 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.
.. 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.

@ -1,54 +0,0 @@
.. _prepare:
:c:type:`uv_prepare_t` --- Prepare handle
=========================================
Prepare handles will run the given callback once per loop iteration, right
before polling for i/o.
Data types
----------
.. c:type:: uv_prepare_t
Prepare handle type.
.. c:type:: void (*uv_prepare_cb)(uv_prepare_t* handle)
Type definition for callback passed to :c:func:`uv_prepare_start`.
Public members
^^^^^^^^^^^^^^
N/A
.. seealso:: The :c:type:`uv_handle_t` members also apply.
API
---
.. c:function:: int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare)
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. 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.

@ -1,251 +0,0 @@
.. _process:
:c:type:`uv_process_t` --- Process handle
=========================================
Process handles will spawn a new process and allow the user to control it and
establish communication channels with it using streams.
Data types
----------
.. c:type:: uv_process_t
Process handle type.
.. c:type:: uv_process_options_t
Options for spawning the process (passed to :c:func:`uv_spawn`.
::
typedef struct uv_process_options_s {
uv_exit_cb exit_cb;
const char* file;
char** args;
char** env;
const char* cwd;
unsigned int flags;
int stdio_count;
uv_stdio_container_t* stdio;
uv_uid_t uid;
uv_gid_t gid;
} uv_process_options_t;
.. c:type:: void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal)
Type definition for callback passed in :c:type:`uv_process_options_t` which
will indicate the exit status and the signal that caused the process to
terminate, if any.
.. c:type:: uv_process_flags
Flags to be set on the flags field of :c:type:`uv_process_options_t`.
::
enum uv_process_flags {
/*
* Set the child process' user id.
*/
UV_PROCESS_SETUID = (1 << 0),
/*
* Set the child process' group id.
*/
UV_PROCESS_SETGID = (1 << 1),
/*
* Do not wrap any arguments in quotes, or perform any other escaping, when
* converting the argument list into a command line string. This option is
* only meaningful on Windows systems. On Unix it is silently ignored.
*/
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),
/*
* Spawn the child process in a detached state - this will make it a process
* group leader, and will effectively enable the child to keep running after
* the parent exits. Note that the child process will still keep the
* parent's event loop alive unless the parent process calls uv_unref() on
* the child's process handle.
*/
UV_PROCESS_DETACHED = (1 << 3),
/*
* Hide the subprocess window that would normally be created. This option is
* only meaningful on Windows systems. On Unix it is silently ignored.
*/
UV_PROCESS_WINDOWS_HIDE = (1 << 4),
/*
* Hide the subprocess console window that would normally be created. This
* option is only meaningful on Windows systems. On Unix it is silently
* ignored.
*/
UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5),
/*
* Hide the subprocess GUI window that would normally be created. This
* option is only meaningful on Windows systems. On Unix it is silently
* ignored.
*/
UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)
};
.. c:type:: uv_stdio_container_t
Container for each stdio handle or fd passed to a child process.
::
typedef struct uv_stdio_container_s {
uv_stdio_flags flags;
union {
uv_stream_t* stream;
int fd;
} data;
} uv_stdio_container_t;
.. c:enum:: uv_stdio_flags
Flags specifying how a stdio should be transmitted to the child process.
::
typedef enum {
UV_IGNORE = 0x00,
UV_CREATE_PIPE = 0x01,
UV_INHERIT_FD = 0x02,
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,
/*
* 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:: 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_exit_cb uv_process_options_t.exit_cb
Callback called after the process exits.
.. c:member:: const char* uv_process_options_t.file
Path pointing to the program to be executed.
.. 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:: char** uv_process_options_t.env
Environment for the new process. If NULL the parents environment is used.
.. c:member:: const char* uv_process_options_t.cwd
Current working directory for the subprocess.
.. 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:: 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
the child process. The convention is that stdio[0] points to stdin,
fd 1 is used for stdout, and fd 2 is stderr.
.. note::
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_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.
.. note::
This is not supported on Windows, :c:func:`uv_spawn` will fail and set the error
to ``UV_ENOTSUP``.
.. c:member:: uv_stdio_flags uv_stdio_container_t.flags
Flags specifying how the stdio container should be passed to the child.
.. c:member:: union @0 uv_stdio_container_t.data
Union containing either the `stream` or `fd` to be passed on to the child
process.
API
---
.. c:function:: void uv_disable_stdio_inheritance(void)
Disables inheritance for file descriptors / handles that this process
inherited from its parent. The effect is that child processes spawned by
this process don't accidentally inherit these handles.
It is recommended to call this function as early in your program as possible,
before the inherited file descriptors can be closed or duplicated.
.. note::
This function works on a best-effort basis: there is no guarantee that libuv can discover
all file descriptors that were inherited. In general it does a better job on Windows than
it does on Unix.
.. c:function:: int uv_spawn(uv_loop_t* loop, uv_process_t* handle, const uv_process_options_t* options)
Initializes the process handle and starts the process. If the process is
successfully spawned, this function will return 0. Otherwise, the
negative error code corresponding to the reason it couldn't spawn is
returned.
Possible reasons for failing to spawn would include (but not be limited to)
the file to execute not existing, not having permissions to use the setuid or
setgid specified, or not having enough memory to allocate for the new
process.
.. versionchanged:: 1.24.0 Added `UV_PROCESS_WINDOWS_HIDE_CONSOLE` and
`UV_PROCESS_WINDOWS_HIDE_GUI` flags.
.. c:function:: int uv_process_kill(uv_process_t* handle, int signum)
Sends the specified signal to the given process handle. Check the documentation
on :c:ref:`signal` for signal support, specially on Windows.
.. c:function:: int uv_kill(int pid, int signum)
Sends the specified signal to the given PID. Check the documentation
on :c:ref:`signal` for signal support, specially on Windows.
.. c:function:: uv_pid_t uv_process_get_pid(const uv_process_t* handle)
Returns `handle->pid`.
.. versionadded:: 1.19.0
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.

@ -1,117 +0,0 @@
.. _request:
:c:type:`uv_req_t` --- Base request
===================================
`uv_req_t` is the base type for all libuv request types.
Structures are aligned so that any libuv request can be cast to `uv_req_t`.
All API functions defined here work with any request type.
Data types
----------
.. c:type:: uv_req_t
The base libuv request structure.
.. c:type:: uv_any_req
Union of all request types.
Public members
^^^^^^^^^^^^^^
.. c:member:: void* uv_req_t.data
Space for user-defined arbitrary data. libuv does not use this field.
.. c:member:: uv_req_type uv_req_t.type
Indicated the type of request. Readonly.
::
typedef enum {
UV_UNKNOWN_REQ = 0,
UV_REQ,
UV_CONNECT,
UV_WRITE,
UV_SHUTDOWN,
UV_UDP_SEND,
UV_FS,
UV_WORK,
UV_GETADDRINFO,
UV_GETNAMEINFO,
UV_REQ_TYPE_MAX,
} uv_req_type;
API
---
.. 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
arguments: the name of the `uv_req_type` element without the `UV_`
prefix, and the name of the corresponding structure type without the
`uv_` prefix and `_t` suffix.
.. c:function:: int uv_cancel(uv_req_t* req)
Cancel a pending request. Fails if the request is executing or has finished
executing.
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`, :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
callback is called.
Here is how cancellation is reported to the callback:
* 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`,
: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)
Returns the size of the given request type. Useful for FFI binding writers
who don't want to know the structure layout.
.. c:function:: void* uv_req_get_data(const uv_req_t* req)
Returns `req->data`.
.. versionadded:: 1.19.0
.. c:function:: void* uv_req_set_data(uv_req_t* req, void* data)
Sets `req->data` to `data`.
.. versionadded:: 1.19.0
.. c:function:: uv_req_type uv_req_get_type(const uv_req_t* req)
Returns `req->type`.
.. versionadded:: 1.19.0
.. c:function:: const char* uv_req_type_name(uv_req_type type)
Returns the name for the equivalent struct for a given request type,
e.g. `"connect"` (as in :c:type:`uv_connect_t`) for `UV_CONNECT`.
If no such request type exists, this returns `NULL`.
.. versionadded:: 1.19.0

@ -1,101 +0,0 @@
.. _signal:
:c:type:`uv_signal_t` --- Signal handle
=======================================
Signal handles implement Unix style signal handling on a per-event loop bases.
Windows notes
-------------
Reception of some signals is emulated:
* SIGINT is normally delivered when the user presses CTRL+C. However, like
on Unix, it is not generated when terminal raw mode is enabled.
* SIGBREAK is delivered when the user pressed CTRL + BREAK.
* SIGHUP is generated when the user closes the console window. On SIGHUP the
program is given approximately 10 seconds to perform cleanup. After that
Windows will unconditionally terminate it.
* SIGWINCH is raised whenever libuv detects that the console has been
resized. When a libuv app is running under a console emulator, or when a
32-bit libuv app is running on 64-bit system, SIGWINCH will be emulated. In
such cases SIGWINCH signals may not always be delivered in a timely manner.
For a writable :c:type:`uv_tty_t` handle libuv will only detect size changes
when the cursor is moved. When a readable :c:type:`uv_tty_t` handle is used,
resizing of the console buffer will be detected only if the handle is in raw
mode and is being read.
* Watchers for other signals can be successfully created, but these signals
are never received. These signals are: `SIGILL`, `SIGABRT`, `SIGFPE`, `SIGSEGV`,
`SIGTERM` and `SIGKILL.`
* Calls to raise() or abort() to programmatically raise a signal are
not detected by libuv; these will not trigger a signal watcher.
.. versionchanged:: 1.15.0 SIGWINCH support on Windows was improved.
.. versionchanged:: 1.31.0 32-bit libuv SIGWINCH support on 64-bit Windows was
rolled back to old implementation.
Unix notes
----------
* SIGKILL and SIGSTOP are impossible to catch.
* Handling SIGBUS, SIGFPE, SIGILL or SIGSEGV via libuv results into undefined behavior.
* SIGABRT will not be caught by libuv if generated by `abort()`, e.g. through `assert()`.
* On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads library to
manage threads. Installing watchers for those signals will lead to unpredictable behavior
and is strongly discouraged. Future versions of libuv may simply reject them.
Data types
----------
.. c:type:: uv_signal_t
Signal handle type.
.. c:type:: void (*uv_signal_cb)(uv_signal_t* handle, int signum)
Type definition for callback passed to :c:func:`uv_signal_start`.
Public members
^^^^^^^^^^^^^^
.. c:member:: int uv_signal_t.signum
Signal being monitored by this handle. Readonly.
.. seealso:: The :c:type:`uv_handle_t` members also apply.
API
---
.. c:function:: int uv_signal_init(uv_loop_t* loop, uv_signal_t* signal)
Initialize the handle.
.. c:function:: int uv_signal_start(uv_signal_t* signal, uv_signal_cb cb, int signum)
Start the handle with the given callback, watching for the given signal.
.. c:function:: int uv_signal_start_oneshot(uv_signal_t* signal, uv_signal_cb cb, int signum)
.. versionadded:: 1.12.0
Same functionality as :c:func:`uv_signal_start` but the signal handler is reset the moment
the signal is received.
.. c:function:: int uv_signal_stop(uv_signal_t* signal)
Stop the handle, the callback will no longer be called.
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.

@ -1,45 +0,0 @@
# encoding: utf-8
#
# Copyright (c) 2013 Dariusz Dwornikowski. All rights reserved.
#
# Adapted from https://github.com/tdi/sphinxcontrib-manpage
# License: Apache 2
#
import re
from docutils import nodes, utils
from docutils.parsers.rst.roles import set_classes
from string import Template
def make_link_node(rawtext, app, name, manpage_num, options):
ref = app.config.man_url_regex
if not ref:
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)
set_classes(options)
node = nodes.reference(rawtext, "%s(%s)" % (name, manpage_num), refuri=ref, **options)
return node
def man_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
app = inliner.document.settings.env.app
p = re.compile("([a-zA-Z0-9_\.-_]+)\((\d)\)")
m = p.match(text)
manpage_num = m.group(2)
name = m.group(1)
node = make_link_node(rawtext, app, name, manpage_num, options)
return [node], []
def setup(app):
app.add_role('man', man_role)
app.add_config_value('man_url_regex', None, 'env')
return

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>Template: White (2014-02-28 09:41)</string>
<string>M6.2.2-1878-1</string>
</array>
</plist>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

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

Loading…
Cancel
Save