mirror of https://github.com/nodejs/node.git
deps: upgrade libuv to 1.7.3
PR-URL: https://github.com/nodejs/node/pull/2310 Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: cjihrig - Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
parent
e3740e4524
commit
a1615949a5
|
@ -200,3 +200,22 @@ 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 <riclau@uk.ibm.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>
|
||||
|
|
|
@ -1,3 +1,163 @@
|
|||
2015.08.28, Version 1.7.3 (Stable), 93877b11c8b86e0a6befcda83a54555c1e36e4f0
|
||||
|
||||
Changes since version 1.7.2:
|
||||
|
||||
* threadpool: fix thread starvation bug (Ben Noordhuis)
|
||||
|
||||
|
||||
2015.08.25, Version 1.7.2 (Stable), 4d13a013fcfa72311f0102751fdc7951873f466c
|
||||
|
||||
Changes since version 1.7.1:
|
||||
|
||||
* unix, win: make uv_loop_init return on error (Willem Thiart)
|
||||
|
||||
* win: reset pipe handle for pipe servers (Saúl Ibarra Corretgé)
|
||||
|
||||
* win: fix replacing pipe handle for pipe servers (Saúl Ibarra Corretgé)
|
||||
|
||||
* win: fix setting pipe pending instances after bind (Saúl Ibarra Corretgé)
|
||||
|
||||
|
||||
2015.08.20, Version 1.7.1 (Stable), 44f4b6bd82d8ae4583ccc4768a83af778ef69f85
|
||||
|
||||
Changes since version 1.7.0:
|
||||
|
||||
* doc: document the procedure for verifying releases (Saúl Ibarra Corretgé)
|
||||
|
||||
* doc: add note about Windows binaries to the README (Saúl Ibarra Corretgé)
|
||||
|
||||
* doc: use long GPG IDs in MAINTAINERS.md (Saúl Ibarra Corretgé)
|
||||
|
||||
* Revert "stream: squelch ECONNRESET error if already closed" (Saúl Ibarra
|
||||
Corretgé)
|
||||
|
||||
* doc: clarify uv_read_stop() is idempotent (Corbin Simpson)
|
||||
|
||||
* unix: OpenBSD's setsockopt needs an unsigned char for multicast (Zachary
|
||||
Hamm)
|
||||
|
||||
* test: Fix two memory leaks (Karl Skomski)
|
||||
|
||||
* unix,win: return EINVAL on nullptr args in uv_fs_{read,write} (Karl Skomski)
|
||||
|
||||
* win: set accepted TCP sockets as non-inheritable (Saúl Ibarra Corretgé)
|
||||
|
||||
* unix: remove superfluous parentheses in fs macros (Ben Noordhuis)
|
||||
|
||||
* unix: don't copy arguments for sync fs requests (Ben Noordhuis)
|
||||
|
||||
* test: plug small memory leak in unix test runner (Ben Noordhuis)
|
||||
|
||||
* unix,windows: allow NULL loop for sync fs requests (Ben Noordhuis)
|
||||
|
||||
* unix,windows: don't assert on unknown error code (Ben Noordhuis)
|
||||
|
||||
* stream: retry write on EPROTOTYPE on OSX (Brian White)
|
||||
|
||||
* common: fix use of snprintf on Windows (Saúl Ibarra Corretgé)
|
||||
|
||||
* tests: refactored fs watch_dir tests for stability (Jeremy Whitlock)
|
||||
|
||||
|
||||
2015.08.06, Version 1.7.0 (Stable), 415a865d6365ba58d02b92b89d46ba5d7744ec8b
|
||||
|
||||
Changes since version 1.6.1:
|
||||
|
||||
* win,stream: add slot to remember CRT fd (Bert Belder)
|
||||
|
||||
* win,pipe: properly close when created from CRT fd (Bert Belder)
|
||||
|
||||
* win,pipe: don't close fd 0-2 (Bert Belder)
|
||||
|
||||
* win,tty: convert fd -> handle safely (Bert Belder)
|
||||
|
||||
* win,tty: properly close when created from CRT fd (Bert Belder)
|
||||
|
||||
* win,tty: don't close fd 0-2 (Bert Belder)
|
||||
|
||||
* win,fs: don't close fd 0-2 (Bert Belder)
|
||||
|
||||
* win: include "malloc.h" (Cheng Zhao)
|
||||
|
||||
* windows: MSVC 2015 has C99 inline (Jason Williams)
|
||||
|
||||
* dragonflybsd: fixes for nonblocking and cloexec (Michael Neumann)
|
||||
|
||||
* dragonflybsd: use sendfile(2) for uv_fs_sendfile (Michael Neumann)
|
||||
|
||||
* dragonflybsd: fix uv_exepath (Michael Neumann)
|
||||
|
||||
* win,fs: Fixes align(8) directive on mingw (Stefano Cristiano)
|
||||
|
||||
* unix, win: prevent replacing fd in uv_{udp,tcp,pipe}_t (Saúl Ibarra Corretgé)
|
||||
|
||||
* win: move logic to set socket non-inheritable to uv_tcp_set_socket (Saúl
|
||||
Ibarra Corretgé)
|
||||
|
||||
* unix, win: add ability to create tcp/udp sockets early (Saúl Ibarra Corretgé)
|
||||
|
||||
* test: retry select() on EINTR, honor milliseconds (Ben Noordhuis)
|
||||
|
||||
* unix: consolidate tcp and udp bind error (Saúl Ibarra Corretgé)
|
||||
|
||||
* test: conditionally skip udp_ipv6_multicast_join6 (heshamsafi)
|
||||
|
||||
* core: add UV_VERSION_HEX macro (Saúl Ibarra Corretgé)
|
||||
|
||||
* doc: add section with version-checking macros and functions (Saúl Ibarra
|
||||
Corretgé)
|
||||
|
||||
* tty: cleanup handle if uv_tty_init fails (Saúl Ibarra Corretgé)
|
||||
|
||||
* darwin: save a fd when FSEvents is used (Saúl Ibarra Corretgé)
|
||||
|
||||
* win: fix returning thread id in uv_thread_self (Saúl Ibarra Corretgé)
|
||||
|
||||
* common: use offsetof for QUEUE_DATA (Saúl Ibarra Corretgé)
|
||||
|
||||
* win: remove UV_HANDLE_CONNECTED (A. Hauptmann)
|
||||
|
||||
* docs: add Windows specific note for uv_fs_open (Saúl Ibarra Corretgé)
|
||||
|
||||
* doc: add note about uv_fs_scandir (Saúl Ibarra Corretgé)
|
||||
|
||||
* test,unix: reduce stack size of watchdog threads (Ben Noordhuis)
|
||||
|
||||
* win: add support for recursive file watching (Saúl Ibarra Corretgé)
|
||||
|
||||
* win,tty: support consoles with non-default colors (John McNamee)
|
||||
|
||||
* doc: add missing variable name (Yosuke Furukawa)
|
||||
|
||||
* stream: squelch ECONNRESET error if already closed (Santiago Gimeno)
|
||||
|
||||
* build: remove ancient condition from common.gypi (Saúl Ibarra Corretgé)
|
||||
|
||||
* tests: skip some tests when network is unreachable (Luca Bruno)
|
||||
|
||||
* build: proper support for android cross compilation (guworks)
|
||||
|
||||
* android: add missing include to pthread-fixes.c (RossBencina)
|
||||
|
||||
* test: fix compilation warning (Saúl Ibarra Corretgé)
|
||||
|
||||
* doc: add a note about uv_dirent_t.type (Saúl Ibarra Corretgé)
|
||||
|
||||
* win,test: fix shared library build (Saúl Ibarra Corretgé)
|
||||
|
||||
* test: fix compilation warning (Santiago Gimeno)
|
||||
|
||||
* build: add experimental Windows installer (Roger A. Light)
|
||||
|
||||
* threadpool: send signal only when queue is empty (chenttuuvv)
|
||||
|
||||
* aix: fix uv_exepath with relative paths (Richard Lau)
|
||||
|
||||
* build: fix version syntax in AppVeyor file (Saúl Ibarra Corretgé)
|
||||
|
||||
* unix: allow nbufs > IOV_MAX in uv_fs_{read,write} (ronkorving)
|
||||
|
||||
|
||||
2015.06.06, Version 1.6.1 (Stable), 30c8be07bb78a66fdee5141626bf53a49a17094a
|
||||
|
||||
Changes since version 1.6.0:
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
# Project Maintainers
|
||||
|
||||
libuv is currently managed by the following individuals:
|
||||
|
||||
* **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))
|
||||
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
|
||||
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
|
||||
* **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
|
||||
|
|
@ -186,8 +186,10 @@ test_run_tests_SOURCES = test/blackhole-server.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 \
|
||||
|
@ -215,6 +217,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
|||
test/test-tcp-close-accept.c \
|
||||
test/test-tcp-close-while-connecting.c \
|
||||
test/test-tcp-close.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 \
|
||||
|
@ -240,6 +243,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
|||
test/test-timer.c \
|
||||
test/test-tty.c \
|
||||
test/test-udp-bind.c \
|
||||
test/test-udp-create-socket-early.c \
|
||||
test/test-udp-dgram-too-big.c \
|
||||
test/test-udp-ipv6.c \
|
||||
test/test-udp-multicast-interface.c \
|
||||
|
|
|
@ -89,6 +89,42 @@ also serve as API specification and usage examples.
|
|||
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/).
|
||||
|
||||
Starting with libuv 1.7.0, binaries for Windows are also provided. This is to
|
||||
be considered EXPERIMENTAL.
|
||||
|
||||
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:
|
||||
|
||||
$ gpg --keyserver pool.sks-keyservers.net \
|
||||
--recv-keys AE9BC059
|
||||
|
||||
Importing a key from a git blob object:
|
||||
|
||||
$ git show pubkey-saghul | gpg --import
|
||||
|
||||
### Verifying releases
|
||||
|
||||
Git tags are signed with the developer's key, they can be verified as follows:
|
||||
|
||||
$ 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 accomanying
|
||||
signature file sit alongside each. Once both the release tarball and the
|
||||
signature file are downloaded, the file can be verified as follows:
|
||||
|
||||
$ gpg --verify libuv-1.7.0.tar.gz.sign
|
||||
|
||||
## Build Instructions
|
||||
|
||||
For GCC there are two build methods: via autotools or via [GYP][].
|
||||
|
|
|
@ -6,7 +6,7 @@ $1/build/tools/make-standalone-toolchain.sh \
|
|||
--toolchain=arm-linux-androideabi-4.8 \
|
||||
--arch=arm \
|
||||
--install-dir=$TOOLCHAIN \
|
||||
--platform=android-9
|
||||
--platform=android-21
|
||||
export PATH=$TOOLCHAIN/bin:$PATH
|
||||
export AR=arm-linux-androideabi-ar
|
||||
export CC=arm-linux-androideabi-gcc
|
||||
|
@ -16,5 +16,5 @@ export PLATFORM=android
|
|||
|
||||
if [ $2 -a $2 == 'gyp' ]
|
||||
then
|
||||
./gyp_uv.py -Dtarget_arch=arm -DOS=android
|
||||
./gyp_uv.py -Dtarget_arch=arm -DOS=android -f make-android
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
version: v1.7.3.build{build}
|
||||
|
||||
install:
|
||||
- cinst -y nsis
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- platform: x86
|
||||
configuration: Release
|
||||
- platform: x64
|
||||
configuration: Release
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
||||
build_script:
|
||||
# Fixed tag version number if using a tag.
|
||||
- cmd: if "%APPVEYOR_REPO_TAG%" == "true" set APPVEYOR_BUILD_VERSION=%APPVEYOR_REPO_TAG_NAME%
|
||||
# vcbuild overwrites the platform variable.
|
||||
- cmd: set ARCH=%platform%
|
||||
- cmd: vcbuild.bat release %ARCH% shared
|
||||
|
||||
after_build:
|
||||
- '"%PROGRAMFILES(x86)%\NSIS\makensis" /DVERSION=%APPVEYOR_BUILD_VERSION% /DARCH=%ARCH% libuv.nsi'
|
||||
|
||||
artifacts:
|
||||
- name: Installer
|
||||
path: 'libuv-*.exe'
|
||||
|
||||
cache:
|
||||
- C:\projects\libuv\build\gyp
|
|
@ -37,9 +37,10 @@
|
|||
'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ],
|
||||
},
|
||||
'conditions': [
|
||||
['OS != "win"', {
|
||||
'defines': [ 'EV_VERIFY=2' ],
|
||||
}],
|
||||
['OS == "android"', {
|
||||
'cflags': [ '-fPIE' ],
|
||||
'ldflags': [ '-fPIE', '-pie' ]
|
||||
}]
|
||||
]
|
||||
},
|
||||
'Release': {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([libuv], [1.6.1], [https://github.com/libuv/libuv/issues])
|
||||
AC_INIT([libuv], [1.7.3], [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])
|
||||
|
|
|
@ -31,7 +31,7 @@ N/A
|
|||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_check_init(uv_loop_t*, uv_check_t* check)
|
||||
.. c:function:: int uv_check_init(uv_loop_t* loop, uv_check_t* check)
|
||||
|
||||
Initialize the handle.
|
||||
|
||||
|
|
|
@ -322,8 +322,10 @@ API
|
|||
|
||||
.. c:function:: const char* uv_strerror(int err)
|
||||
|
||||
Returns the error message for the given error code.
|
||||
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:: const char* uv_err_name(int err)
|
||||
|
||||
Returns the error name for the given error code.
|
||||
Returns the error name for the given error code. Leaks a few bytes
|
||||
of memory when you call it with an unknown error code.
|
||||
|
|
|
@ -168,6 +168,11 @@ API
|
|||
|
||||
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)`.
|
||||
|
@ -206,6 +211,13 @@ API
|
|||
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 filesystems (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)
|
||||
|
|
|
@ -88,7 +88,7 @@ API
|
|||
`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.
|
||||
only on OSX and Windows.
|
||||
|
||||
.. c:function:: int uv_fs_event_stop(uv_fs_event_t* handle)
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ N/A
|
|||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_idle_init(uv_loop_t*, uv_idle_t* idle)
|
||||
.. c:function:: int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle)
|
||||
|
||||
Initialize the handle.
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ Documentation
|
|||
|
||||
design
|
||||
errors
|
||||
version
|
||||
loop
|
||||
handle
|
||||
request
|
||||
|
|
|
@ -135,17 +135,6 @@ API
|
|||
For :man:`isatty(3)` equivalent functionality use this function and test
|
||||
for ``UV_TTY``.
|
||||
|
||||
.. c:function:: unsigned int uv_version(void)
|
||||
|
||||
Returns the libuv version packed into a single integer. 8 bits are used for
|
||||
each component, with the patch number stored in the 8 least significant
|
||||
bits. E.g. for libuv 1.2.3 this would return 0x010203.
|
||||
|
||||
.. c:function:: const char* uv_version_string(void)
|
||||
|
||||
Returns the libuv version number as a string. For non-release versions
|
||||
"-pre" is appended, so the version number could be "1.2.3-pre".
|
||||
|
||||
.. 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
|
||||
|
|
|
@ -29,12 +29,12 @@ N/A
|
|||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc)
|
||||
.. 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.
|
||||
|
||||
.. c:function:: int uv_pipe_open(uv_pipe_t*, uv_file file)
|
||||
.. c:function:: int uv_pipe_open(uv_pipe_t* handle, uv_file file)
|
||||
|
||||
Open an existing file descriptor or HANDLE as a pipe.
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ Public members
|
|||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_signal_init(uv_loop_t*, uv_signal_t* signal)
|
||||
.. c:function:: int uv_signal_init(uv_loop_t* loop, uv_signal_t* signal)
|
||||
|
||||
Initialize the handle.
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ API
|
|||
.. note::
|
||||
`server` and `client` must be handles running on the same loop.
|
||||
|
||||
.. c:function:: int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
|
||||
.. c:function:: int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
|
||||
|
||||
Read data from an incoming stream. The callback will be made several
|
||||
times until there is no more data to read or :c:func:`uv_read_stop` is called.
|
||||
|
@ -142,6 +142,8 @@ API
|
|||
Stop reading data from the stream. The :c:type:`uv_read_cb` callback will
|
||||
no longer be called.
|
||||
|
||||
This function is idempotent and may be safely called on a stopped stream.
|
||||
|
||||
.. c:function:: int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb)
|
||||
|
||||
Write data to stream. Buffers are written in order. Example:
|
||||
|
|
|
@ -28,9 +28,18 @@ N/A
|
|||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle)
|
||||
.. c:function:: int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle)
|
||||
|
||||
Initialize the handle.
|
||||
Initialize the handle. No socket is created as of yet.
|
||||
|
||||
.. c:function:: int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags)
|
||||
|
||||
Initialize the handle with the specified flags. At the moment the lower 8 bits
|
||||
of the `flags` parameter are used as the socket domain. A socket will be created
|
||||
for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created,
|
||||
just like :c:func:`uv_tcp_init`.
|
||||
|
||||
.. versionadded:: 1.7.0
|
||||
|
||||
.. c:function:: int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock)
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ N/A
|
|||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable)
|
||||
.. c:function:: int uv_tty_init(uv_loop_t* loop, uv_tty_t* handle, uv_file fd, int readable)
|
||||
|
||||
Initialize a new TTY stream with the given file descriptor. Usually the
|
||||
file descriptor will be:
|
||||
|
@ -70,7 +70,7 @@ API
|
|||
descriptor that refers to a file returns `UV_EINVAL`
|
||||
on UNIX.
|
||||
|
||||
.. c:function:: int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode)
|
||||
.. c:function:: int uv_tty_set_mode(uv_tty_t* handle, uv_tty_mode_t mode)
|
||||
|
||||
.. versionchanged:: 1.2.0: the mode is specified as a
|
||||
:c:type:`uv_tty_mode_t` value.
|
||||
|
@ -86,7 +86,7 @@ API
|
|||
code ``UV_EBUSY`` if you call it when execution is inside
|
||||
:c:func:`uv_tty_set_mode`.
|
||||
|
||||
.. c:function:: int uv_tty_get_winsize(uv_tty_t*, int* width, int* height)
|
||||
.. c:function:: int uv_tty_get_winsize(uv_tty_t* handle, int* width, int* height)
|
||||
|
||||
Gets the current Window size. On success it returns 0.
|
||||
|
||||
|
|
|
@ -105,11 +105,20 @@ Public members
|
|||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_udp_init(uv_loop_t*, uv_udp_t* handle)
|
||||
.. c:function:: int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle)
|
||||
|
||||
Initialize a new UDP handle. The actual socket is created lazily.
|
||||
Returns 0 on success.
|
||||
|
||||
.. c:function:: int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags)
|
||||
|
||||
Initialize the handle with the specified flags. At the moment the lower 8 bits
|
||||
of the `flags` parameter are used as the socket domain. A socket will be created
|
||||
for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created,
|
||||
just like :c:func:`uv_udp_init`.
|
||||
|
||||
.. versionadded:: 1.7.0
|
||||
|
||||
.. c:function:: int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock)
|
||||
|
||||
Opens an existing file descriptor or Windows SOCKET as a UDP handle.
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
.. _version:
|
||||
|
||||
Version-checking macros and functions
|
||||
=====================================
|
||||
|
||||
Starting with version 1.0.0 libuv follows the `semantic versioning`_
|
||||
scheme. This means that new APIs can be introduced throughout the lifetime of
|
||||
a major release. In this section you'll find all macros and functions that
|
||||
will allow you to write or compile code conditionally, in order to work with
|
||||
multiple libuv versions.
|
||||
|
||||
.. _semantic versioning: http://semver.org
|
||||
|
||||
|
||||
Macros
|
||||
------
|
||||
|
||||
.. c:macro:: UV_VERSION_MAJOR
|
||||
|
||||
libuv version's major number.
|
||||
|
||||
.. c:macro:: UV_VERSION_MINOR
|
||||
|
||||
libuv version's minor number.
|
||||
|
||||
.. c:macro:: UV_VERSION_PATCH
|
||||
|
||||
libuv version's patch number.
|
||||
|
||||
.. c:macro:: UV_VERSION_IS_RELEASE
|
||||
|
||||
Set to 1 to indicate a release version of libuv, 0 for a development
|
||||
snapshot.
|
||||
|
||||
.. c:macro:: UV_VERSION_SUFFIX
|
||||
|
||||
libuv version suffix. Certain development releases such as Release Candidates
|
||||
might have a suffix such as "rc".
|
||||
|
||||
.. c:macro:: UV_VERSION_HEX
|
||||
|
||||
Returns the libuv version packed into a single integer. 8 bits are used for
|
||||
each component, with the patch number stored in the 8 least significant
|
||||
bits. E.g. for libuv 1.2.3 this would be 0x010203.
|
||||
|
||||
.. versionadded:: 1.7.0
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. c:function:: unsigned int uv_version(void)
|
||||
|
||||
Returns :c:macro:`UV_VERSION_HEX`.
|
||||
|
||||
.. c:function:: const char* uv_version_string(void)
|
||||
|
||||
Returns the libuv version number as a string. For non-release versions the
|
||||
version suffix is included.
|
|
@ -31,9 +31,13 @@
|
|||
*/
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 6
|
||||
#define UV_VERSION_PATCH 1
|
||||
#define UV_VERSION_MINOR 7
|
||||
#define UV_VERSION_PATCH 3
|
||||
#define UV_VERSION_IS_RELEASE 1
|
||||
#define UV_VERSION_SUFFIX ""
|
||||
|
||||
#define UV_VERSION_HEX ((UV_VERSION_MAJOR << 16) | \
|
||||
(UV_VERSION_MINOR << 8) | \
|
||||
(UV_VERSION_PATCH))
|
||||
|
||||
#endif /* UV_VERSION_H */
|
||||
|
|
|
@ -406,7 +406,10 @@ struct uv_shutdown_s {
|
|||
/* private */ \
|
||||
uv_close_cb close_cb; \
|
||||
void* handle_queue[2]; \
|
||||
void* reserved[4]; \
|
||||
union { \
|
||||
int fd; \
|
||||
void* reserved[4]; \
|
||||
} u; \
|
||||
UV_HANDLE_PRIVATE_FIELDS \
|
||||
|
||||
/* The abstract base class of all handles. */
|
||||
|
@ -504,6 +507,7 @@ struct uv_tcp_s {
|
|||
};
|
||||
|
||||
UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle);
|
||||
UV_EXTERN int uv_tcp_init_ex(uv_loop_t*, uv_tcp_t* handle, unsigned int flags);
|
||||
UV_EXTERN int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock);
|
||||
UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
|
||||
UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
|
||||
|
@ -594,6 +598,7 @@ struct uv_udp_send_s {
|
|||
};
|
||||
|
||||
UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
|
||||
UV_EXTERN int uv_udp_init_ex(uv_loop_t*, uv_udp_t* handle, unsigned int flags);
|
||||
UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
|
||||
UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
|
||||
const struct sockaddr* addr,
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
; NSIS installer script for libuv
|
||||
|
||||
!include "MUI2.nsh"
|
||||
|
||||
Name "libuv"
|
||||
OutFile "libuv-${ARCH}-${VERSION}.exe"
|
||||
|
||||
!include "x64.nsh"
|
||||
# Default install location, for 32-bit files
|
||||
InstallDir "$PROGRAMFILES\libuv"
|
||||
|
||||
# Override install and registry locations if this is a 64-bit install.
|
||||
function .onInit
|
||||
${If} ${ARCH} == "x64"
|
||||
SetRegView 64
|
||||
StrCpy $INSTDIR "$PROGRAMFILES64\libuv"
|
||||
${EndIf}
|
||||
functionEnd
|
||||
|
||||
;--------------------------------
|
||||
; Installer pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
|
||||
;--------------------------------
|
||||
; Uninstaller pages
|
||||
!insertmacro MUI_UNPAGE_WELCOME
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
;--------------------------------
|
||||
; Languages
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
|
||||
;--------------------------------
|
||||
; Installer sections
|
||||
|
||||
Section "Files" SecInstall
|
||||
SectionIn RO
|
||||
SetOutPath "$INSTDIR"
|
||||
File "Release\*.dll"
|
||||
File "Release\*.lib"
|
||||
File "LICENSE"
|
||||
File "README.md"
|
||||
|
||||
SetOutPath "$INSTDIR\include"
|
||||
File "include\uv.h"
|
||||
File "include\uv-errno.h"
|
||||
File "include\uv-threadpool.h"
|
||||
File "include\uv-version.h"
|
||||
File "include\uv-win.h"
|
||||
File "include\tree.h"
|
||||
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "DisplayName" "libuv-${ARCH}-${VERSION}"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "HelpLink" "http://libuv.org/"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "URLInfoAbout" "http://libuv.org/"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "DisplayVersion" "${VERSION}"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "NoModify" "1"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "NoRepair" "1"
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
Delete "$INSTDIR\libuv.dll"
|
||||
Delete "$INSTDIR\libuv.lib"
|
||||
Delete "$INSTDIR\LICENSE"
|
||||
Delete "$INSTDIR\README.md"
|
||||
|
||||
Delete "$INSTDIR\include\uv.h"
|
||||
Delete "$INSTDIR\include\uv-errno.h"
|
||||
Delete "$INSTDIR\include\uv-threadpool.h"
|
||||
Delete "$INSTDIR\include\uv-version.h"
|
||||
Delete "$INSTDIR\include\uv-win.h"
|
||||
Delete "$INSTDIR\include\tree.h"
|
||||
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
RMDir "$INSTDIR"
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}"
|
||||
SectionEnd
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
#ifndef QUEUE_H_
|
||||
#define QUEUE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef void *QUEUE[2];
|
||||
|
||||
/* Private macros. */
|
||||
|
@ -26,7 +28,7 @@ typedef void *QUEUE[2];
|
|||
|
||||
/* Public macros. */
|
||||
#define QUEUE_DATA(ptr, type, field) \
|
||||
((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field)))
|
||||
((type *) ((char *) (ptr) - offsetof(type, field)))
|
||||
|
||||
#define QUEUE_FOREACH(q, h) \
|
||||
for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
|
||||
|
|
|
@ -44,6 +44,7 @@ static void uv__req_init(uv_loop_t* loop,
|
|||
static uv_once_t once = UV_ONCE_INIT;
|
||||
static uv_cond_t cond;
|
||||
static uv_mutex_t mutex;
|
||||
static unsigned int idle_threads;
|
||||
static unsigned int nthreads;
|
||||
static uv_thread_t* threads;
|
||||
static uv_thread_t default_threads[4];
|
||||
|
@ -69,8 +70,11 @@ static void worker(void* arg) {
|
|||
for (;;) {
|
||||
uv_mutex_lock(&mutex);
|
||||
|
||||
while (QUEUE_EMPTY(&wq))
|
||||
while (QUEUE_EMPTY(&wq)) {
|
||||
idle_threads += 1;
|
||||
uv_cond_wait(&cond, &mutex);
|
||||
idle_threads -= 1;
|
||||
}
|
||||
|
||||
q = QUEUE_HEAD(&wq);
|
||||
|
||||
|
@ -103,7 +107,8 @@ static void worker(void* arg) {
|
|||
static void post(QUEUE* q) {
|
||||
uv_mutex_lock(&mutex);
|
||||
QUEUE_INSERT_TAIL(&wq, q);
|
||||
uv_cond_signal(&cond);
|
||||
if (idle_threads > 0)
|
||||
uv_cond_signal(&cond);
|
||||
uv_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include <sys/protosw.h>
|
||||
#include <libperfstat.h>
|
||||
#include <procinfo.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
|
@ -288,182 +289,80 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
|
|||
* and use it in conjunction with PATH environment variable to craft one.
|
||||
*/
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
ssize_t res;
|
||||
char cwd[PATH_MAX], cwdl[PATH_MAX];
|
||||
char symlink[PATH_MAX], temp_buffer[PATH_MAX];
|
||||
char pp[64];
|
||||
struct psinfo ps;
|
||||
int fd;
|
||||
char **argv;
|
||||
int res;
|
||||
char args[PATH_MAX];
|
||||
char abspath[PATH_MAX];
|
||||
size_t abspath_size;
|
||||
struct procsinfo pi;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
|
||||
|
||||
fd = open(pp, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
res = read(fd, &ps, sizeof(ps));
|
||||
uv__close(fd);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
if (ps.pr_argv == 0)
|
||||
return -EINVAL;
|
||||
|
||||
argv = (char **) *((char ***) (intptr_t) ps.pr_argv);
|
||||
|
||||
if ((argv == NULL) || (argv[0] == NULL))
|
||||
pi.pi_pid = getpid();
|
||||
res = getargs(&pi, sizeof(pi), args, sizeof(args));
|
||||
if (res < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Three possibilities for argv[0]:
|
||||
* Possibilities for args:
|
||||
* i) an absolute path such as: /home/user/myprojects/nodejs/node
|
||||
* ii) a relative path such as: ./node or ./myprojects/nodejs/node
|
||||
* ii) a relative path such as: ./node or ../myprojects/nodejs/node
|
||||
* iii) a bare filename such as "node", after exporting PATH variable
|
||||
* to its location.
|
||||
*/
|
||||
|
||||
/* case #1, absolute path. */
|
||||
if (argv[0][0] == '/') {
|
||||
snprintf(symlink, PATH_MAX-1, "%s", argv[0]);
|
||||
|
||||
/* This could or could not be a symlink. */
|
||||
res = readlink(symlink, temp_buffer, PATH_MAX-1);
|
||||
|
||||
/* if readlink fails, it is a normal file just copy symlink to the
|
||||
* output buffer.
|
||||
*/
|
||||
if (res < 0) {
|
||||
assert(*size > strlen(symlink));
|
||||
strcpy(buffer, symlink);
|
||||
|
||||
/* If it is a link, the resolved filename is again a relative path,
|
||||
* make it absolute.
|
||||
*/
|
||||
} else {
|
||||
assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
|
||||
snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
|
||||
}
|
||||
*size = strlen(buffer);
|
||||
return 0;
|
||||
|
||||
/* case #2, relative path with usage of '.' */
|
||||
} else if (argv[0][0] == '.') {
|
||||
char *relative = strchr(argv[0], '/');
|
||||
if (relative == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get the current working directory to resolve the relative path. */
|
||||
snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
|
||||
|
||||
/* This is always a symlink, resolve it. */
|
||||
res = readlink(cwd, cwdl, sizeof(cwdl) - 1);
|
||||
if (res < 0)
|
||||
/* Case i) and ii) absolute or relative paths */
|
||||
if (strchr(args, '/') != NULL) {
|
||||
if (realpath(args, abspath) != abspath)
|
||||
return -errno;
|
||||
|
||||
snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, relative + 1);
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
res = readlink(symlink, temp_buffer, PATH_MAX-1);
|
||||
if (res < 0) {
|
||||
assert(*size > strlen(symlink));
|
||||
strcpy(buffer, symlink);
|
||||
} else {
|
||||
assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
|
||||
snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
|
||||
}
|
||||
*size = strlen(buffer);
|
||||
return 0;
|
||||
|
||||
/* case #3, relative path without usage of '.', such as invocations in Node test suite. */
|
||||
} else if (strchr(argv[0], '/') != NULL) {
|
||||
/* Get the current working directory to resolve the relative path. */
|
||||
snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
|
||||
|
||||
/* This is always a symlink, resolve it. */
|
||||
res = readlink(cwd, cwdl, sizeof(cwdl) - 1);
|
||||
if (res < 0)
|
||||
return -errno;
|
||||
|
||||
snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, argv[0]);
|
||||
|
||||
res = readlink(symlink, temp_buffer, PATH_MAX-1);
|
||||
if (res < 0) {
|
||||
assert(*size > strlen(symlink));
|
||||
strcpy(buffer, symlink);
|
||||
} else {
|
||||
assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
|
||||
snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
|
||||
}
|
||||
*size = strlen(buffer);
|
||||
return 0;
|
||||
/* Usage of absolute filename with location exported in PATH */
|
||||
} else {
|
||||
char clonedpath[8192]; /* assume 8k buffer will fit PATH */
|
||||
/* Case iii). Search PATH environment variable */
|
||||
char trypath[PATH_MAX];
|
||||
char *clonedpath = NULL;
|
||||
char *token = NULL;
|
||||
struct stat statstruct;
|
||||
|
||||
/* Get the paths. */
|
||||
char *path = getenv("PATH");
|
||||
if(sizeof(clonedpath) <= strlen(path))
|
||||
|
||||
if (path == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get a local copy. */
|
||||
strcpy(clonedpath, path);
|
||||
clonedpath = uv__strdup(path);
|
||||
if (clonedpath == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Tokenize. */
|
||||
token = strtok(clonedpath, ":");
|
||||
while (token != NULL) {
|
||||
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
|
||||
if (realpath(trypath, abspath) == abspath) {
|
||||
/* Check the match is executable */
|
||||
if (access(abspath, X_OK) == 0) {
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
/* Get current working directory. (may be required in the loop). */
|
||||
snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
|
||||
res = readlink(cwd, cwdl, sizeof(cwdl) - 1);
|
||||
if (res < 0)
|
||||
return -errno;
|
||||
/* Run through the tokens, append our executable file name with each,
|
||||
* and see which one succeeds. Exit on first match. */
|
||||
while(token != NULL) {
|
||||
if (token[0] == '.') {
|
||||
/* Path contains a token relative to current directory. */
|
||||
char *relative = strchr(token, '/');
|
||||
if (relative != NULL)
|
||||
/* A path which is not current directory. */
|
||||
snprintf(symlink, PATH_MAX-1, "%s%s/%s", cwdl, relative+1, ps.pr_fname);
|
||||
else
|
||||
snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, ps.pr_fname);
|
||||
if (stat(symlink, &statstruct) != -1) {
|
||||
/* File exists. Resolve if it is a link. */
|
||||
res = readlink(symlink, temp_buffer, PATH_MAX-1);
|
||||
if (res < 0) {
|
||||
assert(*size > strlen(symlink));
|
||||
strcpy(buffer, symlink);
|
||||
} else {
|
||||
assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
|
||||
snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
|
||||
}
|
||||
*size = strlen(buffer);
|
||||
return 0;
|
||||
}
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
/* Absolute path names. */
|
||||
} else {
|
||||
snprintf(symlink, PATH_MAX-1, "%s/%s", token, ps.pr_fname);
|
||||
if (stat(symlink, &statstruct) != -1) {
|
||||
res = readlink(symlink, temp_buffer, PATH_MAX-1);
|
||||
if (res < 0) {
|
||||
assert(*size > strlen(symlink));
|
||||
strcpy(buffer, symlink);
|
||||
} else {
|
||||
assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
|
||||
snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
|
||||
}
|
||||
*size = strlen(buffer);
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
uv__free(clonedpath);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
}
|
||||
uv__free(clonedpath);
|
||||
|
||||
/* Out of tokens (path entries), and no match found */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <limits.h> /* INT_MAX, PATH_MAX */
|
||||
#include <limits.h> /* INT_MAX, PATH_MAX, IOV_MAX */
|
||||
#include <sys/uio.h> /* writev */
|
||||
#include <sys/resource.h> /* getrusage */
|
||||
#include <pwd.h>
|
||||
|
@ -55,13 +55,13 @@
|
|||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/filio.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/wait.h>
|
||||
# define UV__O_CLOEXEC O_CLOEXEC
|
||||
# if __FreeBSD__ >= 10
|
||||
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
|
||||
# define uv__accept4 accept4
|
||||
# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
|
||||
# define UV__SOCK_CLOEXEC SOCK_CLOEXEC
|
||||
|
@ -199,6 +199,19 @@ void uv__make_close_pending(uv_handle_t* handle) {
|
|||
handle->loop->closing_handles = handle;
|
||||
}
|
||||
|
||||
int uv__getiovmax(void) {
|
||||
#if defined(IOV_MAX)
|
||||
return IOV_MAX;
|
||||
#elif defined(_SC_IOV_MAX)
|
||||
static int iovmax = -1;
|
||||
if (iovmax == -1)
|
||||
iovmax = sysconf(_SC_IOV_MAX);
|
||||
return iovmax;
|
||||
#else
|
||||
return 1024;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void uv__finish_close(uv_handle_t* handle) {
|
||||
/* Note: while the handle is in the UV_CLOSING state now, it's still possible
|
||||
|
@ -477,7 +490,7 @@ int uv__close(int fd) {
|
|||
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
|
||||
defined(_AIX)
|
||||
defined(_AIX) || defined(__DragonFly__)
|
||||
|
||||
int uv__nonblock(int fd, int set) {
|
||||
int r;
|
||||
|
@ -506,7 +519,8 @@ int uv__cloexec(int fd, int set) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#else /* !(defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) */
|
||||
#else /* !(defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
|
||||
defined(_AIX) || defined(__DragonFly__)) */
|
||||
|
||||
int uv__nonblock(int fd, int set) {
|
||||
int flags;
|
||||
|
@ -569,7 +583,8 @@ int uv__cloexec(int fd, int set) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) */
|
||||
#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
|
||||
defined(_AIX) || defined(__DragonFly__) */
|
||||
|
||||
|
||||
/* This function is not execve-safe, there is a race window
|
||||
|
@ -907,7 +922,8 @@ int uv__open_cloexec(const char* path, int flags) {
|
|||
int err;
|
||||
int fd;
|
||||
|
||||
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 9)
|
||||
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 9) || \
|
||||
defined(__DragonFly__)
|
||||
static int no_cloexec;
|
||||
|
||||
if (!no_cloexec) {
|
||||
|
|
|
@ -74,6 +74,30 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
|
|||
}
|
||||
|
||||
|
||||
#ifdef __DragonFly__
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
char abspath[PATH_MAX * 2 + 1];
|
||||
ssize_t abspath_size;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
abspath_size = readlink("/proc/curproc/file", abspath, sizeof(abspath));
|
||||
if (abspath_size < 0)
|
||||
return -errno;
|
||||
|
||||
assert(abspath_size > 0);
|
||||
*size -= 1;
|
||||
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
char abspath[PATH_MAX * 2 + 1];
|
||||
int mib[4];
|
||||
|
@ -82,19 +106,12 @@ int uv_exepath(char* buffer, size_t* size) {
|
|||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef __DragonFly__
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_ARGS;
|
||||
mib[3] = getpid();
|
||||
#else
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PATHNAME;
|
||||
mib[3] = -1;
|
||||
#endif
|
||||
|
||||
abspath_size = sizeof abspath;;
|
||||
abspath_size = sizeof abspath;
|
||||
if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0))
|
||||
return -errno;
|
||||
|
||||
|
@ -110,7 +127,7 @@ int uv_exepath(char* buffer, size_t* size) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
int freecount;
|
||||
|
|
|
@ -58,52 +58,63 @@
|
|||
# include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
#define INIT(type) \
|
||||
#define INIT(subtype) \
|
||||
do { \
|
||||
uv__req_init((loop), (req), UV_FS); \
|
||||
(req)->fs_type = UV_FS_ ## type; \
|
||||
(req)->result = 0; \
|
||||
(req)->ptr = NULL; \
|
||||
(req)->loop = loop; \
|
||||
(req)->path = NULL; \
|
||||
(req)->new_path = NULL; \
|
||||
(req)->cb = (cb); \
|
||||
req->type = UV_FS; \
|
||||
if (cb != NULL) \
|
||||
uv__req_init(loop, req, UV_FS); \
|
||||
req->fs_type = UV_FS_ ## subtype; \
|
||||
req->result = 0; \
|
||||
req->ptr = NULL; \
|
||||
req->loop = loop; \
|
||||
req->path = NULL; \
|
||||
req->new_path = NULL; \
|
||||
req->cb = cb; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define PATH \
|
||||
do { \
|
||||
(req)->path = uv__strdup(path); \
|
||||
if ((req)->path == NULL) \
|
||||
return -ENOMEM; \
|
||||
assert(path != NULL); \
|
||||
if (cb == NULL) { \
|
||||
req->path = path; \
|
||||
} else { \
|
||||
req->path = uv__strdup(path); \
|
||||
if (req->path == NULL) \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define PATH2 \
|
||||
do { \
|
||||
size_t path_len; \
|
||||
size_t new_path_len; \
|
||||
path_len = strlen((path)) + 1; \
|
||||
new_path_len = strlen((new_path)) + 1; \
|
||||
(req)->path = uv__malloc(path_len + new_path_len); \
|
||||
if ((req)->path == NULL) \
|
||||
return -ENOMEM; \
|
||||
(req)->new_path = (req)->path + path_len; \
|
||||
memcpy((void*) (req)->path, (path), path_len); \
|
||||
memcpy((void*) (req)->new_path, (new_path), new_path_len); \
|
||||
if (cb == NULL) { \
|
||||
req->path = path; \
|
||||
req->new_path = new_path; \
|
||||
} else { \
|
||||
size_t path_len; \
|
||||
size_t new_path_len; \
|
||||
path_len = strlen(path) + 1; \
|
||||
new_path_len = strlen(new_path) + 1; \
|
||||
req->path = uv__malloc(path_len + new_path_len); \
|
||||
if (req->path == NULL) \
|
||||
return -ENOMEM; \
|
||||
req->new_path = req->path + path_len; \
|
||||
memcpy((void*) req->path, path, path_len); \
|
||||
memcpy((void*) req->new_path, new_path, new_path_len); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define POST \
|
||||
do { \
|
||||
if ((cb) != NULL) { \
|
||||
uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); \
|
||||
if (cb != NULL) { \
|
||||
uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
|
||||
return 0; \
|
||||
} \
|
||||
else { \
|
||||
uv__fs_work(&(req)->work_req); \
|
||||
uv__fs_done(&(req)->work_req, 0); \
|
||||
return (req)->result; \
|
||||
uv__fs_work(&req->work_req); \
|
||||
return req->result; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
@ -309,8 +320,6 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
|
|||
}
|
||||
|
||||
done:
|
||||
if (req->bufs != req->bufsml)
|
||||
uv__free(req->bufs);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -545,7 +554,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
|||
|
||||
return -1;
|
||||
}
|
||||
#elif defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
|
||||
{
|
||||
off_t len;
|
||||
ssize_t r;
|
||||
|
@ -555,7 +564,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
|||
* number of bytes have been sent, we don't consider it an error.
|
||||
*/
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
len = 0;
|
||||
r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
|
||||
#else
|
||||
|
@ -670,9 +679,6 @@ done:
|
|||
pthread_mutex_unlock(&lock);
|
||||
#endif
|
||||
|
||||
if (req->bufs != req->bufsml)
|
||||
uv__free(req->bufs);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -777,6 +783,47 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) {
|
|||
}
|
||||
|
||||
|
||||
typedef ssize_t (*uv__fs_buf_iter_processor)(uv_fs_t* req);
|
||||
static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process) {
|
||||
unsigned int iovmax;
|
||||
unsigned int nbufs;
|
||||
uv_buf_t* bufs;
|
||||
ssize_t total;
|
||||
ssize_t result;
|
||||
|
||||
iovmax = uv__getiovmax();
|
||||
nbufs = req->nbufs;
|
||||
bufs = req->bufs;
|
||||
total = 0;
|
||||
|
||||
while (nbufs > 0) {
|
||||
req->nbufs = nbufs;
|
||||
if (req->nbufs > iovmax)
|
||||
req->nbufs = iovmax;
|
||||
|
||||
result = process(req);
|
||||
if (result <= 0) {
|
||||
if (total == 0)
|
||||
total = result;
|
||||
break;
|
||||
}
|
||||
|
||||
if (req->off >= 0)
|
||||
req->off += result;
|
||||
|
||||
req->bufs += req->nbufs;
|
||||
nbufs -= req->nbufs;
|
||||
total += result;
|
||||
}
|
||||
|
||||
if (bufs != req->bufsml)
|
||||
uv__free(bufs);
|
||||
req->bufs = NULL;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
static void uv__fs_work(struct uv__work* w) {
|
||||
int retry_on_eintr;
|
||||
uv_fs_t* req;
|
||||
|
@ -810,7 +857,7 @@ static void uv__fs_work(struct uv__work* w) {
|
|||
X(MKDIR, mkdir(req->path, req->mode));
|
||||
X(MKDTEMP, uv__fs_mkdtemp(req));
|
||||
X(OPEN, uv__fs_open(req));
|
||||
X(READ, uv__fs_read(req));
|
||||
X(READ, uv__fs_buf_iter(req, uv__fs_read));
|
||||
X(SCANDIR, uv__fs_scandir(req));
|
||||
X(READLINK, uv__fs_readlink(req));
|
||||
X(RENAME, rename(req->path, req->new_path));
|
||||
|
@ -820,7 +867,7 @@ static void uv__fs_work(struct uv__work* w) {
|
|||
X(SYMLINK, symlink(req->path, req->new_path));
|
||||
X(UNLINK, unlink(req->path));
|
||||
X(UTIME, uv__fs_utime(req));
|
||||
X(WRITE, uv__fs_write(req));
|
||||
X(WRITE, uv__fs_buf_iter(req, uv__fs_write));
|
||||
default: abort();
|
||||
}
|
||||
#undef X
|
||||
|
@ -850,8 +897,7 @@ static void uv__fs_done(struct uv__work* w, int status) {
|
|||
req->result = -ECANCELED;
|
||||
}
|
||||
|
||||
if (req->cb != NULL)
|
||||
req->cb(req);
|
||||
req->cb(req);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1035,6 +1081,9 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
|
|||
unsigned int nbufs,
|
||||
int64_t off,
|
||||
uv_fs_cb cb) {
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
return -EINVAL;
|
||||
|
||||
INIT(READ);
|
||||
req->file = file;
|
||||
|
||||
|
@ -1157,6 +1206,9 @@ int uv_fs_write(uv_loop_t* loop,
|
|||
unsigned int nbufs,
|
||||
int64_t off,
|
||||
uv_fs_cb cb) {
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
return -EINVAL;
|
||||
|
||||
INIT(WRITE);
|
||||
req->file = file;
|
||||
|
||||
|
@ -1176,7 +1228,14 @@ int uv_fs_write(uv_loop_t* loop,
|
|||
|
||||
|
||||
void uv_fs_req_cleanup(uv_fs_t* req) {
|
||||
uv__free((void*)req->path);
|
||||
/* Only necessary for asychronous requests, i.e., requests with a callback.
|
||||
* Synchronous ones don't copy their arguments and have req->path and
|
||||
* req->new_path pointing to user-owned memory. UV_FS_MKDTEMP is the
|
||||
* exception to the rule, it always allocates memory.
|
||||
*/
|
||||
if (req->path != NULL && (req->cb != NULL || req->fs_type == UV_FS_MKDTEMP))
|
||||
uv__free((void*) req->path); /* Memory is shared with req->new_path. */
|
||||
|
||||
req->path = NULL;
|
||||
req->new_path = NULL;
|
||||
|
||||
|
|
|
@ -172,6 +172,7 @@ int uv__socket(int domain, int type, int protocol);
|
|||
int uv__dup(int fd);
|
||||
ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
|
||||
void uv__make_close_pending(uv_handle_t* handle);
|
||||
int uv__getiovmax(void);
|
||||
|
||||
void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd);
|
||||
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events);
|
||||
|
|
|
@ -379,6 +379,10 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||
if (!(statbuf.st_mode & S_IFDIR))
|
||||
goto fallback;
|
||||
|
||||
/* The fallback fd is no longer needed */
|
||||
uv__close(fd);
|
||||
handle->event_watcher.fd = -1;
|
||||
|
||||
return uv__fsevents_init(handle);
|
||||
|
||||
fallback:
|
||||
|
@ -406,8 +410,12 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
|
|||
uv__free(handle->path);
|
||||
handle->path = NULL;
|
||||
|
||||
uv__close(handle->event_watcher.fd);
|
||||
handle->event_watcher.fd = -1;
|
||||
if (handle->event_watcher.fd != -1) {
|
||||
/* When FSEvents is used, we don't use the event_watcher's fd under certain
|
||||
* confitions. (see uv_fs_event_start) */
|
||||
uv__close(handle->event_watcher.fd);
|
||||
handle->event_watcher.fd = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -63,24 +63,44 @@ int uv_loop_init(uv_loop_t* loop) {
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
uv_signal_init(loop, &loop->child_watcher);
|
||||
err = uv_signal_init(loop, &loop->child_watcher);
|
||||
if (err)
|
||||
goto fail_signal_init;
|
||||
|
||||
uv__handle_unref(&loop->child_watcher);
|
||||
loop->child_watcher.flags |= UV__HANDLE_INTERNAL;
|
||||
QUEUE_INIT(&loop->process_handles);
|
||||
|
||||
if (uv_rwlock_init(&loop->cloexec_lock))
|
||||
abort();
|
||||
err = uv_rwlock_init(&loop->cloexec_lock);
|
||||
if (err)
|
||||
goto fail_rwlock_init;
|
||||
|
||||
if (uv_mutex_init(&loop->wq_mutex))
|
||||
abort();
|
||||
err = uv_mutex_init(&loop->wq_mutex);
|
||||
if (err)
|
||||
goto fail_mutex_init;
|
||||
|
||||
if (uv_async_init(loop, &loop->wq_async, uv__work_done))
|
||||
abort();
|
||||
err = uv_async_init(loop, &loop->wq_async, uv__work_done);
|
||||
if (err)
|
||||
goto fail_async_init;
|
||||
|
||||
uv__handle_unref(&loop->wq_async);
|
||||
loop->wq_async.flags |= UV__HANDLE_INTERNAL;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_async_init:
|
||||
uv_mutex_destroy(&loop->wq_mutex);
|
||||
|
||||
fail_mutex_init:
|
||||
uv_rwlock_destroy(&loop->cloexec_lock);
|
||||
|
||||
fail_rwlock_init:
|
||||
uv__signal_loop_cleanup(loop);
|
||||
|
||||
fail_signal_init:
|
||||
uv__platform_loop_delete(loop);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
* */
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) {
|
||||
static int workaround;
|
||||
|
|
|
@ -391,6 +391,9 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
|
|||
int enable;
|
||||
#endif
|
||||
|
||||
if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd))
|
||||
return -EBUSY;
|
||||
|
||||
assert(fd >= 0);
|
||||
stream->flags |= flags;
|
||||
|
||||
|
@ -736,19 +739,6 @@ static int uv__handle_fd(uv_handle_t* handle) {
|
|||
}
|
||||
}
|
||||
|
||||
static int uv__getiovmax() {
|
||||
#if defined(IOV_MAX)
|
||||
return IOV_MAX;
|
||||
#elif defined(_SC_IOV_MAX)
|
||||
static int iovmax = -1;
|
||||
if (iovmax == -1)
|
||||
iovmax = sysconf(_SC_IOV_MAX);
|
||||
return iovmax;
|
||||
#else
|
||||
return 1024;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void uv__write(uv_stream_t* stream) {
|
||||
struct iovec* iov;
|
||||
QUEUE* q;
|
||||
|
@ -819,7 +809,17 @@ start:
|
|||
do {
|
||||
n = sendmsg(uv__stream_fd(stream), &msg, 0);
|
||||
}
|
||||
#if defined(__APPLE__)
|
||||
/*
|
||||
* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
|
||||
* EPROTOTYPE can be returned while trying to write to a socket that is
|
||||
* shutting down. If we retry the write, we should get the expected EPIPE
|
||||
* instead.
|
||||
*/
|
||||
while (n == -1 && (errno == EINTR || errno == EPROTOTYPE));
|
||||
#else
|
||||
while (n == -1 && errno == EINTR);
|
||||
#endif
|
||||
} else {
|
||||
do {
|
||||
if (iovcnt == 1) {
|
||||
|
@ -828,7 +828,17 @@ start:
|
|||
n = writev(uv__stream_fd(stream), iov, iovcnt);
|
||||
}
|
||||
}
|
||||
#if defined(__APPLE__)
|
||||
/*
|
||||
* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
|
||||
* EPROTOTYPE can be returned while trying to write to a socket that is
|
||||
* shutting down. If we retry the write, we should get the expected EPIPE
|
||||
* instead.
|
||||
*/
|
||||
while (n == -1 && (errno == EINTR || errno == EPROTOTYPE));
|
||||
#else
|
||||
while (n == -1 && errno == EINTR);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
|
|
|
@ -28,18 +28,14 @@
|
|||
#include <errno.h>
|
||||
|
||||
|
||||
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
|
||||
uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
|
||||
int sockfd;
|
||||
int err;
|
||||
|
||||
if (uv__stream_fd(handle) != -1)
|
||||
if (domain == AF_UNSPEC || uv__stream_fd(handle) != -1) {
|
||||
handle->flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = uv__socket(domain, SOCK_STREAM, 0);
|
||||
if (err < 0)
|
||||
|
@ -56,6 +52,40 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
|
|||
}
|
||||
|
||||
|
||||
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
|
||||
int domain;
|
||||
|
||||
/* Use the lower 8 bits for the domain */
|
||||
domain = flags & 0xFF;
|
||||
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & ~0xFF)
|
||||
return -EINVAL;
|
||||
|
||||
uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
|
||||
|
||||
/* If anything fails beyond this point we need to remove the handle from
|
||||
* the handle queue, since it was added by uv__handle_init in uv_stream_init.
|
||||
*/
|
||||
|
||||
if (domain != AF_UNSPEC) {
|
||||
int err = maybe_new_socket(tcp, domain, 0);
|
||||
if (err) {
|
||||
QUEUE_REMOVE(&tcp->handle_queue);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
|
||||
return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
|
||||
}
|
||||
|
||||
|
||||
int uv__tcp_bind(uv_tcp_t* tcp,
|
||||
const struct sockaddr* addr,
|
||||
unsigned int addrlen,
|
||||
|
@ -91,8 +121,13 @@ int uv__tcp_bind(uv_tcp_t* tcp,
|
|||
#endif
|
||||
|
||||
errno = 0;
|
||||
if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE)
|
||||
if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
|
||||
if (errno == EAFNOSUPPORT)
|
||||
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
|
||||
* socket created with AF_INET to an AF_INET6 address or vice versa. */
|
||||
return -EINVAL;
|
||||
return -errno;
|
||||
}
|
||||
tcp->delayed_error = -errno;
|
||||
|
||||
if (addr->sa_family == AF_INET6)
|
||||
|
|
|
@ -51,8 +51,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
|
|||
flags = 0;
|
||||
newfd = -1;
|
||||
|
||||
uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY);
|
||||
|
||||
/* Reopen the file descriptor when it refers to a tty. This lets us put the
|
||||
* tty in non-blocking mode without affecting other processes that share it
|
||||
* with us.
|
||||
|
@ -89,11 +87,18 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
|
|||
}
|
||||
|
||||
skip:
|
||||
uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY);
|
||||
|
||||
/* If anything fails beyond this point we need to remove the handle from
|
||||
* the handle queue, since it was added by uv__handle_init in uv_stream_init.
|
||||
*/
|
||||
|
||||
#if defined(__APPLE__)
|
||||
r = uv__stream_try_select((uv_stream_t*) tty, &fd);
|
||||
if (r) {
|
||||
if (newfd != -1)
|
||||
uv__close(newfd);
|
||||
QUEUE_REMOVE(&tty->handle_queue);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -321,6 +321,10 @@ int uv__udp_bind(uv_udp_t* handle,
|
|||
|
||||
if (bind(fd, addr, addrlen)) {
|
||||
err = -errno;
|
||||
if (errno == EAFNOSUPPORT)
|
||||
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
|
||||
* socket created with AF_INET to an AF_INET6 address or vice versa. */
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -551,25 +555,51 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
|
|||
}
|
||||
|
||||
|
||||
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
|
||||
int domain;
|
||||
int err;
|
||||
int fd;
|
||||
|
||||
/* Use the lower 8 bits for the domain */
|
||||
domain = flags & 0xFF;
|
||||
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & ~0xFF)
|
||||
return -EINVAL;
|
||||
|
||||
if (domain != AF_UNSPEC) {
|
||||
err = uv__socket(domain, SOCK_DGRAM, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
fd = err;
|
||||
} else {
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP);
|
||||
handle->alloc_cb = NULL;
|
||||
handle->recv_cb = NULL;
|
||||
handle->send_queue_size = 0;
|
||||
handle->send_queue_count = 0;
|
||||
uv__io_init(&handle->io_watcher, uv__udp_io, -1);
|
||||
uv__io_init(&handle->io_watcher, uv__udp_io, fd);
|
||||
QUEUE_INIT(&handle->write_queue);
|
||||
QUEUE_INIT(&handle->write_completed_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
return uv_udp_init_ex(loop, handle, AF_UNSPEC);
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
||||
int err;
|
||||
|
||||
/* Check for already active socket. */
|
||||
if (handle->io_watcher.fd != -1)
|
||||
return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */
|
||||
return -EBUSY;
|
||||
|
||||
err = uv__nonblock(sock, 1);
|
||||
if (err)
|
||||
|
@ -638,6 +668,8 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle,
|
|||
int val) {
|
||||
#if defined(__sun) || defined(_AIX)
|
||||
char arg = val;
|
||||
#elif defined(__OpenBSD__)
|
||||
unsigned char arg = val;
|
||||
#else
|
||||
int arg = val;
|
||||
#endif
|
||||
|
@ -672,13 +704,13 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
|
|||
* so hardcode the size of these options on this platform,
|
||||
* and use the general uv__setsockopt_maybe_char call on other platforms.
|
||||
*/
|
||||
#if defined(__sun) || defined(_AIX)
|
||||
#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__)
|
||||
return uv__setsockopt(handle,
|
||||
IP_TTL,
|
||||
IPV6_UNICAST_HOPS,
|
||||
&ttl,
|
||||
sizeof(ttl));
|
||||
#endif /* defined(__sun) || defined(_AIX) */
|
||||
#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) */
|
||||
|
||||
return uv__setsockopt_maybe_char(handle,
|
||||
IP_TTL,
|
||||
|
|
|
@ -29,7 +29,9 @@
|
|||
#include <stdlib.h> /* malloc */
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
# include <malloc.h> /* malloc */
|
||||
#else
|
||||
# include <net/if.h> /* if_nametoindex */
|
||||
#endif
|
||||
|
||||
|
@ -135,14 +137,27 @@ uv_buf_t uv_buf_init(char* base, unsigned int len) {
|
|||
}
|
||||
|
||||
|
||||
static const char* uv__unknown_err_code(int err) {
|
||||
char buf[32];
|
||||
char* copy;
|
||||
|
||||
#ifndef _WIN32
|
||||
snprintf(buf, sizeof(buf), "Unknown system error %d", err);
|
||||
#else
|
||||
_snprintf(buf, sizeof(buf), "Unknown system error %d", err);
|
||||
#endif
|
||||
copy = uv__strdup(buf);
|
||||
|
||||
return copy != NULL ? copy : "Unknown system error";
|
||||
}
|
||||
|
||||
|
||||
#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
|
||||
const char* uv_err_name(int err) {
|
||||
switch (err) {
|
||||
UV_ERRNO_MAP(UV_ERR_NAME_GEN)
|
||||
default:
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
return uv__unknown_err_code(err);
|
||||
}
|
||||
#undef UV_ERR_NAME_GEN
|
||||
|
||||
|
@ -151,9 +166,8 @@ const char* uv_err_name(int err) {
|
|||
const char* uv_strerror(int err) {
|
||||
switch (err) {
|
||||
UV_ERRNO_MAP(UV_STRERROR_GEN)
|
||||
default:
|
||||
return "Unknown system error";
|
||||
}
|
||||
return uv__unknown_err_code(err);
|
||||
}
|
||||
#undef UV_STRERROR_GEN
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ void uv__fs_scandir_cleanup(uv_fs_t* req);
|
|||
(((h)->flags & UV__HANDLE_REF) != 0)
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define uv__handle_platform_init(h)
|
||||
# define uv__handle_platform_init(h) ((h)->u.fd = -1)
|
||||
#else
|
||||
# define uv__handle_platform_init(h) ((h)->next_closing = NULL)
|
||||
#endif
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
|
||||
#include "uv.h"
|
||||
|
||||
#define UV_VERSION ((UV_VERSION_MAJOR << 16) | \
|
||||
(UV_VERSION_MINOR << 8) | \
|
||||
(UV_VERSION_PATCH))
|
||||
|
||||
#define UV_STRINGIFY(v) UV_STRINGIFY_HELPER(v)
|
||||
#define UV_STRINGIFY_HELPER(v) #v
|
||||
|
||||
|
@ -40,7 +36,7 @@
|
|||
|
||||
|
||||
unsigned int uv_version(void) {
|
||||
return UV_VERSION;
|
||||
return UV_VERSION_HEX;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -124,6 +124,8 @@ static void uv_init(void) {
|
|||
|
||||
|
||||
int uv_loop_init(uv_loop_t* loop) {
|
||||
int err;
|
||||
|
||||
/* Initialize libuv itself first */
|
||||
uv__once_init();
|
||||
|
||||
|
@ -165,16 +167,27 @@ int uv_loop_init(uv_loop_t* loop) {
|
|||
loop->timer_counter = 0;
|
||||
loop->stop_flag = 0;
|
||||
|
||||
if (uv_mutex_init(&loop->wq_mutex))
|
||||
abort();
|
||||
err = uv_mutex_init(&loop->wq_mutex);
|
||||
if (err)
|
||||
goto fail_mutex_init;
|
||||
|
||||
if (uv_async_init(loop, &loop->wq_async, uv__work_done))
|
||||
abort();
|
||||
err = uv_async_init(loop, &loop->wq_async, uv__work_done);
|
||||
if (err)
|
||||
goto fail_async_init;
|
||||
|
||||
uv__handle_unref(&loop->wq_async);
|
||||
loop->wq_async.flags |= UV__HANDLE_INTERNAL;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_async_init:
|
||||
uv_mutex_destroy(&loop->wq_mutex);
|
||||
|
||||
fail_mutex_init:
|
||||
CloseHandle(loop->iocp);
|
||||
loop->iocp = INVALID_HANDLE_VALUE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,
|
|||
if (!ReadDirectoryChangesW(handle->dir_handle,
|
||||
handle->buffer,
|
||||
uv_directory_watcher_buffer_size,
|
||||
FALSE,
|
||||
(handle->flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE,
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME |
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||
|
@ -63,6 +63,20 @@ static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,
|
|||
handle->req_pending = 1;
|
||||
}
|
||||
|
||||
static int uv_relative_path(const WCHAR* filename,
|
||||
const WCHAR* dir,
|
||||
WCHAR** relpath) {
|
||||
int dirlen = wcslen(dir);
|
||||
int filelen = wcslen(filename);
|
||||
if (dir[dirlen - 1] == '\\')
|
||||
dirlen--;
|
||||
*relpath = uv__malloc((MAX_PATH + 1) * sizeof(WCHAR));
|
||||
if (!*relpath)
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
|
||||
wcsncpy(*relpath, filename + dirlen + 1, filelen - dirlen - 1);
|
||||
(*relpath)[filelen - dirlen - 1] = L'\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uv_split_path(const WCHAR* filename, WCHAR** dir,
|
||||
WCHAR** file) {
|
||||
|
@ -237,7 +251,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||
if (!ReadDirectoryChangesW(handle->dir_handle,
|
||||
handle->buffer,
|
||||
uv_directory_watcher_buffer_size,
|
||||
FALSE,
|
||||
(flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE,
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME |
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||
|
@ -410,7 +424,9 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
|||
|
||||
if (long_filenamew) {
|
||||
/* Get the file name out of the long path. */
|
||||
result = uv_split_path(long_filenamew, NULL, &filenamew);
|
||||
result = uv_relative_path(long_filenamew,
|
||||
handle->dirw,
|
||||
&filenamew);
|
||||
uv__free(long_filenamew);
|
||||
|
||||
if (result == 0) {
|
||||
|
|
|
@ -116,8 +116,8 @@ void uv_fs_init() {
|
|||
}
|
||||
|
||||
|
||||
INLINE static int fs__capture_path(uv_loop_t* loop, uv_fs_t* req,
|
||||
const char* path, const char* new_path, const int copy_path) {
|
||||
INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
|
||||
const char* new_path, const int copy_path) {
|
||||
char* buf;
|
||||
char* pos;
|
||||
ssize_t buf_sz = 0, path_len, pathw_len = 0, new_pathw_len = 0;
|
||||
|
@ -528,7 +528,11 @@ void fs__close(uv_fs_t* req) {
|
|||
|
||||
VERIFY_FD(fd, req);
|
||||
|
||||
result = _close(fd);
|
||||
if (fd > 2)
|
||||
result = _close(fd);
|
||||
else
|
||||
result = 0;
|
||||
|
||||
SET_REQ_RESULT(req, result);
|
||||
}
|
||||
|
||||
|
@ -821,7 +825,11 @@ void fs__scandir(uv_fs_t* req) {
|
|||
* A file name is at most 256 WCHARs long.
|
||||
* According to MSDN, the buffer must be aligned at an 8-byte boundary.
|
||||
*/
|
||||
#if _MSC_VER
|
||||
__declspec(align(8)) char buffer[8192];
|
||||
#else
|
||||
__attribute__ ((aligned (8))) char buffer[8192];
|
||||
#endif
|
||||
|
||||
STATIC_ASSERT(sizeof buffer >=
|
||||
sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR));
|
||||
|
@ -1754,8 +1762,7 @@ static void uv__fs_done(struct uv__work* w, int status) {
|
|||
req->result = UV_ECANCELED;
|
||||
}
|
||||
|
||||
if (req->cb != NULL)
|
||||
req->cb(req);
|
||||
req->cb(req);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1784,7 +1791,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_OPEN, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -1823,6 +1830,9 @@ int uv_fs_read(uv_loop_t* loop,
|
|||
unsigned int nbufs,
|
||||
int64_t offset,
|
||||
uv_fs_cb cb) {
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
uv_fs_req_init(loop, req, UV_FS_READ, cb);
|
||||
|
||||
req->file.fd = fd;
|
||||
|
@ -1856,6 +1866,9 @@ int uv_fs_write(uv_loop_t* loop,
|
|||
unsigned int nbufs,
|
||||
int64_t offset,
|
||||
uv_fs_cb cb) {
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
uv_fs_req_init(loop, req, UV_FS_WRITE, cb);
|
||||
|
||||
req->file.fd = fd;
|
||||
|
@ -1888,7 +1901,7 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_UNLINK, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -1909,7 +1922,7 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_MKDIR, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -1932,7 +1945,7 @@ int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_MKDTEMP, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, tpl, NULL, TRUE);
|
||||
err = fs__capture_path(req, tpl, NULL, TRUE);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
|
||||
|
@ -1951,7 +1964,7 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_RMDIR, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -1972,7 +1985,7 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -1995,7 +2008,7 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_LINK, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, new_path, cb != NULL);
|
||||
err = fs__capture_path(req, path, new_path, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -2016,7 +2029,7 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_SYMLINK, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, new_path, cb != NULL);
|
||||
err = fs__capture_path(req, path, new_path, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -2039,7 +2052,7 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_READLINK, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -2060,7 +2073,7 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_CHOWN, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -2094,7 +2107,7 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_STAT, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -2114,7 +2127,7 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_LSTAT, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -2149,7 +2162,7 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_RENAME, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, new_path, cb != NULL);
|
||||
err = fs__capture_path(req, path, new_path, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -2238,7 +2251,7 @@ int uv_fs_access(uv_loop_t* loop,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_ACCESS, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
|
||||
|
@ -2260,7 +2273,7 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_CHMOD, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
@ -2300,7 +2313,7 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
|
|||
|
||||
uv_fs_req_init(loop, req, UV_FS_UTIME, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
|
|||
|
||||
/* Used by all handles. */
|
||||
#define UV_HANDLE_CLOSED 0x00000002
|
||||
#define UV_HANDLE_ENDGAME_QUEUED 0x00000004
|
||||
#define UV_HANDLE_ENDGAME_QUEUED 0x00000008
|
||||
|
||||
/* uv-common.h: #define UV__HANDLE_CLOSING 0x00000001 */
|
||||
/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */
|
||||
|
@ -76,7 +76,6 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
|
|||
#define UV_HANDLE_BOUND 0x00000200
|
||||
#define UV_HANDLE_LISTENING 0x00000800
|
||||
#define UV_HANDLE_CONNECTION 0x00001000
|
||||
#define UV_HANDLE_CONNECTED 0x00002000
|
||||
#define UV_HANDLE_READABLE 0x00008000
|
||||
#define UV_HANDLE_WRITABLE 0x00010000
|
||||
#define UV_HANDLE_READ_PENDING 0x00020000
|
||||
|
|
|
@ -180,6 +180,18 @@ static HANDLE open_named_pipe(const WCHAR* name, DWORD* duplex_flags) {
|
|||
}
|
||||
|
||||
|
||||
static void close_pipe(uv_pipe_t* pipe) {
|
||||
assert(pipe->u.fd == -1 || pipe->u.fd > 2);
|
||||
if (pipe->u.fd == -1)
|
||||
CloseHandle(pipe->handle);
|
||||
else
|
||||
close(pipe->u.fd);
|
||||
|
||||
pipe->u.fd = -1;
|
||||
pipe->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
|
||||
int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
|
||||
char* name, size_t nameSize) {
|
||||
HANDLE pipeHandle;
|
||||
|
@ -233,6 +245,7 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
|
|||
static int uv_set_pipe_handle(uv_loop_t* loop,
|
||||
uv_pipe_t* handle,
|
||||
HANDLE pipeHandle,
|
||||
int fd,
|
||||
DWORD duplex_flags) {
|
||||
NTSTATUS nt_status;
|
||||
IO_STATUS_BLOCK io_status;
|
||||
|
@ -241,6 +254,10 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
|
|||
DWORD current_mode = 0;
|
||||
DWORD err = 0;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_PIPESERVER) &&
|
||||
handle->handle != INVALID_HANDLE_VALUE)
|
||||
return UV_EBUSY;
|
||||
|
||||
if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
|
||||
err = GetLastError();
|
||||
if (err == ERROR_ACCESS_DENIED) {
|
||||
|
@ -292,6 +309,7 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
|
|||
}
|
||||
|
||||
handle->handle = pipeHandle;
|
||||
handle->u.fd = fd;
|
||||
handle->flags |= duplex_flags;
|
||||
|
||||
return 0;
|
||||
|
@ -454,6 +472,8 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
|||
|
||||
|
||||
void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
|
||||
if (handle->flags & UV_HANDLE_BOUND)
|
||||
return;
|
||||
handle->pipe.serv.pending_instances = count;
|
||||
handle->flags |= UV_HANDLE_PIPESERVER;
|
||||
}
|
||||
|
@ -527,6 +547,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
|||
if (uv_set_pipe_handle(loop,
|
||||
handle,
|
||||
handle->pipe.serv.accept_reqs[0].pipeHandle,
|
||||
-1,
|
||||
0)) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
|
@ -580,7 +601,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
|||
}
|
||||
|
||||
if (pipeHandle != INVALID_HANDLE_VALUE &&
|
||||
!uv_set_pipe_handle(loop, handle, pipeHandle, duplex_flags)) {
|
||||
!uv_set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) {
|
||||
SET_REQ_SUCCESS(req);
|
||||
} else {
|
||||
SET_REQ_ERROR(req, GetLastError());
|
||||
|
@ -643,6 +664,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
|||
if (uv_set_pipe_handle(loop,
|
||||
(uv_pipe_t*) req->handle,
|
||||
pipeHandle,
|
||||
-1,
|
||||
duplex_flags)) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
|
@ -729,6 +751,7 @@ void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
|
|||
handle->pipe.serv.accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
handle->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
|
@ -737,11 +760,8 @@ void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
|
|||
}
|
||||
|
||||
if ((handle->flags & UV_HANDLE_CONNECTION)
|
||||
&& handle->handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(handle->handle);
|
||||
handle->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
&& handle->handle != INVALID_HANDLE_VALUE)
|
||||
close_pipe(handle);
|
||||
}
|
||||
|
||||
|
||||
|
@ -786,7 +806,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
|
|||
return;
|
||||
}
|
||||
|
||||
if (uv_set_pipe_handle(loop, handle, req->pipeHandle, 0)) {
|
||||
if (uv_set_pipe_handle(loop, handle, req->pipeHandle, -1, 0)) {
|
||||
CloseHandle(req->pipeHandle);
|
||||
req->pipeHandle = INVALID_HANDLE_VALUE;
|
||||
SET_REQ_ERROR(req, GetLastError());
|
||||
|
@ -1770,8 +1790,7 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
|
|||
} else {
|
||||
/* This pipe is not readable. We can just close it to let the other end */
|
||||
/* know that we're done writing. */
|
||||
CloseHandle(handle->handle);
|
||||
handle->handle = INVALID_HANDLE_VALUE;
|
||||
close_pipe(handle);
|
||||
}
|
||||
|
||||
if (req->cb) {
|
||||
|
@ -1838,8 +1857,7 @@ static void eof_timer_cb(uv_timer_t* timer) {
|
|||
}
|
||||
|
||||
/* Force both ends off the pipe. */
|
||||
CloseHandle(pipe->handle);
|
||||
pipe->handle = INVALID_HANDLE_VALUE;
|
||||
close_pipe(pipe);
|
||||
|
||||
/* Stop reading, so the pending read that is going to fail will */
|
||||
/* not be reported to the user. */
|
||||
|
@ -1874,6 +1892,27 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
|
|||
FILE_ACCESS_INFORMATION access;
|
||||
DWORD duplex_flags = 0;
|
||||
|
||||
if (os_handle == INVALID_HANDLE_VALUE)
|
||||
return UV_EBADF;
|
||||
|
||||
/* In order to avoid closing a stdio file descriptor 0-2, duplicate the
|
||||
* underlying OS handle and forget about the original fd.
|
||||
* We could also opt to use the original OS handle and just never close it,
|
||||
* but then there would be no reliable way to cancel pending read operations
|
||||
* upon close.
|
||||
*/
|
||||
if (file <= 2) {
|
||||
if (!DuplicateHandle(INVALID_HANDLE_VALUE,
|
||||
os_handle,
|
||||
INVALID_HANDLE_VALUE,
|
||||
&os_handle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
file = -1;
|
||||
}
|
||||
|
||||
/* Determine what kind of permissions we have on this handle.
|
||||
* Cygwin opens the pipe in message mode, but we can support it,
|
||||
* just query the access flags and set the stream flags accordingly.
|
||||
|
@ -1899,7 +1938,11 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
|
|||
duplex_flags |= UV_HANDLE_READABLE;
|
||||
|
||||
if (os_handle == INVALID_HANDLE_VALUE ||
|
||||
uv_set_pipe_handle(pipe->loop, pipe, os_handle, duplex_flags) == -1) {
|
||||
uv_set_pipe_handle(pipe->loop,
|
||||
pipe,
|
||||
os_handle,
|
||||
file,
|
||||
duplex_flags) == -1) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -407,7 +407,7 @@ int uv__stdio_create(uv_loop_t* loop,
|
|||
stream_handle = ((uv_tty_t*) stream)->handle;
|
||||
crt_flags = FOPEN | FDEV;
|
||||
} else if (stream->type == UV_NAMED_PIPE &&
|
||||
stream->flags & UV_HANDLE_CONNECTED) {
|
||||
stream->flags & UV_HANDLE_CONNECTION) {
|
||||
stream_handle = ((uv_pipe_t*) stream)->handle;
|
||||
crt_flags = FOPEN | FPIPE;
|
||||
} else {
|
||||
|
|
|
@ -78,19 +78,27 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
|
|||
}
|
||||
|
||||
|
||||
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
SOCKET socket, int family, int imported) {
|
||||
static int uv_tcp_set_socket(uv_loop_t* loop,
|
||||
uv_tcp_t* handle,
|
||||
SOCKET socket,
|
||||
int family,
|
||||
int imported) {
|
||||
DWORD yes = 1;
|
||||
int non_ifs_lsp;
|
||||
int err;
|
||||
|
||||
assert(handle->socket == INVALID_SOCKET);
|
||||
if (handle->socket != INVALID_SOCKET)
|
||||
return UV_EBUSY;
|
||||
|
||||
/* Set the socket to nonblocking mode */
|
||||
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
|
||||
return WSAGetLastError();
|
||||
}
|
||||
|
||||
/* Make the socket non-inheritable */
|
||||
if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0))
|
||||
return GetLastError();
|
||||
|
||||
/* Associate it with the I/O completion port. */
|
||||
/* Use uv_handle_t pointer as completion key. */
|
||||
if (CreateIoCompletionPort((HANDLE)socket,
|
||||
|
@ -146,9 +154,18 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
|||
}
|
||||
|
||||
|
||||
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP);
|
||||
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) {
|
||||
int domain;
|
||||
|
||||
/* Use the lower 8 bits for the domain */
|
||||
domain = flags & 0xFF;
|
||||
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (flags & ~0xFF)
|
||||
return UV_EINVAL;
|
||||
|
||||
uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP);
|
||||
handle->tcp.serv.accept_reqs = NULL;
|
||||
handle->tcp.serv.pending_accepts = NULL;
|
||||
handle->socket = INVALID_SOCKET;
|
||||
|
@ -158,10 +175,39 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
|
|||
handle->tcp.serv.processed_accepts = 0;
|
||||
handle->delayed_error = 0;
|
||||
|
||||
/* If anything fails beyond this point we need to remove the handle from
|
||||
* the handle queue, since it was added by uv__handle_init in uv_stream_init.
|
||||
*/
|
||||
|
||||
if (domain != AF_UNSPEC) {
|
||||
SOCKET sock;
|
||||
DWORD err;
|
||||
|
||||
sock = socket(domain, SOCK_STREAM, 0);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
err = WSAGetLastError();
|
||||
QUEUE_REMOVE(&handle->handle_queue);
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
err = uv_tcp_set_socket(handle->loop, handle, sock, domain, 0);
|
||||
if (err) {
|
||||
closesocket(sock);
|
||||
QUEUE_REMOVE(&handle->handle_queue);
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
return uv_tcp_init_ex(loop, handle, AF_UNSPEC);
|
||||
}
|
||||
|
||||
|
||||
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
int err;
|
||||
unsigned int i;
|
||||
|
@ -267,13 +313,6 @@ static int uv_tcp_try_bind(uv_tcp_t* handle,
|
|||
return WSAGetLastError();
|
||||
}
|
||||
|
||||
/* Make the socket non-inheritable */
|
||||
if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
|
||||
err = GetLastError();
|
||||
closesocket(sock);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0);
|
||||
if (err) {
|
||||
closesocket(sock);
|
||||
|
@ -774,7 +813,7 @@ int uv_tcp_getsockname(const uv_tcp_t* handle,
|
|||
int* namelen) {
|
||||
int result;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
if (handle->socket == INVALID_SOCKET) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
|
@ -796,7 +835,7 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
|
|||
int* namelen) {
|
||||
int result;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
if (handle->socket == INVALID_SOCKET) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1165,12 +1204,6 @@ int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
|
|||
return WSAGetLastError();
|
||||
}
|
||||
|
||||
if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) {
|
||||
err = GetLastError();
|
||||
closesocket(socket);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = uv_tcp_set_socket(tcp->loop,
|
||||
tcp,
|
||||
socket,
|
||||
|
@ -1426,11 +1459,6 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
|
|||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
/* Make the socket non-inheritable */
|
||||
if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
err = uv_tcp_set_socket(handle->loop,
|
||||
handle,
|
||||
sock,
|
||||
|
|
|
@ -191,6 +191,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
|||
|
||||
|
||||
uv_thread_t uv_thread_self(void) {
|
||||
uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
|
||||
return (uv_thread_t) uv_key_get(&uv__current_thread_key);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#define MAX_INPUT_BUFFER_LENGTH 8192
|
||||
|
||||
|
||||
static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info);
|
||||
static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info);
|
||||
|
||||
|
||||
|
@ -96,6 +97,15 @@ static CRITICAL_SECTION uv_tty_output_lock;
|
|||
|
||||
static HANDLE uv_tty_output_handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
static WORD uv_tty_default_text_attributes =
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
|
||||
static char uv_tty_default_fg_color = 7;
|
||||
static char uv_tty_default_bg_color = 0;
|
||||
static char uv_tty_default_fg_bright = 0;
|
||||
static char uv_tty_default_bg_bright = 0;
|
||||
static char uv_tty_default_inverse = 0;
|
||||
|
||||
|
||||
void uv_console_init() {
|
||||
InitializeCriticalSection(&uv_tty_output_lock);
|
||||
|
@ -106,9 +116,26 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
|||
HANDLE handle;
|
||||
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
|
||||
|
||||
handle = (HANDLE) _get_osfhandle(fd);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
handle = (HANDLE) uv__get_osfhandle(fd);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return UV_EBADF;
|
||||
|
||||
if (fd <= 2) {
|
||||
/* In order to avoid closing a stdio file descriptor 0-2, duplicate the
|
||||
* underlying OS handle and forget about the original fd.
|
||||
* We could also opt to use the original OS handle and just never close it,
|
||||
* but then there would be no reliable way to cancel pending read operations
|
||||
* upon close.
|
||||
*/
|
||||
if (!DuplicateHandle(INVALID_HANDLE_VALUE,
|
||||
handle,
|
||||
INVALID_HANDLE_VALUE,
|
||||
&handle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
if (!readable) {
|
||||
|
@ -126,6 +153,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
|||
/* is received. */
|
||||
uv_tty_output_handle = handle;
|
||||
|
||||
/* Remember the original console text attributes. */
|
||||
uv_tty_capture_initial_style(&screen_buffer_info);
|
||||
|
||||
uv_tty_update_virtual_window(&screen_buffer_info);
|
||||
|
||||
LeaveCriticalSection(&uv_tty_output_lock);
|
||||
|
@ -136,6 +166,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
|||
uv_connection_init((uv_stream_t*) tty);
|
||||
|
||||
tty->handle = handle;
|
||||
tty->u.fd = fd;
|
||||
tty->reqs_pending = 0;
|
||||
tty->flags |= UV_HANDLE_BOUND;
|
||||
|
||||
|
@ -170,6 +201,62 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
|||
}
|
||||
|
||||
|
||||
/* Set the default console text attributes based on how the console was
|
||||
* configured when libuv started.
|
||||
*/
|
||||
static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) {
|
||||
static int style_captured = 0;
|
||||
|
||||
/* Only do this once.
|
||||
/* Assumption: Caller has acquired uv_tty_output_lock. */
|
||||
if (style_captured)
|
||||
return;
|
||||
|
||||
/* Save raw win32 attributes. */
|
||||
uv_tty_default_text_attributes = info->wAttributes;
|
||||
|
||||
/* Convert black text on black background to use white text. */
|
||||
if (uv_tty_default_text_attributes == 0)
|
||||
uv_tty_default_text_attributes = 7;
|
||||
|
||||
/* Convert Win32 attributes to ANSI colors. */
|
||||
uv_tty_default_fg_color = 0;
|
||||
uv_tty_default_bg_color = 0;
|
||||
uv_tty_default_fg_bright = 0;
|
||||
uv_tty_default_bg_bright = 0;
|
||||
uv_tty_default_inverse = 0;
|
||||
|
||||
if (uv_tty_default_text_attributes & FOREGROUND_RED)
|
||||
uv_tty_default_fg_color |= 1;
|
||||
|
||||
if (uv_tty_default_text_attributes & FOREGROUND_GREEN)
|
||||
uv_tty_default_fg_color |= 2;
|
||||
|
||||
if (uv_tty_default_text_attributes & FOREGROUND_BLUE)
|
||||
uv_tty_default_fg_color |= 4;
|
||||
|
||||
if (uv_tty_default_text_attributes & BACKGROUND_RED)
|
||||
uv_tty_default_bg_color |= 1;
|
||||
|
||||
if (uv_tty_default_text_attributes & BACKGROUND_GREEN)
|
||||
uv_tty_default_bg_color |= 2;
|
||||
|
||||
if (uv_tty_default_text_attributes & BACKGROUND_BLUE)
|
||||
uv_tty_default_bg_color |= 4;
|
||||
|
||||
if (uv_tty_default_text_attributes & FOREGROUND_INTENSITY)
|
||||
uv_tty_default_fg_bright = 1;
|
||||
|
||||
if (uv_tty_default_text_attributes & BACKGROUND_INTENSITY)
|
||||
uv_tty_default_bg_bright = 1;
|
||||
|
||||
if (uv_tty_default_text_attributes & COMMON_LVB_REVERSE_VIDEO)
|
||||
uv_tty_default_inverse = 1;
|
||||
|
||||
style_captured = 1;
|
||||
}
|
||||
|
||||
|
||||
int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
|
||||
DWORD flags;
|
||||
unsigned char was_reading;
|
||||
|
@ -1004,7 +1091,7 @@ static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,
|
|||
|
||||
static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
|
||||
const COORD origin = {0, 0};
|
||||
const WORD char_attrs = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
const WORD char_attrs = uv_tty_default_text_attributes;
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
DWORD count, written;
|
||||
|
||||
|
@ -1160,11 +1247,11 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
|
|||
|
||||
if (argc == 0) {
|
||||
/* Reset mode */
|
||||
fg_color = 7;
|
||||
bg_color = 0;
|
||||
fg_bright = 0;
|
||||
bg_bright = 0;
|
||||
inverse = 0;
|
||||
fg_color = uv_tty_default_fg_color;
|
||||
bg_color = uv_tty_default_bg_color;
|
||||
fg_bright = uv_tty_default_fg_bright;
|
||||
bg_bright = uv_tty_default_bg_bright;
|
||||
inverse = uv_tty_default_inverse;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
|
@ -1172,11 +1259,11 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
|
|||
|
||||
if (arg == 0) {
|
||||
/* Reset mode */
|
||||
fg_color = 7;
|
||||
bg_color = 0;
|
||||
fg_bright = 0;
|
||||
bg_bright = 0;
|
||||
inverse = 0;
|
||||
fg_color = uv_tty_default_fg_color;
|
||||
bg_color = uv_tty_default_bg_color;
|
||||
fg_bright = uv_tty_default_fg_bright;
|
||||
bg_bright = uv_tty_default_bg_bright;
|
||||
inverse = uv_tty_default_inverse;
|
||||
|
||||
} else if (arg == 1) {
|
||||
/* Foreground bright on */
|
||||
|
@ -1213,8 +1300,8 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
|
|||
|
||||
} else if (arg == 39) {
|
||||
/* Default text color */
|
||||
fg_color = 7;
|
||||
fg_bright = 0;
|
||||
fg_color = uv_tty_default_fg_color;
|
||||
fg_bright = uv_tty_default_fg_bright;
|
||||
|
||||
} else if (arg >= 40 && arg <= 47) {
|
||||
/* Set background color */
|
||||
|
@ -1222,8 +1309,8 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
|
|||
|
||||
} else if (arg == 49) {
|
||||
/* Default background color */
|
||||
bg_color = 0;
|
||||
bg_bright = 0;
|
||||
bg_color = uv_tty_default_bg_color;
|
||||
bg_bright = uv_tty_default_bg_bright;
|
||||
|
||||
} else if (arg >= 90 && arg <= 97) {
|
||||
/* Set bold foreground color */
|
||||
|
@ -1916,11 +2003,16 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||
|
||||
|
||||
void uv_tty_close(uv_tty_t* handle) {
|
||||
CloseHandle(handle->handle);
|
||||
assert(handle->u.fd == -1 || handle->u.fd > 2);
|
||||
if (handle->u.fd == -1)
|
||||
CloseHandle(handle->handle);
|
||||
else
|
||||
close(handle->u.fd);
|
||||
|
||||
if (handle->flags & UV_HANDLE_READING)
|
||||
uv_tty_read_stop(handle);
|
||||
|
||||
handle->u.fd = -1;
|
||||
handle->handle = INVALID_HANDLE_VALUE;
|
||||
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
uv__handle_closing(handle);
|
||||
|
|
|
@ -42,7 +42,7 @@ int uv_udp_getsockname(const uv_udp_t* handle,
|
|||
int* namelen) {
|
||||
int result;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
if (handle->socket == INVALID_SOCKET) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
|
|||
WSAPROTOCOL_INFOW info;
|
||||
int opt_len;
|
||||
|
||||
assert(handle->socket == INVALID_SOCKET);
|
||||
if (handle->socket != INVALID_SOCKET)
|
||||
return UV_EBUSY;
|
||||
|
||||
/* Set the socket to nonblocking mode */
|
||||
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
|
||||
|
@ -122,9 +123,18 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
|
|||
}
|
||||
|
||||
|
||||
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP);
|
||||
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
|
||||
int domain;
|
||||
|
||||
/* Use the lower 8 bits for the domain */
|
||||
domain = flags & 0xFF;
|
||||
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (flags & ~0xFF)
|
||||
return UV_EINVAL;
|
||||
|
||||
uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP);
|
||||
handle->socket = INVALID_SOCKET;
|
||||
handle->reqs_pending = 0;
|
||||
handle->activecnt = 0;
|
||||
|
@ -132,15 +142,42 @@ int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
|
|||
handle->func_wsarecvfrom = WSARecvFrom;
|
||||
handle->send_queue_size = 0;
|
||||
handle->send_queue_count = 0;
|
||||
|
||||
uv_req_init(loop, (uv_req_t*) &(handle->recv_req));
|
||||
handle->recv_req.type = UV_UDP_RECV;
|
||||
handle->recv_req.data = handle;
|
||||
|
||||
/* If anything fails beyond this point we need to remove the handle from
|
||||
* the handle queue, since it was added by uv__handle_init.
|
||||
*/
|
||||
|
||||
if (domain != AF_UNSPEC) {
|
||||
SOCKET sock;
|
||||
DWORD err;
|
||||
|
||||
sock = socket(domain, SOCK_DGRAM, 0);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
err = WSAGetLastError();
|
||||
QUEUE_REMOVE(&handle->handle_queue);
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
err = uv_udp_set_socket(handle->loop, handle, sock, domain);
|
||||
if (err) {
|
||||
closesocket(sock);
|
||||
QUEUE_REMOVE(&handle->handle_queue);
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
return uv_udp_init_ex(loop, handle, AF_UNSPEC);
|
||||
}
|
||||
|
||||
|
||||
void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
uv_udp_recv_stop(handle);
|
||||
closesocket(handle->socket);
|
||||
|
@ -190,25 +227,24 @@ static int uv_udp_maybe_bind(uv_udp_t* handle,
|
|||
closesocket(sock);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (flags & UV_UDP_REUSEADDR) {
|
||||
DWORD yes = 1;
|
||||
/* Set SO_REUSEADDR on the socket. */
|
||||
if (setsockopt(sock,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
(char*) &yes,
|
||||
sizeof yes) == SOCKET_ERROR) {
|
||||
err = WSAGetLastError();
|
||||
closesocket(sock);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr->sa_family == AF_INET6)
|
||||
handle->flags |= UV_HANDLE_IPV6;
|
||||
}
|
||||
|
||||
if (flags & UV_UDP_REUSEADDR) {
|
||||
DWORD yes = 1;
|
||||
/* Set SO_REUSEADDR on the socket. */
|
||||
if (setsockopt(handle->socket,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
(char*) &yes,
|
||||
sizeof yes) == SOCKET_ERROR) {
|
||||
err = WSAGetLastError();
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr->sa_family == AF_INET6)
|
||||
handle->flags |= UV_HANDLE_IPV6;
|
||||
|
||||
if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
|
||||
/* On windows IPV6ONLY is on by default. */
|
||||
/* If the user doesn't specify it libuv turns it off. */
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#define sync_stat(req, path) \
|
||||
do { \
|
||||
uv_fs_stat(uv_default_loop(), (req), (path), NULL); \
|
||||
uv_fs_stat(NULL, (req), (path), NULL); \
|
||||
uv_fs_req_cleanup((req)); \
|
||||
} \
|
||||
while (0)
|
||||
|
|
|
@ -304,7 +304,7 @@ static int pipe_echo_start(char* pipeName) {
|
|||
#ifndef _WIN32
|
||||
{
|
||||
uv_fs_t req;
|
||||
uv_fs_unlink(uv_default_loop(), &req, pipeName, NULL);
|
||||
uv_fs_unlink(NULL, &req, pipeName, NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,7 @@ int ipc_helper_tcp_connection(void);
|
|||
int ipc_send_recv_helper(void);
|
||||
int ipc_helper_bind_twice(void);
|
||||
int stdio_over_pipes_helper(void);
|
||||
int spawn_stdin_stdout(void);
|
||||
|
||||
static int maybe_run_test(int argc, char **argv);
|
||||
|
||||
|
@ -172,5 +173,9 @@ static int maybe_run_test(int argc, char **argv) {
|
|||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
if (strcmp(argv[1], "spawn_helper9") == 0) {
|
||||
return spawn_stdin_stdout();
|
||||
}
|
||||
|
||||
return run_test(argv[1], 0, 1);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
|
@ -173,6 +174,9 @@ int process_wait(process_info_t* vec, int n, int timeout) {
|
|||
process_info_t* p;
|
||||
dowait_args args;
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
unsigned int elapsed_ms;
|
||||
struct timeval timebase;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
|
||||
|
@ -199,20 +203,54 @@ int process_wait(process_info_t* vec, int n, int timeout) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
r = pthread_create(&tid, NULL, dowait, &args);
|
||||
if (pthread_attr_init(&attr))
|
||||
abort();
|
||||
|
||||
if (pthread_attr_setstacksize(&attr, 256 * 1024))
|
||||
abort();
|
||||
|
||||
r = pthread_create(&tid, &attr, dowait, &args);
|
||||
|
||||
if (pthread_attr_destroy(&attr))
|
||||
abort();
|
||||
|
||||
if (r) {
|
||||
perror("pthread_create()");
|
||||
retval = -1;
|
||||
goto terminate;
|
||||
}
|
||||
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = 0;
|
||||
if (gettimeofday(&timebase, NULL))
|
||||
abort();
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(args.pipe[0], &fds);
|
||||
tv = timebase;
|
||||
for (;;) {
|
||||
/* Check that gettimeofday() doesn't jump back in time. */
|
||||
assert(tv.tv_sec == timebase.tv_sec ||
|
||||
(tv.tv_sec == timebase.tv_sec && tv.tv_usec >= timebase.tv_usec));
|
||||
|
||||
r = select(args.pipe[0] + 1, &fds, NULL, NULL, &tv);
|
||||
elapsed_ms =
|
||||
(tv.tv_sec - timebase.tv_sec) * 1000 +
|
||||
(tv.tv_usec / 1000) -
|
||||
(timebase.tv_usec / 1000);
|
||||
|
||||
r = 0; /* Timeout. */
|
||||
if (elapsed_ms >= (unsigned) timeout)
|
||||
break;
|
||||
|
||||
tv.tv_sec = (timeout - elapsed_ms) / 1000;
|
||||
tv.tv_usec = (timeout - elapsed_ms) % 1000 * 1000;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(args.pipe[0], &fds);
|
||||
|
||||
r = select(args.pipe[0] + 1, &fds, NULL, NULL, &tv);
|
||||
if (!(r == -1 && errno == EINTR))
|
||||
break;
|
||||
|
||||
if (gettimeofday(&tv, NULL))
|
||||
abort();
|
||||
}
|
||||
|
||||
if (r == -1) {
|
||||
perror("select()");
|
||||
|
@ -229,15 +267,11 @@ int process_wait(process_info_t* vec, int n, int timeout) {
|
|||
kill(p->pid, SIGTERM);
|
||||
}
|
||||
retval = -2;
|
||||
|
||||
/* Wait for thread to finish. */
|
||||
r = pthread_join(tid, NULL);
|
||||
if (r) {
|
||||
perror("pthread_join");
|
||||
retval = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pthread_join(tid, NULL))
|
||||
abort();
|
||||
|
||||
terminate:
|
||||
close(args.pipe[0]);
|
||||
close(args.pipe[1]);
|
||||
|
|
|
@ -179,8 +179,8 @@ enum test_status {
|
|||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Define inline for MSVC */
|
||||
# ifdef _MSC_VER
|
||||
/* Define inline for MSVC<2015 */
|
||||
# if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
# define inline __inline
|
||||
# endif
|
||||
|
||||
|
|
|
@ -37,11 +37,15 @@
|
|||
|
||||
static uv_fs_event_t fs_event;
|
||||
static const char file_prefix[] = "fsevent-";
|
||||
static const int fs_event_file_count = 16;
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
static const char file_prefix_in_subdir[] = "subdir";
|
||||
#endif
|
||||
static uv_timer_t timer;
|
||||
static int timer_cb_called;
|
||||
static int close_cb_called;
|
||||
static const int fs_event_file_count = 128;
|
||||
static int fs_event_created;
|
||||
static int fs_event_removed;
|
||||
static int fs_event_cb_called;
|
||||
#if defined(PATH_MAX)
|
||||
static char fs_event_filename[PATH_MAX];
|
||||
|
@ -50,48 +54,45 @@ static char fs_event_filename[1024];
|
|||
#endif /* defined(PATH_MAX) */
|
||||
static int timer_cb_touch_called;
|
||||
|
||||
static void fs_event_unlink_files(uv_timer_t* handle);
|
||||
|
||||
static void create_dir(uv_loop_t* loop, const char* name) {
|
||||
static void create_dir(const char* name) {
|
||||
int r;
|
||||
uv_fs_t req;
|
||||
r = uv_fs_mkdir(loop, &req, name, 0755, NULL);
|
||||
r = uv_fs_mkdir(NULL, &req, name, 0755, NULL);
|
||||
ASSERT(r == 0 || r == UV_EEXIST);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
|
||||
static void create_file(uv_loop_t* loop, const char* name) {
|
||||
static void create_file(const char* name) {
|
||||
int r;
|
||||
uv_file file;
|
||||
uv_fs_t req;
|
||||
|
||||
r = uv_fs_open(loop, &req, name, O_WRONLY | O_CREAT,
|
||||
S_IWUSR | S_IRUSR, NULL);
|
||||
r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r >= 0);
|
||||
file = r;
|
||||
uv_fs_req_cleanup(&req);
|
||||
r = uv_fs_close(loop, &req, file, NULL);
|
||||
r = uv_fs_close(NULL, &req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
|
||||
static void touch_file(uv_loop_t* loop, const char* name) {
|
||||
static void touch_file(const char* name) {
|
||||
int r;
|
||||
uv_file file;
|
||||
uv_fs_t req;
|
||||
uv_buf_t buf;
|
||||
|
||||
r = uv_fs_open(loop, &req, name, O_RDWR, 0, NULL);
|
||||
r = uv_fs_open(NULL, &req, name, O_RDWR, 0, NULL);
|
||||
ASSERT(r >= 0);
|
||||
file = r;
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
buf = uv_buf_init("foo", 4);
|
||||
r = uv_fs_write(loop, &req, file, &buf, 1, -1, NULL);
|
||||
r = uv_fs_write(NULL, &req, file, &buf, 1, -1, NULL);
|
||||
ASSERT(r >= 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_close(loop, &req, file, NULL);
|
||||
r = uv_fs_close(NULL, &req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
|
@ -119,25 +120,6 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename,
|
|||
uv_close((uv_handle_t*)handle, close_cb);
|
||||
}
|
||||
|
||||
static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
int events,
|
||||
int status) {
|
||||
fs_event_cb_called++;
|
||||
ASSERT(handle == &fs_event);
|
||||
ASSERT(status == 0);
|
||||
ASSERT(events == UV_RENAME);
|
||||
ASSERT(filename == NULL ||
|
||||
strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0);
|
||||
|
||||
/* Stop watching dir when received events about all files:
|
||||
* both create and close events */
|
||||
if (fs_event_cb_called == 2 * fs_event_file_count) {
|
||||
ASSERT(0 == uv_fs_event_stop(handle));
|
||||
uv_close((uv_handle_t*) handle, close_cb);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* fs_event_get_filename(int i) {
|
||||
snprintf(fs_event_filename,
|
||||
sizeof(fs_event_filename),
|
||||
|
@ -148,40 +130,140 @@ static const char* fs_event_get_filename(int i) {
|
|||
}
|
||||
|
||||
static void fs_event_create_files(uv_timer_t* handle) {
|
||||
int i;
|
||||
/* Make sure we're not attempting to create files we do not intend */
|
||||
ASSERT(fs_event_created < fs_event_file_count);
|
||||
|
||||
/* Already created all files */
|
||||
if (fs_event_created == fs_event_file_count) {
|
||||
uv_close((uv_handle_t*) &timer, close_cb);
|
||||
return;
|
||||
/* Create the file */
|
||||
create_file(fs_event_get_filename(fs_event_created));
|
||||
|
||||
if (++fs_event_created < fs_event_file_count) {
|
||||
/* Create another file on a different event loop tick. We do it this way
|
||||
* to avoid fs events coalescing into one fs event. */
|
||||
ASSERT(0 == uv_timer_start(&timer, fs_event_create_files, 1, 0));
|
||||
}
|
||||
|
||||
/* Create all files */
|
||||
for (i = 0; i < 16; i++, fs_event_created++)
|
||||
create_file(handle->loop, fs_event_get_filename(i));
|
||||
|
||||
/* And unlink them */
|
||||
ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files, 50, 0));
|
||||
}
|
||||
|
||||
void fs_event_unlink_files(uv_timer_t* handle) {
|
||||
static void fs_event_unlink_files(uv_timer_t* handle) {
|
||||
int r;
|
||||
int i;
|
||||
|
||||
/* NOTE: handle might be NULL if invoked not as timer callback */
|
||||
if (handle == NULL) {
|
||||
/* Unlink all files */
|
||||
for (i = 0; i < 16; i++) {
|
||||
r = remove(fs_event_get_filename(i));
|
||||
if (handle != NULL)
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
} else {
|
||||
/* Make sure we're not attempting to remove files we do not intend */
|
||||
ASSERT(fs_event_removed < fs_event_file_count);
|
||||
|
||||
/* Unlink all files */
|
||||
for (i = 0; i < 16; i++) {
|
||||
r = remove(fs_event_get_filename(i));
|
||||
if (handle != NULL)
|
||||
ASSERT(r == 0);
|
||||
/* Remove the file */
|
||||
ASSERT(0 == remove(fs_event_get_filename(fs_event_removed)));
|
||||
|
||||
if (++fs_event_removed < fs_event_file_count) {
|
||||
/* Remove another file on a different event loop tick. We do it this way
|
||||
* to avoid fs events coalescing into one fs event. */
|
||||
ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/* And create them again */
|
||||
if (handle != NULL)
|
||||
ASSERT(0 == uv_timer_start(&timer, fs_event_create_files, 50, 0));
|
||||
}
|
||||
|
||||
static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
int events,
|
||||
int status) {
|
||||
fs_event_cb_called++;
|
||||
ASSERT(handle == &fs_event);
|
||||
ASSERT(status == 0);
|
||||
ASSERT(events == UV_CHANGE || UV_RENAME);
|
||||
ASSERT(filename == NULL ||
|
||||
strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0);
|
||||
|
||||
if (fs_event_created + fs_event_removed == fs_event_file_count) {
|
||||
/* Once we've processed all create events, delete all files */
|
||||
ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files, 1, 0));
|
||||
} else if (fs_event_cb_called == 2 * fs_event_file_count) {
|
||||
/* Once we've processed all create and delete events, stop watching */
|
||||
uv_close((uv_handle_t*) &timer, close_cb);
|
||||
uv_close((uv_handle_t*) handle, close_cb);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
static const char* fs_event_get_filename_in_subdir(int i) {
|
||||
snprintf(fs_event_filename,
|
||||
sizeof(fs_event_filename),
|
||||
"watch_dir/subdir/%s%d",
|
||||
file_prefix,
|
||||
i);
|
||||
return fs_event_filename;
|
||||
}
|
||||
|
||||
static void fs_event_create_files_in_subdir(uv_timer_t* handle) {
|
||||
/* Make sure we're not attempting to create files we do not intend */
|
||||
ASSERT(fs_event_created < fs_event_file_count);
|
||||
|
||||
/* Create the file */
|
||||
create_file(fs_event_get_filename_in_subdir(fs_event_created));
|
||||
|
||||
if (++fs_event_created < fs_event_file_count) {
|
||||
/* Create another file on a different event loop tick. We do it this way
|
||||
* to avoid fs events coalescing into one fs event. */
|
||||
ASSERT(0 == uv_timer_start(&timer, fs_event_create_files_in_subdir, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static void fs_event_unlink_files_in_subdir(uv_timer_t* handle) {
|
||||
int r;
|
||||
int i;
|
||||
|
||||
/* NOTE: handle might be NULL if invoked not as timer callback */
|
||||
if (handle == NULL) {
|
||||
/* Unlink all files */
|
||||
for (i = 0; i < 16; i++) {
|
||||
r = remove(fs_event_get_filename_in_subdir(i));
|
||||
if (handle != NULL)
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
} else {
|
||||
/* Make sure we're not attempting to remove files we do not intend */
|
||||
ASSERT(fs_event_removed < fs_event_file_count);
|
||||
|
||||
/* Remove the file */
|
||||
ASSERT(0 == remove(fs_event_get_filename_in_subdir(fs_event_removed)));
|
||||
|
||||
if (++fs_event_removed < fs_event_file_count) {
|
||||
/* Remove another file on a different event loop tick. We do it this way
|
||||
* to avoid fs events coalescing into one fs event. */
|
||||
ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
int events,
|
||||
int status) {
|
||||
fs_event_cb_called++;
|
||||
ASSERT(handle == &fs_event);
|
||||
ASSERT(status == 0);
|
||||
ASSERT(events == UV_CHANGE || UV_RENAME);
|
||||
ASSERT(filename == NULL ||
|
||||
strncmp(filename, file_prefix_in_subdir, sizeof(file_prefix_in_subdir) - 1) == 0);
|
||||
|
||||
if (fs_event_created + fs_event_removed == fs_event_file_count) {
|
||||
/* Once we've processed all create events, delete all files */
|
||||
ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0));
|
||||
} else if (fs_event_cb_called == 2 * fs_event_file_count) {
|
||||
/* Once we've processed all create and delete events, stop watching */
|
||||
uv_close((uv_handle_t*) &timer, close_cb);
|
||||
uv_close((uv_handle_t*) handle, close_cb);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename,
|
||||
int events, int status) {
|
||||
++fs_event_cb_called;
|
||||
|
@ -226,16 +308,16 @@ static void timer_cb_file(uv_timer_t* handle) {
|
|||
++timer_cb_called;
|
||||
|
||||
if (timer_cb_called == 1) {
|
||||
touch_file(handle->loop, "watch_dir/file1");
|
||||
touch_file("watch_dir/file1");
|
||||
} else {
|
||||
touch_file(handle->loop, "watch_dir/file2");
|
||||
touch_file("watch_dir/file2");
|
||||
uv_close((uv_handle_t*)handle, close_cb);
|
||||
}
|
||||
}
|
||||
|
||||
static void timer_cb_touch(uv_timer_t* timer) {
|
||||
uv_close((uv_handle_t*)timer, NULL);
|
||||
touch_file(timer->loop, "watch_file");
|
||||
touch_file("watch_file");
|
||||
timer_cb_touch_called++;
|
||||
}
|
||||
|
||||
|
@ -255,7 +337,7 @@ TEST_IMPL(fs_event_watch_dir) {
|
|||
remove("watch_dir/file2");
|
||||
remove("watch_dir/file1");
|
||||
remove("watch_dir/");
|
||||
create_dir(loop, "watch_dir");
|
||||
create_dir("watch_dir");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
|
@ -268,8 +350,7 @@ TEST_IMPL(fs_event_watch_dir) {
|
|||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(fs_event_cb_called == 2 * fs_event_file_count);
|
||||
ASSERT(fs_event_created == fs_event_file_count);
|
||||
ASSERT(fs_event_cb_called == fs_event_created + fs_event_removed);
|
||||
ASSERT(close_cb_called == 2);
|
||||
|
||||
/* Cleanup */
|
||||
|
@ -282,6 +363,50 @@ TEST_IMPL(fs_event_watch_dir) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_event_watch_dir_recursive) {
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
uv_loop_t* loop;
|
||||
int r;
|
||||
|
||||
/* Setup */
|
||||
loop = uv_default_loop();
|
||||
fs_event_unlink_files(NULL);
|
||||
remove("watch_dir/file2");
|
||||
remove("watch_dir/file1");
|
||||
remove("watch_dir/subdir");
|
||||
remove("watch_dir/");
|
||||
create_dir("watch_dir");
|
||||
create_dir("watch_dir/subdir");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
r = uv_fs_event_start(&fs_event, fs_event_cb_dir_multi_file_in_subdir, "watch_dir", UV_FS_EVENT_RECURSIVE);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT(r == 0);
|
||||
r = uv_timer_start(&timer, fs_event_create_files_in_subdir, 100, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(fs_event_cb_called == fs_event_created + fs_event_removed);
|
||||
ASSERT(close_cb_called == 2);
|
||||
|
||||
/* Cleanup */
|
||||
fs_event_unlink_files_in_subdir(NULL);
|
||||
remove("watch_dir/file2");
|
||||
remove("watch_dir/file1");
|
||||
remove("watch_dir/subdir");
|
||||
remove("watch_dir/");
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
#else
|
||||
RETURN_SKIP("Recursive directory watching not supported on this platform.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_event_watch_file) {
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
int r;
|
||||
|
@ -290,9 +415,9 @@ TEST_IMPL(fs_event_watch_file) {
|
|||
remove("watch_dir/file2");
|
||||
remove("watch_dir/file1");
|
||||
remove("watch_dir/");
|
||||
create_dir(loop, "watch_dir");
|
||||
create_file(loop, "watch_dir/file1");
|
||||
create_file(loop, "watch_dir/file2");
|
||||
create_dir("watch_dir");
|
||||
create_file("watch_dir/file1");
|
||||
create_file("watch_dir/file2");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
|
@ -348,7 +473,7 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
|
|||
|
||||
/* Setup */
|
||||
remove("watch_file");
|
||||
create_file(loop, "watch_file");
|
||||
create_file("watch_file");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
|
@ -389,8 +514,8 @@ TEST_IMPL(fs_event_no_callback_after_close) {
|
|||
/* Setup */
|
||||
remove("watch_dir/file1");
|
||||
remove("watch_dir/");
|
||||
create_dir(loop, "watch_dir");
|
||||
create_file(loop, "watch_dir/file1");
|
||||
create_dir("watch_dir");
|
||||
create_file("watch_dir/file1");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
|
@ -402,7 +527,7 @@ TEST_IMPL(fs_event_no_callback_after_close) {
|
|||
|
||||
|
||||
uv_close((uv_handle_t*)&fs_event, close_cb);
|
||||
touch_file(loop, "watch_dir/file1");
|
||||
touch_file("watch_dir/file1");
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(fs_event_cb_called == 0);
|
||||
|
@ -423,8 +548,8 @@ TEST_IMPL(fs_event_no_callback_on_close) {
|
|||
/* Setup */
|
||||
remove("watch_dir/file1");
|
||||
remove("watch_dir/");
|
||||
create_dir(loop, "watch_dir");
|
||||
create_file(loop, "watch_dir/file1");
|
||||
create_dir("watch_dir");
|
||||
create_file("watch_dir/file1");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
|
@ -497,8 +622,8 @@ TEST_IMPL(fs_event_close_with_pending_event) {
|
|||
|
||||
loop = uv_default_loop();
|
||||
|
||||
create_dir(loop, "watch_dir");
|
||||
create_file(loop, "watch_dir/file");
|
||||
create_dir("watch_dir");
|
||||
create_file("watch_dir/file");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
|
@ -506,7 +631,7 @@ TEST_IMPL(fs_event_close_with_pending_event) {
|
|||
ASSERT(r == 0);
|
||||
|
||||
/* Generate an fs event. */
|
||||
touch_file(loop, "watch_dir/file");
|
||||
touch_file("watch_dir/file");
|
||||
|
||||
uv_close((uv_handle_t*)&fs_event, close_cb);
|
||||
|
||||
|
@ -554,12 +679,12 @@ TEST_IMPL(fs_event_close_in_callback) {
|
|||
|
||||
loop = uv_default_loop();
|
||||
|
||||
create_dir(loop, "watch_dir");
|
||||
create_file(loop, "watch_dir/file1");
|
||||
create_file(loop, "watch_dir/file2");
|
||||
create_file(loop, "watch_dir/file3");
|
||||
create_file(loop, "watch_dir/file4");
|
||||
create_file(loop, "watch_dir/file5");
|
||||
create_dir("watch_dir");
|
||||
create_file("watch_dir/file1");
|
||||
create_file("watch_dir/file2");
|
||||
create_file("watch_dir/file3");
|
||||
create_file("watch_dir/file4");
|
||||
create_file("watch_dir/file5");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
|
@ -567,11 +692,11 @@ TEST_IMPL(fs_event_close_in_callback) {
|
|||
ASSERT(r == 0);
|
||||
|
||||
/* Generate a couple of fs events. */
|
||||
touch_file(loop, "watch_dir/file1");
|
||||
touch_file(loop, "watch_dir/file2");
|
||||
touch_file(loop, "watch_dir/file3");
|
||||
touch_file(loop, "watch_dir/file4");
|
||||
touch_file(loop, "watch_dir/file5");
|
||||
touch_file("watch_dir/file1");
|
||||
touch_file("watch_dir/file2");
|
||||
touch_file("watch_dir/file3");
|
||||
touch_file("watch_dir/file4");
|
||||
touch_file("watch_dir/file5");
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
|
@ -600,7 +725,7 @@ TEST_IMPL(fs_event_start_and_close) {
|
|||
|
||||
loop = uv_default_loop();
|
||||
|
||||
create_dir(loop, "watch_dir");
|
||||
create_dir("watch_dir");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event1);
|
||||
ASSERT(r == 0);
|
||||
|
@ -630,7 +755,7 @@ TEST_IMPL(fs_event_getpath) {
|
|||
char buf[1024];
|
||||
size_t len;
|
||||
|
||||
create_dir(loop, "watch_dir");
|
||||
create_dir("watch_dir");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT(r == 0);
|
||||
|
@ -692,7 +817,7 @@ TEST_IMPL(fs_event_error_reporting) {
|
|||
TEST_FILE_LIMIT(ARRAY_SIZE(loops) * 3);
|
||||
|
||||
remove("watch_dir/");
|
||||
create_dir(uv_default_loop(), "watch_dir");
|
||||
create_dir("watch_dir");
|
||||
|
||||
/* Create a lot of loops, and start FSEventStream in each of them.
|
||||
* Eventually, this should create enough streams to make FSEventStreamStart()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -66,6 +66,7 @@ TEST_DECLARE (tcp_write_fail)
|
|||
TEST_DECLARE (tcp_try_write)
|
||||
TEST_DECLARE (tcp_write_queue_order)
|
||||
TEST_DECLARE (tcp_open)
|
||||
TEST_DECLARE (tcp_open_twice)
|
||||
TEST_DECLARE (tcp_connect_error_after_write)
|
||||
TEST_DECLARE (tcp_shutdown_after_write)
|
||||
TEST_DECLARE (tcp_bind_error_addrinuse)
|
||||
|
@ -80,6 +81,10 @@ TEST_DECLARE (tcp_connect_error_fault)
|
|||
TEST_DECLARE (tcp_connect_timeout)
|
||||
TEST_DECLARE (tcp_close_while_connecting)
|
||||
TEST_DECLARE (tcp_close)
|
||||
TEST_DECLARE (tcp_create_early)
|
||||
TEST_DECLARE (tcp_create_early_bad_bind)
|
||||
TEST_DECLARE (tcp_create_early_bad_domain)
|
||||
TEST_DECLARE (tcp_create_early_accept)
|
||||
#ifndef _WIN32
|
||||
TEST_DECLARE (tcp_close_accept)
|
||||
TEST_DECLARE (tcp_oob)
|
||||
|
@ -95,6 +100,9 @@ TEST_DECLARE (tcp_bind6_error_inval)
|
|||
TEST_DECLARE (tcp_bind6_localhost_ok)
|
||||
TEST_DECLARE (udp_bind)
|
||||
TEST_DECLARE (udp_bind_reuseaddr)
|
||||
TEST_DECLARE (udp_create_early)
|
||||
TEST_DECLARE (udp_create_early_bad_bind)
|
||||
TEST_DECLARE (udp_create_early_bad_domain)
|
||||
TEST_DECLARE (udp_send_and_recv)
|
||||
TEST_DECLARE (udp_send_immediate)
|
||||
TEST_DECLARE (udp_send_unreachable)
|
||||
|
@ -110,10 +118,12 @@ TEST_DECLARE (udp_options)
|
|||
TEST_DECLARE (udp_options6)
|
||||
TEST_DECLARE (udp_no_autobind)
|
||||
TEST_DECLARE (udp_open)
|
||||
TEST_DECLARE (udp_open_twice)
|
||||
TEST_DECLARE (udp_try_send)
|
||||
TEST_DECLARE (pipe_bind_error_addrinuse)
|
||||
TEST_DECLARE (pipe_bind_error_addrnotavail)
|
||||
TEST_DECLARE (pipe_bind_error_inval)
|
||||
TEST_DECLARE (pipe_connect_multiple)
|
||||
TEST_DECLARE (pipe_listen_without_bind)
|
||||
TEST_DECLARE (pipe_connect_bad_name)
|
||||
TEST_DECLARE (pipe_connect_to_file)
|
||||
|
@ -121,6 +131,7 @@ TEST_DECLARE (pipe_connect_on_prepare)
|
|||
TEST_DECLARE (pipe_getsockname)
|
||||
TEST_DECLARE (pipe_getsockname_abstract)
|
||||
TEST_DECLARE (pipe_getsockname_blocking)
|
||||
TEST_DECLARE (pipe_pending_instances)
|
||||
TEST_DECLARE (pipe_sendmsg)
|
||||
TEST_DECLARE (pipe_server_close)
|
||||
TEST_DECLARE (connection_fail)
|
||||
|
@ -221,6 +232,7 @@ TEST_DECLARE (spawn_stdout_and_stderr_to_file_swap)
|
|||
TEST_DECLARE (spawn_auto_unref)
|
||||
TEST_DECLARE (spawn_closed_process_io)
|
||||
TEST_DECLARE (spawn_reads_child_path)
|
||||
TEST_DECLARE (spawn_inherit_streams)
|
||||
TEST_DECLARE (fs_poll)
|
||||
TEST_DECLARE (fs_poll_getpath)
|
||||
TEST_DECLARE (kill)
|
||||
|
@ -248,6 +260,7 @@ TEST_DECLARE (fs_file_open_append)
|
|||
TEST_DECLARE (fs_stat_missing_path)
|
||||
TEST_DECLARE (fs_read_file_eof)
|
||||
TEST_DECLARE (fs_event_watch_dir)
|
||||
TEST_DECLARE (fs_event_watch_dir_recursive)
|
||||
TEST_DECLARE (fs_event_watch_file)
|
||||
TEST_DECLARE (fs_event_watch_file_twice)
|
||||
TEST_DECLARE (fs_event_watch_file_current_dir)
|
||||
|
@ -264,6 +277,9 @@ TEST_DECLARE (fs_scandir_file)
|
|||
TEST_DECLARE (fs_open_dir)
|
||||
TEST_DECLARE (fs_rename_to_existing_file)
|
||||
TEST_DECLARE (fs_write_multiple_bufs)
|
||||
TEST_DECLARE (fs_read_write_null_arguments)
|
||||
TEST_DECLARE (fs_write_alotof_bufs)
|
||||
TEST_DECLARE (fs_write_alotof_bufs_with_offset)
|
||||
TEST_DECLARE (threadpool_queue_work_simple)
|
||||
TEST_DECLARE (threadpool_queue_work_einval)
|
||||
TEST_DECLARE (threadpool_multiple_event_loops)
|
||||
|
@ -289,8 +305,10 @@ TEST_DECLARE (ip6_addr_link_local)
|
|||
TEST_DECLARE (poll_close_doesnt_corrupt_stack)
|
||||
TEST_DECLARE (poll_closesocket)
|
||||
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
|
||||
#if !defined(USING_UV_SHARED)
|
||||
TEST_DECLARE (argument_escaping)
|
||||
TEST_DECLARE (environment_creation)
|
||||
#endif
|
||||
TEST_DECLARE (listen_with_simultaneous_accepts)
|
||||
TEST_DECLARE (listen_no_simultaneous_accepts)
|
||||
TEST_DECLARE (fs_stat_root)
|
||||
|
@ -393,6 +411,7 @@ TASK_LIST_START
|
|||
|
||||
TEST_ENTRY (tcp_open)
|
||||
TEST_HELPER (tcp_open, tcp4_echo_server)
|
||||
TEST_ENTRY (tcp_open_twice)
|
||||
|
||||
TEST_ENTRY (tcp_shutdown_after_write)
|
||||
TEST_HELPER (tcp_shutdown_after_write, tcp4_echo_server)
|
||||
|
@ -410,6 +429,10 @@ TASK_LIST_START
|
|||
TEST_ENTRY (tcp_connect_timeout)
|
||||
TEST_ENTRY (tcp_close_while_connecting)
|
||||
TEST_ENTRY (tcp_close)
|
||||
TEST_ENTRY (tcp_create_early)
|
||||
TEST_ENTRY (tcp_create_early_bad_bind)
|
||||
TEST_ENTRY (tcp_create_early_bad_domain)
|
||||
TEST_ENTRY (tcp_create_early_accept)
|
||||
#ifndef _WIN32
|
||||
TEST_ENTRY (tcp_close_accept)
|
||||
TEST_ENTRY (tcp_oob)
|
||||
|
@ -429,6 +452,9 @@ TASK_LIST_START
|
|||
|
||||
TEST_ENTRY (udp_bind)
|
||||
TEST_ENTRY (udp_bind_reuseaddr)
|
||||
TEST_ENTRY (udp_create_early)
|
||||
TEST_ENTRY (udp_create_early_bad_bind)
|
||||
TEST_ENTRY (udp_create_early_bad_domain)
|
||||
TEST_ENTRY (udp_send_and_recv)
|
||||
TEST_ENTRY (udp_send_immediate)
|
||||
TEST_ENTRY (udp_send_unreachable)
|
||||
|
@ -447,14 +473,17 @@ TASK_LIST_START
|
|||
|
||||
TEST_ENTRY (udp_open)
|
||||
TEST_HELPER (udp_open, udp4_echo_server)
|
||||
TEST_ENTRY (udp_open_twice)
|
||||
|
||||
TEST_ENTRY (pipe_bind_error_addrinuse)
|
||||
TEST_ENTRY (pipe_bind_error_addrnotavail)
|
||||
TEST_ENTRY (pipe_bind_error_inval)
|
||||
TEST_ENTRY (pipe_connect_multiple)
|
||||
TEST_ENTRY (pipe_listen_without_bind)
|
||||
TEST_ENTRY (pipe_getsockname)
|
||||
TEST_ENTRY (pipe_getsockname_abstract)
|
||||
TEST_ENTRY (pipe_getsockname_blocking)
|
||||
TEST_ENTRY (pipe_pending_instances)
|
||||
TEST_ENTRY (pipe_sendmsg)
|
||||
|
||||
TEST_ENTRY (connection_fail)
|
||||
|
@ -590,6 +619,7 @@ TASK_LIST_START
|
|||
TEST_ENTRY (spawn_auto_unref)
|
||||
TEST_ENTRY (spawn_closed_process_io)
|
||||
TEST_ENTRY (spawn_reads_child_path)
|
||||
TEST_ENTRY (spawn_inherit_streams)
|
||||
TEST_ENTRY (fs_poll)
|
||||
TEST_ENTRY (fs_poll_getpath)
|
||||
TEST_ENTRY (kill)
|
||||
|
@ -598,8 +628,10 @@ TASK_LIST_START
|
|||
TEST_ENTRY (poll_close_doesnt_corrupt_stack)
|
||||
TEST_ENTRY (poll_closesocket)
|
||||
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
|
||||
#if !defined(USING_UV_SHARED)
|
||||
TEST_ENTRY (argument_escaping)
|
||||
TEST_ENTRY (environment_creation)
|
||||
# endif
|
||||
TEST_ENTRY (listen_with_simultaneous_accepts)
|
||||
TEST_ENTRY (listen_no_simultaneous_accepts)
|
||||
TEST_ENTRY (fs_stat_root)
|
||||
|
@ -644,6 +676,7 @@ TASK_LIST_START
|
|||
TEST_ENTRY (fs_read_file_eof)
|
||||
TEST_ENTRY (fs_file_open_append)
|
||||
TEST_ENTRY (fs_event_watch_dir)
|
||||
TEST_ENTRY (fs_event_watch_dir_recursive)
|
||||
TEST_ENTRY (fs_event_watch_file)
|
||||
TEST_ENTRY (fs_event_watch_file_twice)
|
||||
TEST_ENTRY (fs_event_watch_file_current_dir)
|
||||
|
@ -660,6 +693,9 @@ TASK_LIST_START
|
|||
TEST_ENTRY (fs_open_dir)
|
||||
TEST_ENTRY (fs_rename_to_existing_file)
|
||||
TEST_ENTRY (fs_write_multiple_bufs)
|
||||
TEST_ENTRY (fs_write_alotof_bufs)
|
||||
TEST_ENTRY (fs_write_alotof_bufs_with_offset)
|
||||
TEST_ENTRY (fs_read_write_null_arguments)
|
||||
TEST_ENTRY (threadpool_queue_work_simple)
|
||||
TEST_ENTRY (threadpool_queue_work_einval)
|
||||
TEST_ENTRY (threadpool_multiple_event_loops)
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/* Copyright (c) 2015 Saúl Ibarra Corretgé <saghul@gmail.com>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static int connection_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
|
||||
#define NUM_CLIENTS 4
|
||||
|
||||
typedef struct {
|
||||
uv_pipe_t pipe_handle;
|
||||
uv_connect_t conn_req;
|
||||
} client_t;
|
||||
|
||||
static uv_pipe_t server_handle;
|
||||
static client_t clients[NUM_CLIENTS];
|
||||
static uv_pipe_t connections[NUM_CLIENTS];
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* server, int status) {
|
||||
int r;
|
||||
uv_pipe_t* conn;
|
||||
ASSERT(status == 0);
|
||||
|
||||
conn = &connections[connection_cb_called];
|
||||
r = uv_pipe_init(server->loop, conn, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)conn);
|
||||
ASSERT(r == 0);
|
||||
|
||||
if (++connection_cb_called == NUM_CLIENTS &&
|
||||
connect_cb_called == NUM_CLIENTS) {
|
||||
uv_stop(server->loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* connect_req, int status) {
|
||||
ASSERT(status == 0);
|
||||
if (++connect_cb_called == NUM_CLIENTS &&
|
||||
connection_cb_called == NUM_CLIENTS) {
|
||||
uv_stop(connect_req->handle->loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_connect_multiple) {
|
||||
int i;
|
||||
int r;
|
||||
uv_loop_t* loop;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
r = uv_pipe_init(loop, &server_handle, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_bind(&server_handle, TEST_PIPENAME);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server_handle, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
for (i = 0; i < NUM_CLIENTS; i++) {
|
||||
r = uv_pipe_init(loop, &clients[i].pipe_handle, 0);
|
||||
ASSERT(r == 0);
|
||||
uv_pipe_connect(&clients[i].conn_req,
|
||||
&clients[i].pipe_handle,
|
||||
TEST_PIPENAME,
|
||||
connect_cb);
|
||||
}
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
ASSERT(connection_cb_called == NUM_CLIENTS);
|
||||
ASSERT(connect_cb_called == NUM_CLIENTS);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (c) 2015 Saúl Ibarra Corretgé <saghul@gmail.com>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* server, int status) {
|
||||
ASSERT(0 && "this will never be called");
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_pending_instances) {
|
||||
int r;
|
||||
uv_pipe_t pipe_handle;
|
||||
uv_loop_t* loop;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
r = uv_pipe_init(loop, &pipe_handle, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_pipe_pending_instances(&pipe_handle, 8);
|
||||
|
||||
r = uv_pipe_bind(&pipe_handle, TEST_PIPENAME);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_pipe_pending_instances(&pipe_handle, 16);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&pipe_handle, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_close((uv_handle_t*)&pipe_handle, NULL);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
|
@ -185,6 +185,7 @@ static void loop_creating_worker(void* context) {
|
|||
ASSERT(r == 0);
|
||||
|
||||
uv_loop_close(loop);
|
||||
free(loop);
|
||||
|
||||
increment_counter(&loop_creation_counter);
|
||||
} while (!stop);
|
||||
|
|
|
@ -277,7 +277,7 @@ TEST_IMPL(spawn_stdout_to_file) {
|
|||
|
||||
init_process_options("spawn_helper2", exit_cb);
|
||||
|
||||
r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR,
|
||||
r = uv_fs_open(NULL, &fs_req, "stdout_file", O_CREAT | O_RDWR,
|
||||
S_IRUSR | S_IWUSR, NULL);
|
||||
ASSERT(r != -1);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
@ -300,11 +300,11 @@ TEST_IMPL(spawn_stdout_to_file) {
|
|||
ASSERT(close_cb_called == 1);
|
||||
|
||||
buf = uv_buf_init(output, sizeof(output));
|
||||
r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
|
||||
r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
|
||||
ASSERT(r == 12);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
|
||||
r = uv_fs_close(NULL, &fs_req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
|
@ -331,7 +331,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
|
|||
|
||||
init_process_options("spawn_helper6", exit_cb);
|
||||
|
||||
r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR,
|
||||
r = uv_fs_open(NULL, &fs_req, "stdout_file", O_CREAT | O_RDWR,
|
||||
S_IRUSR | S_IWUSR, NULL);
|
||||
ASSERT(r != -1);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
@ -356,11 +356,11 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
|
|||
ASSERT(close_cb_called == 1);
|
||||
|
||||
buf = uv_buf_init(output, sizeof(output));
|
||||
r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
|
||||
r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
|
||||
ASSERT(r == 27);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
|
||||
r = uv_fs_close(NULL, &fs_req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
|
@ -389,7 +389,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file2) {
|
|||
init_process_options("spawn_helper6", exit_cb);
|
||||
|
||||
/* Replace stderr with our file */
|
||||
r = uv_fs_open(uv_default_loop(),
|
||||
r = uv_fs_open(NULL,
|
||||
&fs_req,
|
||||
"stdout_file",
|
||||
O_CREAT | O_RDWR,
|
||||
|
@ -418,11 +418,11 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file2) {
|
|||
ASSERT(close_cb_called == 1);
|
||||
|
||||
buf = uv_buf_init(output, sizeof(output));
|
||||
r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
|
||||
r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
|
||||
ASSERT(r == 27);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
|
||||
r = uv_fs_close(NULL, &fs_req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
|
@ -456,7 +456,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
|
|||
init_process_options("spawn_helper6", exit_cb);
|
||||
|
||||
/* open 'stdout_file' and replace STDOUT_FILENO with it */
|
||||
r = uv_fs_open(uv_default_loop(),
|
||||
r = uv_fs_open(NULL,
|
||||
&fs_req,
|
||||
"stdout_file",
|
||||
O_CREAT | O_RDWR,
|
||||
|
@ -468,7 +468,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
|
|||
ASSERT(stdout_file != -1);
|
||||
|
||||
/* open 'stderr_file' and replace STDERR_FILENO with it */
|
||||
r = uv_fs_open(uv_default_loop(), &fs_req, "stderr_file", O_CREAT | O_RDWR,
|
||||
r = uv_fs_open(NULL, &fs_req, "stderr_file", O_CREAT | O_RDWR,
|
||||
S_IRUSR | S_IWUSR, NULL);
|
||||
ASSERT(r != -1);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
@ -497,11 +497,11 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
|
|||
buf = uv_buf_init(output, sizeof(output));
|
||||
|
||||
/* check the content of stdout_file */
|
||||
r = uv_fs_read(uv_default_loop(), &fs_req, stdout_file, &buf, 1, 0, NULL);
|
||||
r = uv_fs_read(NULL, &fs_req, stdout_file, &buf, 1, 0, NULL);
|
||||
ASSERT(r >= 15);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
r = uv_fs_close(uv_default_loop(), &fs_req, stdout_file, NULL);
|
||||
r = uv_fs_close(NULL, &fs_req, stdout_file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
|
@ -509,11 +509,11 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
|
|||
ASSERT(strncmp("hello errworld\n", output, 15) == 0);
|
||||
|
||||
/* check the content of stderr_file */
|
||||
r = uv_fs_read(uv_default_loop(), &fs_req, stderr_file, &buf, 1, 0, NULL);
|
||||
r = uv_fs_read(NULL, &fs_req, stderr_file, &buf, 1, 0, NULL);
|
||||
ASSERT(r >= 12);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
r = uv_fs_close(uv_default_loop(), &fs_req, stderr_file, NULL);
|
||||
r = uv_fs_close(NULL, &fs_req, stderr_file, NULL);
|
||||
ASSERT(r == 0);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
|
@ -994,6 +994,7 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
|
|||
}
|
||||
|
||||
|
||||
#if !defined(USING_UV_SHARED)
|
||||
int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr);
|
||||
WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target);
|
||||
|
||||
|
@ -1196,6 +1197,7 @@ TEST_IMPL(environment_creation) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Regression test for issue #909 */
|
||||
TEST_IMPL(spawn_with_an_odd_path) {
|
||||
|
@ -1397,8 +1399,9 @@ TEST_IMPL(spawn_fs_open) {
|
|||
uv_buf_t buf;
|
||||
uv_stdio_container_t stdio[1];
|
||||
|
||||
fd = uv_fs_open(uv_default_loop(), &fs_req, "/dev/null", O_RDWR, 0, NULL);
|
||||
fd = uv_fs_open(NULL, &fs_req, "/dev/null", O_RDWR, 0, NULL);
|
||||
ASSERT(fd >= 0);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
init_process_options("spawn_helper8", exit_cb);
|
||||
|
||||
|
@ -1415,7 +1418,7 @@ TEST_IMPL(spawn_fs_open) {
|
|||
ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb));
|
||||
|
||||
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
ASSERT(0 == uv_fs_close(uv_default_loop(), &fs_req, fd, NULL));
|
||||
ASSERT(0 == uv_fs_close(NULL, &fs_req, fd, NULL));
|
||||
|
||||
ASSERT(exit_cb_called == 1);
|
||||
ASSERT(close_cb_called == 2); /* One for `in`, one for process */
|
||||
|
@ -1540,3 +1543,164 @@ TEST_IMPL(spawn_reads_child_path) {
|
|||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static int mpipe(int *fds) {
|
||||
if (pipe(fds) == -1)
|
||||
return -1;
|
||||
if (fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
|
||||
fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int mpipe(int *fds) {
|
||||
SECURITY_ATTRIBUTES attr;
|
||||
HANDLE readh, writeh;
|
||||
attr.nLength = sizeof(attr);
|
||||
attr.lpSecurityDescriptor = NULL;
|
||||
attr.bInheritHandle = FALSE;
|
||||
if (!CreatePipe(&readh, &writeh, &attr, 0))
|
||||
return -1;
|
||||
fds[0] = _open_osfhandle((intptr_t)readh, 0);
|
||||
fds[1] = _open_osfhandle((intptr_t)writeh, 0);
|
||||
if (fds[0] == -1 || fds[1] == -1) {
|
||||
CloseHandle(readh);
|
||||
CloseHandle(writeh);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
TEST_IMPL(spawn_inherit_streams) {
|
||||
uv_process_t child_req;
|
||||
uv_stdio_container_t child_stdio[2];
|
||||
int fds_stdin[2];
|
||||
int fds_stdout[2];
|
||||
uv_pipe_t pipe_stdin_child;
|
||||
uv_pipe_t pipe_stdout_child;
|
||||
uv_pipe_t pipe_stdin_parent;
|
||||
uv_pipe_t pipe_stdout_parent;
|
||||
unsigned char ubuf[OUTPUT_SIZE - 1];
|
||||
uv_buf_t buf;
|
||||
unsigned int i;
|
||||
int r;
|
||||
uv_write_t write_req;
|
||||
uv_loop_t* loop;
|
||||
|
||||
init_process_options("spawn_helper9", exit_cb);
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(uv_pipe_init(loop, &pipe_stdin_child, 0) == 0);
|
||||
ASSERT(uv_pipe_init(loop, &pipe_stdout_child, 0) == 0);
|
||||
ASSERT(uv_pipe_init(loop, &pipe_stdin_parent, 0) == 0);
|
||||
ASSERT(uv_pipe_init(loop, &pipe_stdout_parent, 0) == 0);
|
||||
|
||||
ASSERT(mpipe(fds_stdin) != -1);
|
||||
ASSERT(mpipe(fds_stdout) != -1);
|
||||
|
||||
ASSERT(uv_pipe_open(&pipe_stdin_child, fds_stdin[0]) == 0);
|
||||
ASSERT(uv_pipe_open(&pipe_stdout_child, fds_stdout[1]) == 0);
|
||||
ASSERT(uv_pipe_open(&pipe_stdin_parent, fds_stdin[1]) == 0);
|
||||
ASSERT(uv_pipe_open(&pipe_stdout_parent, fds_stdout[0]) == 0);
|
||||
|
||||
child_stdio[0].flags = UV_INHERIT_STREAM;
|
||||
child_stdio[0].data.stream = (uv_stream_t *)&pipe_stdin_child;
|
||||
|
||||
child_stdio[1].flags = UV_INHERIT_STREAM;
|
||||
child_stdio[1].data.stream = (uv_stream_t *)&pipe_stdout_child;
|
||||
|
||||
options.stdio = child_stdio;
|
||||
options.stdio_count = 2;
|
||||
|
||||
ASSERT(uv_spawn(loop, &child_req, &options) == 0);
|
||||
|
||||
uv_close((uv_handle_t*)&pipe_stdin_child, NULL);
|
||||
uv_close((uv_handle_t*)&pipe_stdout_child, NULL);
|
||||
|
||||
buf = uv_buf_init((char*)ubuf, sizeof ubuf);
|
||||
for (i = 0; i < sizeof ubuf; ++i)
|
||||
ubuf[i] = i & 255u;
|
||||
memset(output, 0, sizeof ubuf);
|
||||
|
||||
r = uv_write(&write_req,
|
||||
(uv_stream_t*)&pipe_stdin_parent,
|
||||
&buf,
|
||||
1,
|
||||
write_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*)&pipe_stdout_parent, on_alloc, on_read);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(exit_cb_called == 1);
|
||||
ASSERT(close_cb_called == 3);
|
||||
|
||||
r = memcmp(ubuf, output, sizeof ubuf);
|
||||
ASSERT(r == 0);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper for child process of spawn_inherit_streams */
|
||||
#ifndef _WIN32
|
||||
int spawn_stdin_stdout(void) {
|
||||
char buf[1024];
|
||||
char* pbuf;
|
||||
for (;;) {
|
||||
ssize_t r, w, c;
|
||||
do {
|
||||
r = read(0, buf, sizeof buf);
|
||||
} while (r == -1 && errno == EINTR);
|
||||
if (r == 0) {
|
||||
return 1;
|
||||
}
|
||||
ASSERT(r > 0);
|
||||
c = r;
|
||||
pbuf = buf;
|
||||
while (c) {
|
||||
do {
|
||||
w = write(1, pbuf, (size_t)c);
|
||||
} while (w == -1 && errno == EINTR);
|
||||
ASSERT(w >= 0);
|
||||
pbuf = pbuf + w;
|
||||
c = c - w;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
#else
|
||||
int spawn_stdin_stdout(void) {
|
||||
char buf[1024];
|
||||
char* pbuf;
|
||||
HANDLE h_stdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
ASSERT(h_stdin != INVALID_HANDLE_VALUE);
|
||||
ASSERT(h_stdout != INVALID_HANDLE_VALUE);
|
||||
for (;;) {
|
||||
DWORD n_read;
|
||||
DWORD n_written;
|
||||
DWORD to_write;
|
||||
if (!ReadFile(h_stdin, buf, sizeof buf, &n_read, NULL)) {
|
||||
ASSERT(GetLastError() == ERROR_BROKEN_PIPE);
|
||||
return 1;
|
||||
}
|
||||
to_write = n_read;
|
||||
pbuf = buf;
|
||||
while (to_write) {
|
||||
ASSERT(WriteFile(h_stdout, pbuf, to_write, &n_written, NULL));
|
||||
to_write -= n_written;
|
||||
pbuf += n_written;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
|
|
@ -59,14 +59,18 @@ TEST_IMPL(tcp_close_while_connecting) {
|
|||
uv_connect_t connect_req;
|
||||
struct sockaddr_in addr;
|
||||
uv_loop_t* loop;
|
||||
int r;
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(0 == uv_ip4_addr("1.2.3.4", TEST_PORT, &addr));
|
||||
ASSERT(0 == uv_tcp_init(loop, &tcp_handle));
|
||||
ASSERT(0 == uv_tcp_connect(&connect_req,
|
||||
&tcp_handle,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb));
|
||||
r = uv_tcp_connect(&connect_req,
|
||||
&tcp_handle,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb);
|
||||
if (r == UV_ENETUNREACH)
|
||||
RETURN_SKIP("Network unreachable.");
|
||||
ASSERT(r == 0);
|
||||
ASSERT(0 == uv_timer_init(loop, &timer1_handle));
|
||||
ASSERT(0 == uv_timer_start(&timer1_handle, timer1_cb, 50, 0));
|
||||
ASSERT(0 == uv_timer_init(loop, &timer2_handle));
|
||||
|
|
|
@ -79,6 +79,8 @@ TEST_IMPL(tcp_connect_timeout) {
|
|||
&conn,
|
||||
(const struct sockaddr*) &addr,
|
||||
connect_cb);
|
||||
if (r == UV_ENETUNREACH)
|
||||
RETURN_SKIP("Network unreachable.");
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/* Copyright (c) 2015 Saúl Ibarra Corretgé <saghul@gmail.com>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define INVALID_FD (INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
# define INVALID_FD (-1)
|
||||
#endif
|
||||
|
||||
|
||||
static void on_connect(uv_connect_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
uv_close((uv_handle_t*) req->handle, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void on_connection(uv_stream_t* server, int status) {
|
||||
uv_tcp_t* handle;
|
||||
int r;
|
||||
|
||||
ASSERT(status == 0);
|
||||
|
||||
handle = malloc(sizeof(*handle));
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
r = uv_tcp_init_ex(server->loop, handle, AF_INET);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)handle);
|
||||
ASSERT(r == UV_EBUSY);
|
||||
|
||||
uv_close((uv_handle_t*) server, NULL);
|
||||
uv_close((uv_handle_t*) handle, (uv_close_cb)free);
|
||||
}
|
||||
|
||||
|
||||
static void tcp_listener(uv_loop_t* loop, uv_tcp_t* server) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init(loop, server);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*) server, 128, on_connection);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void tcp_connector(uv_loop_t* loop, uv_tcp_t* client, uv_connect_t* req) {
|
||||
struct sockaddr_in server_addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
|
||||
|
||||
r = uv_tcp_init(loop, client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_connect(req,
|
||||
client,
|
||||
(const struct sockaddr*) &server_addr,
|
||||
on_connect);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_create_early) {
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr_in sockname;
|
||||
uv_tcp_t client;
|
||||
uv_os_fd_t fd;
|
||||
int r, namelen;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init_ex(uv_default_loop(), &client, AF_INET);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_fileno((const uv_handle_t*) &client, &fd);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(fd != INVALID_FD);
|
||||
|
||||
/* Windows returns WSAEINVAL if the socket is not bound */
|
||||
#ifndef _WIN32
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(sockname.sin_family == AF_INET);
|
||||
#endif
|
||||
|
||||
r = uv_tcp_bind(&client, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(memcmp(&addr.sin_addr,
|
||||
&sockname.sin_addr,
|
||||
sizeof(addr.sin_addr)) == 0);
|
||||
|
||||
uv_close((uv_handle_t*) &client, NULL);
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_create_early_bad_bind) {
|
||||
struct sockaddr_in addr;
|
||||
uv_tcp_t client;
|
||||
uv_os_fd_t fd;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init_ex(uv_default_loop(), &client, AF_INET6);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_fileno((const uv_handle_t*) &client, &fd);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(fd != INVALID_FD);
|
||||
|
||||
/* Windows returns WSAEINVAL if the socket is not bound */
|
||||
#ifndef _WIN32
|
||||
{
|
||||
int namelen;
|
||||
struct sockaddr_in6 sockname;
|
||||
namelen = sizeof sockname;
|
||||
r = uv_tcp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(sockname.sin6_family == AF_INET6);
|
||||
}
|
||||
#endif
|
||||
|
||||
r = uv_tcp_bind(&client, (const struct sockaddr*) &addr, 0);
|
||||
#ifndef _WIN32
|
||||
ASSERT(r == UV_EINVAL);
|
||||
#else
|
||||
ASSERT(r == UV_EFAULT);
|
||||
#endif
|
||||
|
||||
uv_close((uv_handle_t*) &client, NULL);
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_create_early_bad_domain) {
|
||||
uv_tcp_t client;
|
||||
int r;
|
||||
|
||||
r = uv_tcp_init_ex(uv_default_loop(), &client, 47);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
r = uv_tcp_init_ex(uv_default_loop(), &client, 1024);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_create_early_accept) {
|
||||
uv_tcp_t client, server;
|
||||
uv_connect_t connect_req;
|
||||
|
||||
tcp_listener(uv_default_loop(), &server);
|
||||
tcp_connector(uv_default_loop(), &client, &connect_req);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
|
@ -71,6 +71,17 @@ static uv_os_sock_t create_tcp_socket(void) {
|
|||
}
|
||||
|
||||
|
||||
static void close_socket(uv_os_sock_t sock) {
|
||||
int r;
|
||||
#ifdef _WIN32
|
||||
r = closesocket(sock);
|
||||
#else
|
||||
r = close(sock);
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
|
@ -180,3 +191,30 @@ TEST_IMPL(tcp_open) {
|
|||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_open_twice) {
|
||||
uv_tcp_t client;
|
||||
uv_os_sock_t sock1, sock2;
|
||||
int r;
|
||||
|
||||
startup();
|
||||
sock1 = create_tcp_socket();
|
||||
sock2 = create_tcp_socket();
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_open(&client, sock1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_open(&client, sock2);
|
||||
ASSERT(r == UV_EBUSY);
|
||||
close_socket(sock2);
|
||||
|
||||
uv_close((uv_handle_t*) &client, NULL);
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/* Copyright (c) 2015, Santiago Gimeno <santiago.gimeno@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static uv_tcp_t tcp_server;
|
||||
static uv_tcp_t tcp_client;
|
||||
static uv_tcp_t tcp_server_client;
|
||||
static uv_connect_t connect_req;
|
||||
static uv_write_t write_req;
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle,
|
||||
size_t size,
|
||||
uv_buf_t* buf) {
|
||||
buf->base = malloc(size);
|
||||
buf->len = size;
|
||||
}
|
||||
|
||||
static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
|
||||
free(buf->base);
|
||||
ASSERT(nread == UV_EOF);
|
||||
}
|
||||
|
||||
static void on_connect(uv_connect_t* req, int status) {
|
||||
int r;
|
||||
uv_buf_t outbuf;
|
||||
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
|
||||
outbuf = uv_buf_init("ping", 4);
|
||||
r = uv_write(&write_req, (uv_stream_t*) req->handle, &outbuf, 1, NULL);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*) req->handle, alloc_cb, read_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
static void on_connection(uv_stream_t* server, int status) {
|
||||
int r;
|
||||
|
||||
ASSERT(status == 0);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server_client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*) &tcp_server_client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_close((uv_handle_t*) &tcp_server_client, NULL);
|
||||
uv_close((uv_handle_t*) &tcp_server, NULL);
|
||||
}
|
||||
|
||||
static void start_server(void) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*) &tcp_server, SOMAXCONN, on_connection);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
static void start_client(void) {
|
||||
struct sockaddr_in addr;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &tcp_client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_connect(&connect_req,
|
||||
&tcp_client,
|
||||
(const struct sockaddr*) &addr,
|
||||
on_connect);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_squelch_connreset) {
|
||||
|
||||
start_server();
|
||||
|
||||
start_client();
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
|
@ -279,10 +279,12 @@ TEST_IMPL(threadpool_cancel_fs) {
|
|||
uv_fs_t reqs[25];
|
||||
uv_loop_t* loop;
|
||||
unsigned n;
|
||||
uv_buf_t iov;
|
||||
|
||||
INIT_CANCEL_INFO(&ci, reqs);
|
||||
loop = uv_default_loop();
|
||||
saturate_threadpool();
|
||||
iov = uv_buf_init(NULL, 0);
|
||||
|
||||
/* Needs to match ARRAY_SIZE(fs_reqs). */
|
||||
n = 0;
|
||||
|
@ -300,7 +302,7 @@ TEST_IMPL(threadpool_cancel_fs) {
|
|||
ASSERT(0 == uv_fs_lstat(loop, reqs + n++, "/", fs_cb));
|
||||
ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_open(loop, reqs + n++, "/", 0, 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, NULL, 0, 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, &iov, 1, 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb));
|
||||
ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb));
|
||||
|
@ -310,7 +312,7 @@ TEST_IMPL(threadpool_cancel_fs) {
|
|||
ASSERT(0 == uv_fs_symlink(loop, reqs + n++, "/", "/", 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_unlink(loop, reqs + n++, "/", fs_cb));
|
||||
ASSERT(0 == uv_fs_utime(loop, reqs + n++, "/", 0, 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_write(loop, reqs + n++, 0, NULL, 0, 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_write(loop, reqs + n++, 0, &iov, 1, 0, fs_cb));
|
||||
ASSERT(n == ARRAY_SIZE(reqs));
|
||||
|
||||
ASSERT(0 == uv_timer_init(loop, &ci.timer_handle));
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/* Copyright (c) 2015 Saúl Ibarra Corretgé <saghul@gmail.com>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define INVALID_FD (INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
# define INVALID_FD (-1)
|
||||
#endif
|
||||
|
||||
|
||||
TEST_IMPL(udp_create_early) {
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr_in sockname;
|
||||
uv_udp_t client;
|
||||
uv_os_fd_t fd;
|
||||
int r, namelen;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_udp_init_ex(uv_default_loop(), &client, AF_INET);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_fileno((const uv_handle_t*) &client, &fd);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(fd != INVALID_FD);
|
||||
|
||||
/* Windows returns WSAEINVAL if the socket is not bound */
|
||||
#ifndef _WIN32
|
||||
namelen = sizeof sockname;
|
||||
r = uv_udp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(sockname.sin_family == AF_INET);
|
||||
#endif
|
||||
|
||||
r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
namelen = sizeof sockname;
|
||||
r = uv_udp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(memcmp(&addr.sin_addr,
|
||||
&sockname.sin_addr,
|
||||
sizeof(addr.sin_addr)) == 0);
|
||||
|
||||
uv_close((uv_handle_t*) &client, NULL);
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(udp_create_early_bad_bind) {
|
||||
struct sockaddr_in addr;
|
||||
uv_udp_t client;
|
||||
uv_os_fd_t fd;
|
||||
int r;
|
||||
|
||||
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
||||
|
||||
r = uv_udp_init_ex(uv_default_loop(), &client, AF_INET6);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_fileno((const uv_handle_t*) &client, &fd);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(fd != INVALID_FD);
|
||||
|
||||
/* Windows returns WSAEINVAL if the socket is not bound */
|
||||
#ifndef _WIN32
|
||||
{
|
||||
int namelen;
|
||||
struct sockaddr_in6 sockname;
|
||||
namelen = sizeof sockname;
|
||||
r = uv_udp_getsockname(&client, (struct sockaddr*) &sockname, &namelen);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(sockname.sin6_family == AF_INET6);
|
||||
}
|
||||
#endif
|
||||
|
||||
r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0);
|
||||
#ifndef _WIN32
|
||||
ASSERT(r == UV_EINVAL);
|
||||
#else
|
||||
ASSERT(r == UV_EFAULT);
|
||||
#endif
|
||||
|
||||
uv_close((uv_handle_t*) &client, NULL);
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(udp_create_early_bad_domain) {
|
||||
uv_udp_t client;
|
||||
int r;
|
||||
|
||||
r = uv_udp_init_ex(uv_default_loop(), &client, 47);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
r = uv_udp_init_ex(uv_default_loop(), &client, 1024);
|
||||
ASSERT(r == UV_EINVAL);
|
||||
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
|
@ -44,7 +44,7 @@ static void close_cb(uv_handle_t* handle) {
|
|||
|
||||
static void sv_send_cb(uv_udp_send_t* req, int status) {
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
ASSERT(status == 0 || status == UV_ENETUNREACH);
|
||||
CHECK_HANDLE(req->handle);
|
||||
|
||||
sv_send_cb_called++;
|
||||
|
|
|
@ -116,6 +116,8 @@ TEST_IMPL(udp_multicast_join) {
|
|||
|
||||
/* join the multicast channel */
|
||||
r = uv_udp_set_membership(&client, "239.255.0.1", NULL, UV_JOIN_GROUP);
|
||||
if (r == UV_ENODEV)
|
||||
RETURN_SKIP("No multicast support.");
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_udp_recv_start(&client, alloc_cb, cl_recv_cb);
|
||||
|
|
|
@ -124,6 +124,11 @@ TEST_IMPL(udp_multicast_join6) {
|
|||
#else
|
||||
r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP);
|
||||
#endif
|
||||
if (r == UV_ENODEV) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
RETURN_SKIP("No ipv6 multicast route");
|
||||
}
|
||||
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_udp_recv_start(&client, alloc_cb, cl_recv_cb);
|
||||
|
|
|
@ -44,7 +44,7 @@ static void close_cb(uv_handle_t* handle) {
|
|||
|
||||
static void sv_send_cb(uv_udp_send_t* req, int status) {
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
ASSERT(status == 0 || status == UV_ENETUNREACH);
|
||||
CHECK_HANDLE(req->handle);
|
||||
|
||||
sv_send_cb_called++;
|
||||
|
|
|
@ -67,6 +67,17 @@ static uv_os_sock_t create_udp_socket(void) {
|
|||
}
|
||||
|
||||
|
||||
static void close_socket(uv_os_sock_t sock) {
|
||||
int r;
|
||||
#ifdef _WIN32
|
||||
r = closesocket(sock);
|
||||
#else
|
||||
r = close(sock);
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void alloc_cb(uv_handle_t* handle,
|
||||
size_t suggested_size,
|
||||
uv_buf_t* buf) {
|
||||
|
@ -164,3 +175,30 @@ TEST_IMPL(udp_open) {
|
|||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(udp_open_twice) {
|
||||
uv_udp_t client;
|
||||
uv_os_sock_t sock1, sock2;
|
||||
int r;
|
||||
|
||||
startup();
|
||||
sock1 = create_udp_socket();
|
||||
sock2 = create_udp_socket();
|
||||
|
||||
r = uv_udp_init(uv_default_loop(), &client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_udp_open(&client, sock1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_udp_open(&client, sock2);
|
||||
ASSERT(r == UV_EBUSY);
|
||||
close_socket(sock2);
|
||||
|
||||
uv_close((uv_handle_t*) &client, NULL);
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -326,8 +326,10 @@
|
|||
'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',
|
||||
|
@ -356,6 +358,7 @@
|
|||
'test/test-tcp-close.c',
|
||||
'test/test-tcp-close-accept.c',
|
||||
'test/test-tcp-close-while-connecting.c',
|
||||
'test/test-tcp-create-socket-early.c',
|
||||
'test/test-tcp-connect-error-after-write.c',
|
||||
'test/test-tcp-shutdown-after-write.c',
|
||||
'test/test-tcp-flags.c',
|
||||
|
@ -384,6 +387,7 @@
|
|||
'test/test-timer.c',
|
||||
'test/test-tty.c',
|
||||
'test/test-udp-bind.c',
|
||||
'test/test-udp-create-socket-early.c',
|
||||
'test/test-udp-dgram-too-big.c',
|
||||
'test/test-udp-ipv6.c',
|
||||
'test/test-udp-open.c',
|
||||
|
@ -427,6 +431,9 @@
|
|||
'_XOPEN_SOURCE=500',
|
||||
],
|
||||
}],
|
||||
['uv_library=="shared_library"', {
|
||||
'defines': [ 'USING_UV_SHARED=1' ]
|
||||
}],
|
||||
],
|
||||
'msvs-settings': {
|
||||
'VCLinkerTool': {
|
||||
|
@ -478,7 +485,10 @@
|
|||
'test/runner-unix.c',
|
||||
'test/runner-unix.h',
|
||||
]
|
||||
}]
|
||||
}],
|
||||
['uv_library=="shared_library"', {
|
||||
'defines': [ 'USING_UV_SHARED=1' ]
|
||||
}],
|
||||
],
|
||||
'msvs-settings': {
|
||||
'VCLinkerTool': {
|
||||
|
|
Loading…
Reference in New Issue