From a1615949a591fc523048a09540a2d340ff1b3da8 Mon Sep 17 00:00:00 2001 From: Saúl Ibarra Corretgé Date: Wed, 5 Aug 2015 21:17:46 +0200 Subject: deps: upgrade libuv to 1.7.3 PR-URL: https://github.com/nodejs/node/pull/2310 Reviewed-By: bnoordhuis - Ben Noordhuis Reviewed-By: cjihrig - Colin Ihrig --- deps/uv/AUTHORS | 19 + deps/uv/ChangeLog | 160 ++++++++ deps/uv/MAINTAINERS.md | 36 ++ deps/uv/Makefile.am | 4 + deps/uv/README.md | 36 ++ deps/uv/android-configure | 4 +- deps/uv/appveyor.yml | 36 ++ deps/uv/common.gypi | 7 +- deps/uv/configure.ac | 2 +- deps/uv/docs/src/check.rst | 2 +- deps/uv/docs/src/errors.rst | 6 +- deps/uv/docs/src/fs.rst | 12 + deps/uv/docs/src/fs_event.rst | 2 +- deps/uv/docs/src/idle.rst | 2 +- deps/uv/docs/src/index.rst | 1 + deps/uv/docs/src/misc.rst | 11 - deps/uv/docs/src/pipe.rst | 4 +- deps/uv/docs/src/signal.rst | 2 +- deps/uv/docs/src/stream.rst | 4 +- deps/uv/docs/src/tcp.rst | 13 +- deps/uv/docs/src/tty.rst | 6 +- deps/uv/docs/src/udp.rst | 11 +- deps/uv/docs/src/version.rst | 60 +++ deps/uv/include/uv-version.h | 8 +- deps/uv/include/uv.h | 7 +- deps/uv/libuv.nsi | 86 +++++ deps/uv/src/queue.h | 4 +- deps/uv/src/threadpool.c | 9 +- deps/uv/src/unix/aix.c | 187 +++------- deps/uv/src/unix/core.c | 30 +- deps/uv/src/unix/freebsd.c | 35 +- deps/uv/src/unix/fs.c | 137 +++++-- deps/uv/src/unix/internal.h | 1 + deps/uv/src/unix/kqueue.c | 12 +- deps/uv/src/unix/loop.c | 34 +- deps/uv/src/unix/pthread-fixes.c | 1 + deps/uv/src/unix/stream.c | 36 +- deps/uv/src/unix/tcp.c | 51 ++- deps/uv/src/unix/tty.c | 9 +- deps/uv/src/unix/udp.c | 42 ++- deps/uv/src/uv-common.c | 26 +- deps/uv/src/uv-common.h | 2 +- deps/uv/src/version.c | 6 +- deps/uv/src/win/core.c | 21 +- deps/uv/src/win/fs-event.c | 22 +- deps/uv/src/win/fs.c | 55 +-- deps/uv/src/win/internal.h | 3 +- deps/uv/src/win/pipe.c | 67 +++- deps/uv/src/win/process-stdio.c | 2 +- deps/uv/src/win/tcp.c | 78 ++-- deps/uv/src/win/thread.c | 1 + deps/uv/src/win/tty.c | 128 ++++++- deps/uv/src/win/udp.c | 76 +++- deps/uv/test/benchmark-fs-stat.c | 2 +- deps/uv/test/echo-server.c | 2 +- deps/uv/test/run-tests.c | 5 + deps/uv/test/runner-unix.c | 60 ++- deps/uv/test/task.h | 4 +- deps/uv/test/test-fs-event.c | 273 ++++++++++---- deps/uv/test/test-fs.c | 487 ++++++++++++++++++------- deps/uv/test/test-list.h | 36 ++ deps/uv/test/test-pipe-connect-multiple.c | 104 ++++++ deps/uv/test/test-pipe-pending-instances.c | 59 +++ deps/uv/test/test-signal-multiple-loops.c | 1 + deps/uv/test/test-spawn.c | 198 +++++++++- deps/uv/test/test-tcp-close-while-connecting.c | 12 +- deps/uv/test/test-tcp-connect-timeout.c | 2 + deps/uv/test/test-tcp-create-socket-early.c | 206 +++++++++++ deps/uv/test/test-tcp-open.c | 38 ++ deps/uv/test/test-tcp-squelch-connreset.c | 119 ++++++ deps/uv/test/test-threadpool-cancel.c | 6 +- deps/uv/test/test-udp-create-socket-early.c | 132 +++++++ deps/uv/test/test-udp-multicast-interface.c | 2 +- deps/uv/test/test-udp-multicast-join.c | 2 + deps/uv/test/test-udp-multicast-join6.c | 5 + deps/uv/test/test-udp-multicast-ttl.c | 2 +- deps/uv/test/test-udp-open.c | 38 ++ deps/uv/uv.gyp | 12 +- 78 files changed, 2772 insertions(+), 651 deletions(-) create mode 100644 deps/uv/MAINTAINERS.md create mode 100644 deps/uv/appveyor.yml create mode 100644 deps/uv/docs/src/version.rst create mode 100644 deps/uv/libuv.nsi create mode 100644 deps/uv/test/test-pipe-connect-multiple.c create mode 100644 deps/uv/test/test-pipe-pending-instances.c create mode 100644 deps/uv/test/test-tcp-create-socket-early.c create mode 100644 deps/uv/test/test-tcp-squelch-connreset.c create mode 100644 deps/uv/test/test-udp-create-socket-early.c (limited to 'deps/uv') diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index bbb8f4d8cd..2c12c14123 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -200,3 +200,22 @@ farblue68 Jason Williams Igor Soarez Miodrag Milanovic +Cheng Zhao +Michael Neumann +Stefano Cristiano +heshamsafi +A. Hauptmann +John McNamee +Yosuke Furukawa +Santiago Gimeno +guworks +RossBencina +Roger A. Light +chenttuuvv +Richard Lau +ronkorving +Corbin Simpson +Zachary Hamm +Karl Skomski +Jeremy Whitlock +Willem Thiart diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 5d3a4cad46..e9ebdecd4c 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -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: diff --git a/deps/uv/MAINTAINERS.md b/deps/uv/MAINTAINERS.md new file mode 100644 index 0000000000..4db2f5130c --- /dev/null +++ b/deps/uv/MAINTAINERS.md @@ -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 + diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index e9814d7b70..f0ca6a7d82 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -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 \ diff --git a/deps/uv/README.md b/deps/uv/README.md index f9a7a1e62e..0ce2669971 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -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][]. diff --git a/deps/uv/android-configure b/deps/uv/android-configure index 9750581206..e0b250fb63 100755 --- a/deps/uv/android-configure +++ b/deps/uv/android-configure @@ -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 diff --git a/deps/uv/appveyor.yml b/deps/uv/appveyor.yml new file mode 100644 index 0000000000..8790283340 --- /dev/null +++ b/deps/uv/appveyor.yml @@ -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 diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi index ecf9475234..c6f6dec865 100644 --- a/deps/uv/common.gypi +++ b/deps/uv/common.gypi @@ -37,9 +37,10 @@ 'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ], }, 'conditions': [ - ['OS != "win"', { - 'defines': [ 'EV_VERIFY=2' ], - }], + ['OS == "android"', { + 'cflags': [ '-fPIE' ], + 'ldflags': [ '-fPIE', '-pie' ] + }] ] }, 'Release': { diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index fe7228e2b7..ad5cb00842 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.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]) diff --git a/deps/uv/docs/src/check.rst b/deps/uv/docs/src/check.rst index 8d48f22276..36c93cf03d 100644 --- a/deps/uv/docs/src/check.rst +++ b/deps/uv/docs/src/check.rst @@ -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. diff --git a/deps/uv/docs/src/errors.rst b/deps/uv/docs/src/errors.rst index 5d59dc30f2..cec25f5187 100644 --- a/deps/uv/docs/src/errors.rst +++ b/deps/uv/docs/src/errors.rst @@ -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. diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index c2a3fc252a..33c04406f1 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -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) diff --git a/deps/uv/docs/src/fs_event.rst b/deps/uv/docs/src/fs_event.rst index 681ae52f95..c2d7f52023 100644 --- a/deps/uv/docs/src/fs_event.rst +++ b/deps/uv/docs/src/fs_event.rst @@ -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) diff --git a/deps/uv/docs/src/idle.rst b/deps/uv/docs/src/idle.rst index 81f51d2076..1f51c4a19e 100644 --- a/deps/uv/docs/src/idle.rst +++ b/deps/uv/docs/src/idle.rst @@ -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. diff --git a/deps/uv/docs/src/index.rst b/deps/uv/docs/src/index.rst index 9cdc494aec..fa89c4bffe 100644 --- a/deps/uv/docs/src/index.rst +++ b/deps/uv/docs/src/index.rst @@ -68,6 +68,7 @@ Documentation design errors + version loop handle request diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 9708c5dea4..e9ddba3db6 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -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 diff --git a/deps/uv/docs/src/pipe.rst b/deps/uv/docs/src/pipe.rst index df896a0583..d33b0f2b97 100644 --- a/deps/uv/docs/src/pipe.rst +++ b/deps/uv/docs/src/pipe.rst @@ -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. diff --git a/deps/uv/docs/src/signal.rst b/deps/uv/docs/src/signal.rst index 21675945fc..dc1223b90a 100644 --- a/deps/uv/docs/src/signal.rst +++ b/deps/uv/docs/src/signal.rst @@ -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. diff --git a/deps/uv/docs/src/stream.rst b/deps/uv/docs/src/stream.rst index 880f0e2ebc..21562b3702 100644 --- a/deps/uv/docs/src/stream.rst +++ b/deps/uv/docs/src/stream.rst @@ -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: diff --git a/deps/uv/docs/src/tcp.rst b/deps/uv/docs/src/tcp.rst index dd746fe87f..dd18522d91 100644 --- a/deps/uv/docs/src/tcp.rst +++ b/deps/uv/docs/src/tcp.rst @@ -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) diff --git a/deps/uv/docs/src/tty.rst b/deps/uv/docs/src/tty.rst index 18f34ef46d..655dca9ca2 100644 --- a/deps/uv/docs/src/tty.rst +++ b/deps/uv/docs/src/tty.rst @@ -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. diff --git a/deps/uv/docs/src/udp.rst b/deps/uv/docs/src/udp.rst index ec7ce56d38..dd46603394 100644 --- a/deps/uv/docs/src/udp.rst +++ b/deps/uv/docs/src/udp.rst @@ -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. diff --git a/deps/uv/docs/src/version.rst b/deps/uv/docs/src/version.rst new file mode 100644 index 0000000000..e1715b2d3c --- /dev/null +++ b/deps/uv/docs/src/version.rst @@ -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. diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index 3372212c8c..90f2ce1f67 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -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 */ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 564af5fad6..f96026b603 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.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, diff --git a/deps/uv/libuv.nsi b/deps/uv/libuv.nsi new file mode 100644 index 0000000000..159756e196 --- /dev/null +++ b/deps/uv/libuv.nsi @@ -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 + diff --git a/deps/uv/src/queue.h b/deps/uv/src/queue.h index fe02b454ea..60c8000038 100644 --- a/deps/uv/src/queue.h +++ b/deps/uv/src/queue.h @@ -16,6 +16,8 @@ #ifndef QUEUE_H_ #define QUEUE_H_ +#include + 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)) diff --git a/deps/uv/src/threadpool.c b/deps/uv/src/threadpool.c index debaf5ca96..15d719944f 100644 --- a/deps/uv/src/threadpool.c +++ b/deps/uv/src/threadpool.c @@ -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); } diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index a2b0744a04..c90b7e5cb9 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -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); - - 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()); + abspath_size = strlen(abspath); - /* This is always a symlink, resolve it. */ - res = readlink(cwd, cwdl, sizeof(cwdl) - 1); - if (res < 0) - return -errno; + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; - snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, argv[0]); + 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; - /* 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; } diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 826b4113b2..e149357e07 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -35,7 +35,7 @@ #include #include #include -#include /* INT_MAX, PATH_MAX */ +#include /* INT_MAX, PATH_MAX, IOV_MAX */ #include /* writev */ #include /* getrusage */ #include @@ -55,13 +55,13 @@ # include #endif -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__DragonFly__) # include # include # include # include # 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) { diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index 44976f7fe2..c838beb28e 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -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; diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 9dab202dd7..52082e9347 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -58,52 +58,63 @@ # include #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; diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index c31e54992d..741fa57d69 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -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); diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 424236a6ef..495f20d285 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -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; } diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c index aa9146bf9a..92e96f09ed 100644 --- a/deps/uv/src/unix/loop.c +++ b/deps/uv/src/unix/loop.c @@ -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; } diff --git a/deps/uv/src/unix/pthread-fixes.c b/deps/uv/src/unix/pthread-fixes.c index dc54f35d60..3a71eb5aae 100644 --- a/deps/uv/src/unix/pthread-fixes.c +++ b/deps/uv/src/unix/pthread-fixes.c @@ -35,6 +35,7 @@ * */ #include #include +#include int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) { static int workaround; diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 7ad1658cf8..183b68cf71 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -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) { diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 4060e7bd70..6d213a4977 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -28,18 +28,14 @@ #include -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) diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index 7783548a6e..54c9055a08 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -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 diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index f85ab1473a..66ecc4e341 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -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, diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 77879b9a6c..675a776bf4 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -29,7 +29,9 @@ #include /* malloc */ #include /* memset */ -#if !defined(_WIN32) +#if defined(_WIN32) +# include /* malloc */ +#else # include /* 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 diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index 8258d7a138..b348ec76bd 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -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 diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c index ff91a46090..686dedd98d 100644 --- a/deps/uv/src/version.c +++ b/deps/uv/src/version.c @@ -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; } diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 115449224f..de0483e102 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -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; } diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c index eb205d3921..ba68f78c82 100644 --- a/deps/uv/src/win/fs-event.c +++ b/deps/uv/src/win/fs-event.c @@ -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) { diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 00d0197a54..4a17573113 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -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); } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 04b2a548ca..8d4081bdb5 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -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 diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index d232efae3a..8312b1ceb9 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -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; } diff --git a/deps/uv/src/win/process-stdio.c b/deps/uv/src/win/process-stdio.c index e81f799f0b..e3c06f57de 100644 --- a/deps/uv/src/win/process-stdio.c +++ b/deps/uv/src/win/process-stdio.c @@ -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 { diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index da89f28d16..0f5654863e 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -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, diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c index e91ae9b138..d7171fd690 100644 --- a/deps/uv/src/win/thread.c +++ b/deps/uv/src/win/thread.c @@ -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); } diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 7b1e4ba055..c3af02f7f2 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -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); diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 197e5d828f..24792ec067 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -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 (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) + 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. */ diff --git a/deps/uv/test/benchmark-fs-stat.c b/deps/uv/test/benchmark-fs-stat.c index 5c87de0043..32d2589586 100644 --- a/deps/uv/test/benchmark-fs-stat.c +++ b/deps/uv/test/benchmark-fs-stat.c @@ -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) diff --git a/deps/uv/test/echo-server.c b/deps/uv/test/echo-server.c index f223981c26..bfed67675d 100644 --- a/deps/uv/test/echo-server.c +++ b/deps/uv/test/echo-server.c @@ -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 diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c index 1f45874532..b4be01f6f9 100644 --- a/deps/uv/test/run-tests.c +++ b/deps/uv/test/run-tests.c @@ -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); } diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index 5da720fad4..2264d1e89d 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/test/runner-unix.c @@ -37,6 +37,7 @@ #include #include +#include #include @@ -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(); + + 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)); + + 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; - FD_ZERO(&fds); - FD_SET(args.pipe[0], &fds); + tv.tv_sec = (timeout - elapsed_ms) / 1000; + tv.tv_usec = (timeout - elapsed_ms) % 1000 * 1000; - r = select(args.pipe[0] + 1, &fds, NULL, NULL, &tv); + 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]); diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index e06a50e213..e736763802 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -179,8 +179,8 @@ enum test_status { #include -/* Define inline for MSVC */ -# ifdef _MSC_VER +/* Define inline for MSVC<2015 */ +# if defined(_MSC_VER) && _MSC_VER < 1900 # define inline __inline # endif diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 0a2ba33145..a0908ce575 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -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,6 +120,56 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename, 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), + "watch_dir/%s%d", + file_prefix, + i); + return fs_event_filename; +} + +static void fs_event_create_files(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(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)); + } +} + +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); + + /* 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)); + } + } +} + static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle, const char* filename, int events, @@ -126,61 +177,92 @@ static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle, fs_event_cb_called++; ASSERT(handle == &fs_event); ASSERT(status == 0); - ASSERT(events == UV_RENAME); + ASSERT(events == UV_CHANGE || 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)); + 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); } } -static const char* fs_event_get_filename(int i) { +#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/%s%d", + "watch_dir/subdir/%s%d", file_prefix, i); return fs_event_filename; } -static void fs_event_create_files(uv_timer_t* handle) { - int i; - - /* Already created all files */ - if (fs_event_created == fs_event_file_count) { - uv_close((uv_handle_t*) &timer, close_cb); - return; - } +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 all files */ - for (i = 0; i < 16; i++, fs_event_created++) - create_file(handle->loop, fs_event_get_filename(i)); + /* Create the file */ + create_file(fs_event_get_filename_in_subdir(fs_event_created)); - /* And unlink them */ - ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files, 50, 0)); + 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)); + } } -void fs_event_unlink_files(uv_timer_t* handle) { +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))); - /* Unlink all files */ - for (i = 0; i < 16; i++) { - r = remove(fs_event_get_filename(i)); - if (handle != NULL) - ASSERT(r == 0); + 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); - /* And create them again */ - if (handle != NULL) - ASSERT(0 == uv_timer_start(&timer, fs_event_create_files, 50, 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) { @@ -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() diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index a0600b3079..17b90e91c1 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -119,7 +119,7 @@ static void check_permission(const char* filename, unsigned int mode) { uv_fs_t req; uv_stat_t* s; - r = uv_fs_stat(uv_default_loop(), &req, filename, NULL); + r = uv_fs_stat(NULL, &req, filename, NULL); ASSERT(r == 0); ASSERT(req.result == 0); @@ -402,7 +402,7 @@ static void check_mkdtemp_result(uv_fs_t* req) { check_permission(req->path, 0700); /* Check if req->path is actually a directory */ - r = uv_fs_stat(uv_default_loop(), &stat_req, req->path, NULL); + r = uv_fs_stat(NULL, &stat_req, req->path, NULL); ASSERT(r == 0); ASSERT(((uv_stat_t*)stat_req.ptr)->st_mode & S_IFDIR); uv_fs_req_cleanup(&stat_req); @@ -521,7 +521,7 @@ TEST_IMPL(fs_file_noent) { loop = uv_default_loop(); - r = uv_fs_open(loop, &req, "does_not_exist", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &req, "does_not_exist", O_RDONLY, 0, NULL); ASSERT(r == UV_ENOENT); ASSERT(req.result == UV_ENOENT); uv_fs_req_cleanup(&req); @@ -549,7 +549,7 @@ TEST_IMPL(fs_file_nametoolong) { memset(name, 'a', TOO_LONG_NAME_LENGTH); name[TOO_LONG_NAME_LENGTH] = 0; - r = uv_fs_open(loop, &req, name, O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &req, name, O_RDONLY, 0, NULL); ASSERT(r == UV_ENAMETOOLONG); ASSERT(req.result == UV_ENAMETOOLONG); uv_fs_req_cleanup(&req); @@ -572,7 +572,7 @@ TEST_IMPL(fs_file_loop) { loop = uv_default_loop(); unlink("test_symlink"); - r = uv_fs_symlink(loop, &req, "test_symlink", "test_symlink", 0, NULL); + r = uv_fs_symlink(NULL, &req, "test_symlink", "test_symlink", 0, NULL); #ifdef _WIN32 /* * Windows XP and Server 2003 don't support symlinks; we'll get UV_ENOTSUP. @@ -585,7 +585,7 @@ TEST_IMPL(fs_file_loop) { ASSERT(r == 0); uv_fs_req_cleanup(&req); - r = uv_fs_open(loop, &req, "test_symlink", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &req, "test_symlink", O_RDONLY, 0, NULL); ASSERT(r == UV_ELOOP); ASSERT(req.result == UV_ELOOP); uv_fs_req_cleanup(&req); @@ -730,63 +730,62 @@ TEST_IMPL(fs_file_sync) { uv_fs_req_cleanup(&open_req1); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(write_req.result >= 0); uv_fs_req_cleanup(&write_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_file", O_RDWR, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(read_req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); uv_fs_req_cleanup(&read_req); - r = uv_fs_ftruncate(loop, &ftruncate_req, open_req1.result, 7, NULL); + r = uv_fs_ftruncate(NULL, &ftruncate_req, open_req1.result, 7, NULL); ASSERT(r == 0); ASSERT(ftruncate_req.result == 0); uv_fs_req_cleanup(&ftruncate_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_rename(loop, &rename_req, "test_file", "test_file2", NULL); + r = uv_fs_rename(NULL, &rename_req, "test_file", "test_file2", NULL); ASSERT(r == 0); ASSERT(rename_req.result == 0); uv_fs_req_cleanup(&rename_req); - r = uv_fs_open(loop, &open_req1, "test_file2", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); memset(buf, 0, sizeof(buf)); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, - NULL); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(read_req.result >= 0); ASSERT(strcmp(buf, "test-bu") == 0); uv_fs_req_cleanup(&read_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_unlink(loop, &unlink_req, "test_file2", NULL); + r = uv_fs_unlink(NULL, &unlink_req, "test_file2", NULL); ASSERT(r == 0); ASSERT(unlink_req.result == 0); uv_fs_req_cleanup(&unlink_req); @@ -808,19 +807,19 @@ TEST_IMPL(fs_file_write_null_buffer) { loop = uv_default_loop(); - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); iov = uv_buf_init(NULL, 0); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r == 0); ASSERT(write_req.result == 0); uv_fs_req_cleanup(&write_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); @@ -850,19 +849,19 @@ TEST_IMPL(fs_async_dir) { ASSERT(mkdir_cb_count == 1); /* Create 2 files synchronously. */ - r = uv_fs_open(loop, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&close_req); @@ -873,7 +872,7 @@ TEST_IMPL(fs_async_dir) { ASSERT(scandir_cb_count == 1); /* sync uv_fs_scandir */ - r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, NULL); + r = uv_fs_scandir(NULL, &scandir_req, "test_dir", 0, NULL); ASSERT(r == 2); ASSERT(scandir_req.result == 2); ASSERT(scandir_req.ptr); @@ -957,12 +956,12 @@ TEST_IMPL(fs_async_sendfile) { ASSERT(r == 0); /* Test starts here. */ - r = uv_fs_open(loop, &open_req1, "test_file", O_RDWR, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); - r = uv_fs_open(loop, &open_req2, "test_file2", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req2, "test_file2", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req2.result >= 0); @@ -975,10 +974,10 @@ TEST_IMPL(fs_async_sendfile) { ASSERT(sendfile_cb_count == 1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_close(loop, &close_req, open_req2.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req2.result, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&close_req); @@ -1008,7 +1007,7 @@ TEST_IMPL(fs_mkdtemp) { ASSERT(mkdtemp_cb_count == 1); /* sync mkdtemp */ - r = uv_fs_mkdtemp(loop, &mkdtemp_req2, path_template, NULL); + r = uv_fs_mkdtemp(NULL, &mkdtemp_req2, path_template, NULL); ASSERT(r == 0); check_mkdtemp_result(&mkdtemp_req2); @@ -1040,7 +1039,7 @@ TEST_IMPL(fs_fstat) { loop = uv_default_loop(); - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, + r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); @@ -1048,12 +1047,12 @@ TEST_IMPL(fs_fstat) { uv_fs_req_cleanup(&req); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); ASSERT(r == sizeof(test_buf)); ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); - r = uv_fs_fstat(loop, &req, file, NULL); + r = uv_fs_fstat(NULL, &req, file, NULL); ASSERT(r == 0); ASSERT(req.result == 0); s = req.ptr; @@ -1130,7 +1129,7 @@ TEST_IMPL(fs_fstat) { ASSERT(fstat_cb_count == 1); - r = uv_fs_close(loop, &req, file, NULL); + r = uv_fs_close(NULL, &req, file, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1161,7 +1160,7 @@ TEST_IMPL(fs_access) { loop = uv_default_loop(); /* File should not exist */ - r = uv_fs_access(loop, &req, "test_file", F_OK, NULL); + r = uv_fs_access(NULL, &req, "test_file", F_OK, NULL); ASSERT(r < 0); ASSERT(req.result < 0); uv_fs_req_cleanup(&req); @@ -1174,7 +1173,7 @@ TEST_IMPL(fs_access) { access_cb_count = 0; /* reset for the next test */ /* Create file */ - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, + r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); @@ -1182,7 +1181,7 @@ TEST_IMPL(fs_access) { uv_fs_req_cleanup(&req); /* File should exist */ - r = uv_fs_access(loop, &req, "test_file", F_OK, NULL); + r = uv_fs_access(NULL, &req, "test_file", F_OK, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1195,17 +1194,17 @@ TEST_IMPL(fs_access) { access_cb_count = 0; /* reset for the next test */ /* Close file */ - r = uv_fs_close(loop, &req, file, NULL); + r = uv_fs_close(NULL, &req, file, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); /* Directory access */ - r = uv_fs_mkdir(loop, &req, "test_dir", 0777, NULL); + r = uv_fs_mkdir(NULL, &req, "test_dir", 0777, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&req); - r = uv_fs_access(loop, &req, "test_dir", W_OK, NULL); + r = uv_fs_access(NULL, &req, "test_dir", W_OK, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1235,7 +1234,7 @@ TEST_IMPL(fs_chmod) { loop = uv_default_loop(); - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, + r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); @@ -1243,14 +1242,14 @@ TEST_IMPL(fs_chmod) { uv_fs_req_cleanup(&req); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); ASSERT(r == sizeof(test_buf)); ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); #ifndef _WIN32 /* Make the file write-only */ - r = uv_fs_chmod(loop, &req, "test_file", 0200, NULL); + r = uv_fs_chmod(NULL, &req, "test_file", 0200, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1259,7 +1258,7 @@ TEST_IMPL(fs_chmod) { #endif /* Make the file read-only */ - r = uv_fs_chmod(loop, &req, "test_file", 0400, NULL); + r = uv_fs_chmod(NULL, &req, "test_file", 0400, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1267,7 +1266,7 @@ TEST_IMPL(fs_chmod) { check_permission("test_file", 0400); /* Make the file read+write with sync uv_fs_fchmod */ - r = uv_fs_fchmod(loop, &req, file, 0600, NULL); + r = uv_fs_fchmod(NULL, &req, file, 0600, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1333,7 +1332,7 @@ TEST_IMPL(fs_unlink_readonly) { loop = uv_default_loop(); - r = uv_fs_open(loop, + r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, @@ -1345,7 +1344,7 @@ TEST_IMPL(fs_unlink_readonly) { uv_fs_req_cleanup(&req); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); ASSERT(r == sizeof(test_buf)); ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); @@ -1353,7 +1352,7 @@ TEST_IMPL(fs_unlink_readonly) { close(file); /* Make the file read-only */ - r = uv_fs_chmod(loop, &req, "test_file", 0400, NULL); + r = uv_fs_chmod(NULL, &req, "test_file", 0400, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1361,7 +1360,7 @@ TEST_IMPL(fs_unlink_readonly) { check_permission("test_file", 0400); /* Try to unlink the file */ - r = uv_fs_unlink(loop, &req, "test_file", NULL); + r = uv_fs_unlink(NULL, &req, "test_file", NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1373,7 +1372,7 @@ TEST_IMPL(fs_unlink_readonly) { uv_run(loop, UV_RUN_DEFAULT); /* Cleanup. */ - uv_fs_chmod(loop, &req, "test_file", 0600, NULL); + uv_fs_chmod(NULL, &req, "test_file", 0600, NULL); uv_fs_req_cleanup(&req); unlink("test_file"); @@ -1392,7 +1391,7 @@ TEST_IMPL(fs_chown) { loop = uv_default_loop(); - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, + r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); @@ -1400,13 +1399,13 @@ TEST_IMPL(fs_chown) { uv_fs_req_cleanup(&req); /* sync chown */ - r = uv_fs_chown(loop, &req, "test_file", -1, -1, NULL); + r = uv_fs_chown(NULL, &req, "test_file", -1, -1, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); /* sync fchown */ - r = uv_fs_fchown(loop, &req, file, -1, -1, NULL); + r = uv_fs_fchown(NULL, &req, file, -1, -1, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); @@ -1458,7 +1457,7 @@ TEST_IMPL(fs_link) { loop = uv_default_loop(); - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, + r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); @@ -1466,7 +1465,7 @@ TEST_IMPL(fs_link) { uv_fs_req_cleanup(&req); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); ASSERT(r == sizeof(test_buf)); ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); @@ -1474,12 +1473,12 @@ TEST_IMPL(fs_link) { close(file); /* sync link */ - r = uv_fs_link(loop, &req, "test_file", "test_file_link", NULL); + r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); - r = uv_fs_open(loop, &req, "test_file_link", O_RDWR, 0, NULL); + r = uv_fs_open(NULL, &req, "test_file_link", O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); link = req.result; @@ -1487,7 +1486,7 @@ TEST_IMPL(fs_link) { memset(buf, 0, sizeof(buf)); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL); + r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); @@ -1500,7 +1499,7 @@ TEST_IMPL(fs_link) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(link_cb_count == 1); - r = uv_fs_open(loop, &req, "test_file_link2", O_RDWR, 0, NULL); + r = uv_fs_open(NULL, &req, "test_file_link2", O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); link = req.result; @@ -1508,7 +1507,7 @@ TEST_IMPL(fs_link) { memset(buf, 0, sizeof(buf)); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL); + r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); @@ -1542,7 +1541,7 @@ TEST_IMPL(fs_readlink) { ASSERT(req.result == UV_ENOENT); uv_fs_req_cleanup(&req); - ASSERT(UV_ENOENT == uv_fs_readlink(loop, &req, "no_such_file", NULL)); + ASSERT(UV_ENOENT == uv_fs_readlink(NULL, &req, "no_such_file", NULL)); ASSERT(req.ptr == NULL); ASSERT(req.result == UV_ENOENT); uv_fs_req_cleanup(&req); @@ -1567,7 +1566,7 @@ TEST_IMPL(fs_symlink) { loop = uv_default_loop(); - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, + r = uv_fs_open(NULL, &req, "test_file", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); @@ -1575,7 +1574,7 @@ TEST_IMPL(fs_symlink) { uv_fs_req_cleanup(&req); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); ASSERT(r == sizeof(test_buf)); ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); @@ -1583,7 +1582,7 @@ TEST_IMPL(fs_symlink) { close(file); /* sync symlink */ - r = uv_fs_symlink(loop, &req, "test_file", "test_file_symlink", 0, NULL); + r = uv_fs_symlink(NULL, &req, "test_file", "test_file_symlink", 0, NULL); #ifdef _WIN32 if (r < 0) { if (r == UV_ENOTSUP) { @@ -1605,7 +1604,7 @@ TEST_IMPL(fs_symlink) { ASSERT(req.result == 0); uv_fs_req_cleanup(&req); - r = uv_fs_open(loop, &req, "test_file_symlink", O_RDWR, 0, NULL); + r = uv_fs_open(NULL, &req, "test_file_symlink", O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); link = req.result; @@ -1613,14 +1612,14 @@ TEST_IMPL(fs_symlink) { memset(buf, 0, sizeof(buf)); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL); + r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); close(link); - r = uv_fs_symlink(loop, + r = uv_fs_symlink(NULL, &req, "test_file_symlink", "test_file_symlink_symlink", @@ -1629,7 +1628,7 @@ TEST_IMPL(fs_symlink) { ASSERT(r == 0); uv_fs_req_cleanup(&req); - r = uv_fs_readlink(loop, &req, "test_file_symlink_symlink", NULL); + r = uv_fs_readlink(NULL, &req, "test_file_symlink_symlink", NULL); ASSERT(r == 0); ASSERT(strcmp(req.ptr, "test_file_symlink") == 0); uv_fs_req_cleanup(&req); @@ -1645,7 +1644,7 @@ TEST_IMPL(fs_symlink) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(symlink_cb_count == 1); - r = uv_fs_open(loop, &req, "test_file_symlink2", O_RDWR, 0, NULL); + r = uv_fs_open(NULL, &req, "test_file_symlink2", O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); link = req.result; @@ -1653,14 +1652,14 @@ TEST_IMPL(fs_symlink) { memset(buf, 0, sizeof(buf)); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL); + r = uv_fs_read(NULL, &req, link, &iov, 1, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); close(link); - r = uv_fs_symlink(loop, + r = uv_fs_symlink(NULL, &req, "test_file_symlink2", "test_file_symlink2_symlink", @@ -1706,7 +1705,7 @@ TEST_IMPL(fs_symlink_dir) { loop = uv_default_loop(); - uv_fs_mkdir(loop, &req, "test_dir", 0777, NULL); + uv_fs_mkdir(NULL, &req, "test_dir", 0777, NULL); uv_fs_req_cleanup(&req); #ifdef _WIN32 @@ -1723,18 +1722,18 @@ TEST_IMPL(fs_symlink_dir) { test_dir = "test_dir"; #endif - r = uv_fs_symlink(loop, &req, test_dir, "test_dir_symlink", + r = uv_fs_symlink(NULL, &req, test_dir, "test_dir_symlink", UV_FS_SYMLINK_JUNCTION, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); - r = uv_fs_stat(loop, &req, "test_dir_symlink", NULL); + r = uv_fs_stat(NULL, &req, "test_dir_symlink", NULL); ASSERT(r == 0); ASSERT(((uv_stat_t*)req.ptr)->st_mode & S_IFDIR); uv_fs_req_cleanup(&req); - r = uv_fs_lstat(loop, &req, "test_dir_symlink", NULL); + r = uv_fs_lstat(NULL, &req, "test_dir_symlink", NULL); ASSERT(r == 0); ASSERT(((uv_stat_t*)req.ptr)->st_mode & S_IFLNK); #ifdef _WIN32 @@ -1744,7 +1743,7 @@ TEST_IMPL(fs_symlink_dir) { #endif uv_fs_req_cleanup(&req); - r = uv_fs_readlink(loop, &req, "test_dir_symlink", NULL); + r = uv_fs_readlink(NULL, &req, "test_dir_symlink", NULL); ASSERT(r == 0); #ifdef _WIN32 ASSERT(strcmp(req.ptr, test_dir + 4) == 0); @@ -1753,23 +1752,23 @@ TEST_IMPL(fs_symlink_dir) { #endif uv_fs_req_cleanup(&req); - r = uv_fs_open(loop, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_scandir(loop, &scandir_req, "test_dir_symlink", 0, NULL); + r = uv_fs_scandir(NULL, &scandir_req, "test_dir_symlink", 0, NULL); ASSERT(r == 2); ASSERT(scandir_req.result == 2); ASSERT(scandir_req.ptr); @@ -1785,15 +1784,15 @@ TEST_IMPL(fs_symlink_dir) { ASSERT(!scandir_req.ptr); /* unlink will remove the directory symlink */ - r = uv_fs_unlink(loop, &req, "test_dir_symlink", NULL); + r = uv_fs_unlink(NULL, &req, "test_dir_symlink", NULL); ASSERT(r == 0); uv_fs_req_cleanup(&req); - r = uv_fs_scandir(loop, &scandir_req, "test_dir_symlink", 0, NULL); + r = uv_fs_scandir(NULL, &scandir_req, "test_dir_symlink", 0, NULL); ASSERT(r == UV_ENOENT); uv_fs_req_cleanup(&scandir_req); - r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, NULL); + r = uv_fs_scandir(NULL, &scandir_req, "test_dir", 0, NULL); ASSERT(r == 2); ASSERT(scandir_req.result == 2); ASSERT(scandir_req.ptr); @@ -1830,8 +1829,7 @@ TEST_IMPL(fs_utime) { /* Setup. */ loop = uv_default_loop(); unlink(path); - r = uv_fs_open(loop, &req, path, O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); + r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); uv_fs_req_cleanup(&req); @@ -1839,12 +1837,12 @@ TEST_IMPL(fs_utime) { atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ - r = uv_fs_utime(loop, &req, path, atime, mtime, NULL); + r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); - r = uv_fs_stat(loop, &req, path, NULL); + r = uv_fs_stat(NULL, &req, path, NULL); ASSERT(r == 0); ASSERT(req.result == 0); check_utime(path, atime, mtime); @@ -1875,26 +1873,26 @@ TEST_IMPL(fs_stat_root) { int r; uv_loop_t* loop = uv_default_loop(); - r = uv_fs_stat(loop, &stat_req, "\\", NULL); + r = uv_fs_stat(NULL, &stat_req, "\\", NULL); ASSERT(r == 0); - r = uv_fs_stat(loop, &stat_req, "..\\..\\..\\..\\..\\..\\..", NULL); + r = uv_fs_stat(NULL, &stat_req, "..\\..\\..\\..\\..\\..\\..", NULL); ASSERT(r == 0); - r = uv_fs_stat(loop, &stat_req, "..", NULL); + r = uv_fs_stat(NULL, &stat_req, "..", NULL); ASSERT(r == 0); - r = uv_fs_stat(loop, &stat_req, "..\\", NULL); + r = uv_fs_stat(NULL, &stat_req, "..\\", NULL); ASSERT(r == 0); /* stats the current directory on c: */ - r = uv_fs_stat(loop, &stat_req, "c:", NULL); + r = uv_fs_stat(NULL, &stat_req, "c:", NULL); ASSERT(r == 0); - r = uv_fs_stat(loop, &stat_req, "c:\\", NULL); + r = uv_fs_stat(NULL, &stat_req, "c:\\", NULL); ASSERT(r == 0); - r = uv_fs_stat(loop, &stat_req, "\\\\?\\C:\\", NULL); + r = uv_fs_stat(NULL, &stat_req, "\\\\?\\C:\\", NULL); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); @@ -1915,8 +1913,7 @@ TEST_IMPL(fs_futime) { /* Setup. */ loop = uv_default_loop(); unlink(path); - r = uv_fs_open(loop, &req, path, O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); + r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); uv_fs_req_cleanup(&req); @@ -1924,18 +1921,18 @@ TEST_IMPL(fs_futime) { atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ - r = uv_fs_open(loop, &req, path, O_RDWR, 0, NULL); + r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); file = req.result; /* FIXME probably not how it's supposed to be used */ uv_fs_req_cleanup(&req); - r = uv_fs_futime(loop, &req, file, atime, mtime, NULL); + r = uv_fs_futime(NULL, &req, file, atime, mtime, NULL); ASSERT(r == 0); ASSERT(req.result == 0); uv_fs_req_cleanup(&req); - r = uv_fs_stat(loop, &req, path, NULL); + r = uv_fs_stat(NULL, &req, path, NULL); ASSERT(r == 0); ASSERT(req.result == 0); check_utime(path, atime, mtime); @@ -1968,7 +1965,7 @@ TEST_IMPL(fs_stat_missing_path) { loop = uv_default_loop(); - r = uv_fs_stat(loop, &req, "non_existent_file", NULL); + r = uv_fs_stat(NULL, &req, "non_existent_file", NULL); ASSERT(r == UV_ENOENT); ASSERT(req.result == UV_ENOENT); uv_fs_req_cleanup(&req); @@ -1987,13 +1984,13 @@ TEST_IMPL(fs_scandir_empty_dir) { path = "./empty_dir/"; loop = uv_default_loop(); - uv_fs_mkdir(loop, &req, path, 0777, NULL); + uv_fs_mkdir(NULL, &req, path, 0777, NULL); uv_fs_req_cleanup(&req); /* Fill the req to ensure that required fields are cleaned up */ memset(&req, 0xdb, sizeof(req)); - r = uv_fs_scandir(loop, &req, path, 0, NULL); + r = uv_fs_scandir(NULL, &req, path, 0, NULL); ASSERT(r == 0); ASSERT(req.result == 0); ASSERT(req.ptr == NULL); @@ -2007,7 +2004,7 @@ TEST_IMPL(fs_scandir_empty_dir) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(scandir_cb_count == 1); - uv_fs_rmdir(loop, &req, path, NULL); + uv_fs_rmdir(NULL, &req, path, NULL); uv_fs_req_cleanup(&req); MAKE_VALGRIND_HAPPY(); @@ -2022,7 +2019,7 @@ TEST_IMPL(fs_scandir_file) { path = "test/fixtures/empty_file"; loop = uv_default_loop(); - r = uv_fs_scandir(loop, &scandir_req, path, 0, NULL); + r = uv_fs_scandir(NULL, &scandir_req, path, 0, NULL); ASSERT(r == UV_ENOTDIR); uv_fs_req_cleanup(&scandir_req); @@ -2046,14 +2043,14 @@ TEST_IMPL(fs_open_dir) { path = "."; loop = uv_default_loop(); - r = uv_fs_open(loop, &req, path, O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &req, path, O_RDONLY, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); ASSERT(req.ptr == NULL); 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); r = uv_fs_open(loop, &req, path, O_RDONLY, 0, open_cb_simple); @@ -2076,47 +2073,46 @@ TEST_IMPL(fs_file_open_append) { loop = uv_default_loop(); - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(write_req.result >= 0); uv_fs_req_cleanup(&write_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_file", O_RDWR | O_APPEND, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR | O_APPEND, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(write_req.result >= 0); uv_fs_req_cleanup(&write_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, S_IRUSR, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, - NULL); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); printf("read = %d\n", r); ASSERT(r == 26); ASSERT(read_req.result == 26); @@ -2125,7 +2121,7 @@ TEST_IMPL(fs_file_open_append) { sizeof("test-buffer\n\0test-buffer\n\0") - 1) == 0); uv_fs_req_cleanup(&read_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); @@ -2147,54 +2143,53 @@ TEST_IMPL(fs_rename_to_existing_file) { loop = uv_default_loop(); - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(write_req.result >= 0); uv_fs_req_cleanup(&write_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_file2", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_file2", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_rename(loop, &rename_req, "test_file", "test_file2", NULL); + r = uv_fs_rename(NULL, &rename_req, "test_file", "test_file2", NULL); ASSERT(r == 0); ASSERT(rename_req.result == 0); uv_fs_req_cleanup(&rename_req); - r = uv_fs_open(loop, &open_req1, "test_file2", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); memset(buf, 0, sizeof(buf)); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, - NULL); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(read_req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); uv_fs_req_cleanup(&read_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); @@ -2216,44 +2211,44 @@ TEST_IMPL(fs_read_file_eof) { loop = uv_default_loop(); - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(write_req.result >= 0); uv_fs_req_cleanup(&write_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); memset(buf, 0, sizeof(buf)); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); ASSERT(r >= 0); ASSERT(read_req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); uv_fs_req_cleanup(&read_req); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, read_req.result, NULL); ASSERT(r == 0); ASSERT(read_req.result == 0); uv_fs_req_cleanup(&read_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); @@ -2275,7 +2270,7 @@ TEST_IMPL(fs_write_multiple_bufs) { loop = uv_default_loop(); - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, + r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); @@ -2283,17 +2278,17 @@ TEST_IMPL(fs_write_multiple_bufs) { iovs[0] = uv_buf_init(test_buf, sizeof(test_buf)); iovs[1] = uv_buf_init(test_buf2, sizeof(test_buf2)); - r = uv_fs_write(loop, &write_req, open_req1.result, iovs, 2, 0, NULL); + r = uv_fs_write(NULL, &write_req, open_req1.result, iovs, 2, 0, NULL); ASSERT(r >= 0); ASSERT(write_req.result >= 0); uv_fs_req_cleanup(&write_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2303,7 +2298,7 @@ TEST_IMPL(fs_write_multiple_bufs) { /* Read the strings back to separate buffers. */ iovs[0] = uv_buf_init(buf, sizeof(test_buf)); iovs[1] = uv_buf_init(buf2, sizeof(test_buf2)); - r = uv_fs_read(loop, &read_req, open_req1.result, iovs, 2, 0, NULL); + r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, 2, 0, NULL); ASSERT(r >= 0); ASSERT(read_req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); @@ -2311,13 +2306,13 @@ TEST_IMPL(fs_write_multiple_bufs) { uv_fs_req_cleanup(&read_req); iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, read_req.result, NULL); ASSERT(r == 0); ASSERT(read_req.result == 0); uv_fs_req_cleanup(&read_req); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); ASSERT(r == 0); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); @@ -2328,3 +2323,211 @@ TEST_IMPL(fs_write_multiple_bufs) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(fs_write_alotof_bufs) { + const size_t iovcount = 54321; + uv_buf_t* iovs; + char* buffer; + size_t index; + int r; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + iovs = malloc(sizeof(*iovs) * iovcount); + ASSERT(iovs != NULL); + + r = uv_fs_open(NULL, + &open_req1, + "test_file", + O_RDWR | O_CREAT, + S_IWUSR | S_IRUSR, + NULL); + ASSERT(r >= 0); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + for (index = 0; index < iovcount; ++index) + iovs[index] = uv_buf_init(test_buf, sizeof(test_buf)); + + r = uv_fs_write(NULL, + &write_req, + open_req1.result, + iovs, + iovcount, + -1, + NULL); + ASSERT(r >= 0); + ASSERT((size_t)write_req.result == sizeof(test_buf) * iovcount); + uv_fs_req_cleanup(&write_req); + + /* Read the strings back to separate buffers. */ + buffer = malloc(sizeof(test_buf) * iovcount); + ASSERT(buffer != NULL); + + for (index = 0; index < iovcount; ++index) + iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), + sizeof(test_buf)); + + r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, iovcount, 0, NULL); + ASSERT(r >= 0); + ASSERT((size_t)read_req.result == sizeof(test_buf) * iovcount); + + for (index = 0; index < iovcount; ++index) + ASSERT(strncmp(buffer + index * sizeof(test_buf), + test_buf, + sizeof(test_buf)) == 0); + + uv_fs_req_cleanup(&read_req); + free(buffer); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, + &read_req, + open_req1.result, + &iov, + 1, + read_req.result, + NULL); + ASSERT(r == 0); + ASSERT(read_req.result == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + /* Cleanup */ + unlink("test_file"); + free(iovs); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(fs_write_alotof_bufs_with_offset) { + const size_t iovcount = 54321; + uv_buf_t* iovs; + char* buffer; + size_t index; + int r; + int64_t offset; + char* filler = "0123456789"; + int filler_len = strlen(filler); + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + iovs = malloc(sizeof(*iovs) * iovcount); + ASSERT(iovs != NULL); + + r = uv_fs_open(NULL, + &open_req1, + "test_file", + O_RDWR | O_CREAT, + S_IWUSR | S_IRUSR, + NULL); + ASSERT(r >= 0); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + iov = uv_buf_init(filler, filler_len); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r == filler_len); + ASSERT(write_req.result == filler_len); + uv_fs_req_cleanup(&write_req); + offset = (int64_t)r; + + for (index = 0; index < iovcount; ++index) + iovs[index] = uv_buf_init(test_buf, sizeof(test_buf)); + + r = uv_fs_write(NULL, + &write_req, + open_req1.result, + iovs, + iovcount, + offset, + NULL); + ASSERT(r >= 0); + ASSERT((size_t)write_req.result == sizeof(test_buf) * iovcount); + uv_fs_req_cleanup(&write_req); + + /* Read the strings back to separate buffers. */ + buffer = malloc(sizeof(test_buf) * iovcount); + ASSERT(buffer != NULL); + + for (index = 0; index < iovcount; ++index) + iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), + sizeof(test_buf)); + + r = uv_fs_read(NULL, &read_req, open_req1.result, + iovs, iovcount, offset, NULL); + ASSERT(r >= 0); + ASSERT(read_req.result == sizeof(test_buf) * iovcount); + + for (index = 0; index < iovcount; ++index) + ASSERT(strncmp(buffer + index * sizeof(test_buf), + test_buf, + sizeof(test_buf)) == 0); + + uv_fs_req_cleanup(&read_req); + free(buffer); + + r = uv_fs_stat(NULL, &stat_req, "test_file", NULL); + ASSERT(r == 0); + ASSERT((int64_t)((uv_stat_t*)stat_req.ptr)->st_size == + offset + (int64_t)(iovcount * sizeof(test_buf))); + uv_fs_req_cleanup(&stat_req); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, + &read_req, + open_req1.result, + &iov, + 1, + read_req.result + offset, + NULL); + ASSERT(r == 0); + ASSERT(read_req.result == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + /* Cleanup */ + unlink("test_file"); + free(iovs); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(fs_read_write_null_arguments) { + int r; + + r = uv_fs_read(NULL, NULL, 0, NULL, 0, -1, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_write(NULL, NULL, 0, NULL, 0, -1, NULL); + ASSERT(r == UV_EINVAL); + + iov = uv_buf_init(NULL, 0); + r = uv_fs_read(NULL, NULL, 0, &iov, 0, -1, NULL); + ASSERT(r == UV_EINVAL); + + iov = uv_buf_init(NULL, 0); + r = uv_fs_write(NULL, NULL, 0, &iov, 0, -1, NULL); + ASSERT(r == UV_EINVAL); + + return 0; +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 1e4018c98b..31899664f5 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -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) diff --git a/deps/uv/test/test-pipe-connect-multiple.c b/deps/uv/test/test-pipe-connect-multiple.c new file mode 100644 index 0000000000..3de5a9a0bf --- /dev/null +++ b/deps/uv/test/test-pipe-connect-multiple.c @@ -0,0 +1,104 @@ +/* Copyright (c) 2015 Saúl Ibarra Corretgé . + * 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 +#include + + +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; +} diff --git a/deps/uv/test/test-pipe-pending-instances.c b/deps/uv/test/test-pipe-pending-instances.c new file mode 100644 index 0000000000..b6ff911a0f --- /dev/null +++ b/deps/uv/test/test-pipe-pending-instances.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2015 Saúl Ibarra Corretgé . + * 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; +} diff --git a/deps/uv/test/test-signal-multiple-loops.c b/deps/uv/test/test-signal-multiple-loops.c index f8fef36ee0..158129919b 100644 --- a/deps/uv/test/test-signal-multiple-loops.c +++ b/deps/uv/test/test-signal-multiple-loops.c @@ -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); diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index d01862abe1..e71f0f7d53 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -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 */ diff --git a/deps/uv/test/test-tcp-close-while-connecting.c b/deps/uv/test/test-tcp-close-while-connecting.c index 0a69a0ddee..2c39b652b6 100644 --- a/deps/uv/test/test-tcp-close-while-connecting.c +++ b/deps/uv/test/test-tcp-close-while-connecting.c @@ -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)); diff --git a/deps/uv/test/test-tcp-connect-timeout.c b/deps/uv/test/test-tcp-connect-timeout.c index a22c773c6d..081424b800 100644 --- a/deps/uv/test/test-tcp-connect-timeout.c +++ b/deps/uv/test/test-tcp-connect-timeout.c @@ -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); diff --git a/deps/uv/test/test-tcp-create-socket-early.c b/deps/uv/test/test-tcp-create-socket-early.c new file mode 100644 index 0000000000..65650adcc2 --- /dev/null +++ b/deps/uv/test/test-tcp-create-socket-early.c @@ -0,0 +1,206 @@ +/* Copyright (c) 2015 Saúl Ibarra Corretgé . + * 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 + +#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; +} diff --git a/deps/uv/test/test-tcp-open.c b/deps/uv/test/test-tcp-open.c index edeacc70e4..6c8d43d000 100644 --- a/deps/uv/test/test-tcp-open.c +++ b/deps/uv/test/test-tcp-open.c @@ -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; +} diff --git a/deps/uv/test/test-tcp-squelch-connreset.c b/deps/uv/test/test-tcp-squelch-connreset.c new file mode 100644 index 0000000000..f1c5743797 --- /dev/null +++ b/deps/uv/test/test-tcp-squelch-connreset.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2015, Santiago Gimeno + * + * 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 +#include + + +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; +} diff --git a/deps/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c index f999cba818..cb45622451 100644 --- a/deps/uv/test/test-threadpool-cancel.c +++ b/deps/uv/test/test-threadpool-cancel.c @@ -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)); diff --git a/deps/uv/test/test-udp-create-socket-early.c b/deps/uv/test/test-udp-create-socket-early.c new file mode 100644 index 0000000000..3d0152428b --- /dev/null +++ b/deps/uv/test/test-udp-create-socket-early.c @@ -0,0 +1,132 @@ +/* Copyright (c) 2015 Saúl Ibarra Corretgé . + * 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 + +#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; +} diff --git a/deps/uv/test/test-udp-multicast-interface.c b/deps/uv/test/test-udp-multicast-interface.c index f0679c578e..71001a77e0 100644 --- a/deps/uv/test/test-udp-multicast-interface.c +++ b/deps/uv/test/test-udp-multicast-interface.c @@ -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++; diff --git a/deps/uv/test/test-udp-multicast-join.c b/deps/uv/test/test-udp-multicast-join.c index 686edf3d22..6110a8d922 100644 --- a/deps/uv/test/test-udp-multicast-join.c +++ b/deps/uv/test/test-udp-multicast-join.c @@ -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); diff --git a/deps/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c index 9ba201ab9e..873cb6d811 100644 --- a/deps/uv/test/test-udp-multicast-join6.c +++ b/deps/uv/test/test-udp-multicast-join6.c @@ -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); diff --git a/deps/uv/test/test-udp-multicast-ttl.c b/deps/uv/test/test-udp-multicast-ttl.c index bed0ea1342..7f1af9b9dd 100644 --- a/deps/uv/test/test-udp-multicast-ttl.c +++ b/deps/uv/test/test-udp-multicast-ttl.c @@ -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++; diff --git a/deps/uv/test/test-udp-open.c b/deps/uv/test/test-udp-open.c index b2b6117784..4d77f45d36 100644 --- a/deps/uv/test/test-udp-open.c +++ b/deps/uv/test/test-udp-open.c @@ -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; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 7173a827a3..8049faa7a6 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -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': { -- cgit v1.2.3