From 5ce569c223ca31ea55eac6b3378f959350b33601 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Wed, 6 Sep 2017 09:59:10 -0400 Subject: [PATCH] deps: upgrade libuv to 1.14.1 Fixes: https://github.com/nodejs/node/issues/12737 Fixes: https://github.com/nodejs/node/issues/13581 Fixes: https://github.com/nodejs/node/issues/15117 PR-URL: https://github.com/nodejs/node/pull/14866 Reviewed-By: Refael Ackermann Reviewed-By: James M Snell --- deps/uv/.gitignore | 1 + deps/uv/AUTHORS | 9 + deps/uv/ChangeLog | 115 ++++++++ deps/uv/LICENSE | 4 +- deps/uv/Makefile.am | 14 +- deps/uv/README.md | 9 +- deps/uv/SUPPORTED_PLATFORMS.md | 6 +- deps/uv/android-configure | 5 +- deps/uv/appveyor.yml | 5 +- deps/uv/checksparse.sh | 1 + deps/uv/configure.ac | 2 +- deps/uv/docs/src/async.rst | 6 +- deps/uv/docs/src/fs.rst | 19 +- deps/uv/docs/src/misc.rst | 23 +- deps/uv/docs/src/poll.rst | 15 +- deps/uv/docs/src/stream.rst | 2 +- deps/uv/include/pthread-barrier.h | 1 + deps/uv/include/uv-errno.h | 6 + deps/uv/include/uv-version.h | 2 +- deps/uv/include/uv.h | 19 +- deps/uv/src/unix/aix.c | 21 +- deps/uv/src/unix/android-ifaddrs.c | 41 +-- deps/uv/src/unix/bsd-ifaddrs.c | 15 +- deps/uv/src/unix/core.c | 11 +- deps/uv/src/unix/freebsd.c | 6 +- deps/uv/src/unix/fs.c | 139 ++++++++- deps/uv/src/unix/internal.h | 12 + deps/uv/src/unix/kqueue.c | 35 +++ deps/uv/src/unix/linux-core.c | 14 +- deps/uv/src/unix/netbsd.c | 8 +- deps/uv/src/unix/openbsd.c | 7 +- deps/uv/src/unix/os390-syscalls.c | 23 +- deps/uv/src/unix/os390.c | 38 ++- deps/uv/src/unix/poll.c | 25 +- deps/uv/src/unix/pthread-barrier.c | 121 -------- deps/uv/src/unix/thread.c | 122 +++++++- deps/uv/src/win/dl.c | 55 ++-- deps/uv/src/win/fs.c | 448 +++++++++++------------------ deps/uv/src/win/pipe.c | 2 + deps/uv/src/win/process.c | 9 +- deps/uv/src/win/tcp.c | 15 + deps/uv/src/win/tty.c | 1 + deps/uv/src/win/winapi.h | 4 + deps/uv/test/runner-win.c | 1 - deps/uv/test/test-dlerror.c | 2 + deps/uv/test/test-fs-copyfile.c | 150 ++++++++++ deps/uv/test/test-fs.c | 111 ++++++- deps/uv/test/test-list.h | 20 ++ deps/uv/test/test-poll-oob.c | 205 +++++++++++++ deps/uv/test/test-spawn.c | 32 ++- deps/uv/test/test-tcp-oob.c | 13 + deps/uv/test/test-tcp-open.c | 57 ++++ deps/uv/uv.gyp | 7 +- deps/uv/vcbuild.bat | 7 +- 54 files changed, 1486 insertions(+), 555 deletions(-) delete mode 100644 deps/uv/src/unix/pthread-barrier.c create mode 100644 deps/uv/test/test-fs-copyfile.c create mode 100644 deps/uv/test/test-poll-oob.c diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index eb54f92488d7b2..7536abd54970a2 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -39,6 +39,7 @@ Makefile.in # Generated by gyp for android *.target.mk +/android-toolchain /out/ /build/gyp diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 4ef241092701d2..3562bb81698b66 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -299,3 +299,12 @@ Barnabas Gema Romain Caire Robert Ayrapetyan Refael Ackermann +André Klitzing +Matthew Taylor +CurlyMoo +XadillaX +Anticrisis +Jacob Segal +Maciej Szeptuch (Neverous) +Joel Winarske +Gergely Nagy diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 67c99df82eaee7..d0b55750172152 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,118 @@ +2017.09.07, Version 1.14.1 (Stable), b0f9fb2a07a5e638b1580fe9a42a356c3ab35f37 + +Changes since version 1.14.0: + +* fs, win: add support for user symlinks (Bartosz Sosnowski) + +* cygwin: include uv-posix.h header (Joel Winarske) + +* zos: fix semaphore initialization (jBarz) + +* zos: improve loop_count benchmark performance (jBarz) + +* zos, test: flush out the oob data in callback (jBarz) + +* unix,win: check for bad flags in uv_fs_copyfile() (cjihrig) + +* unix: modify argv[0] when process title is set (Matthew Taylor) + +* unix: don't use req->loop in uv__fs_copyfile() (cjihrig) + +* doc: fix a trivial typo (Vladimír Čunát) + +* android: fix uv_cond_timedwait on API level < 21 (Gergely Nagy) + +* win: add uv__once_init() calls (Bartosz Sosnowski) + +* unix,windows: init all requests in fs calls (cjihrig) + +* unix,windows: return UV_EINVAL on NULL fs reqs (cjihrig) + +* windows: add POST macro to fs functions (cjihrig) + +* unix: handle partial sends in uv_fs_copyfile() (A. Hauptmann) + +* Revert "win, test: fix double close in test runner" (Bartosz Sosnowski) + +* win, test: remove surplus CloseHandle (Bartosz Sosnowski) + + +2017.08.17, Version 1.14.0 (Stable), e0d31e9e21870f88277746b6d59cf07b977cdfea + +Changes since version 1.13.1: + +* unix: check for NULL in uv_os_unsetenv for parameter name (André Klitzing) + +* doc: add thread safety warning for process title (Matthew Taylor) + +* unix: always copy process title into local buffer (Matthew Taylor) + +* poll: add support for OOB TCP and GPIO interrupts (CurlyMoo) + +* win,build: fix appveyor properly (Refael Ackermann) + +* win: include filename in dlopen error message (Ben Noordhuis) + +* aix: add netmask, mac address into net interfaces (Gireesh Punathil) + +* unix, windows: map EREMOTEIO errno (Ben Noordhuis) + +* unix: fix wrong MAC of uv_interface_address (XadillaX) + +* win,build: fix building from Windows SDK or VS console (Saúl Ibarra Corretgé) + +* github: fix link to help repo in issue template (Ben Noordhuis) + +* zos: remove nonexistent include from autotools build (Saúl Ibarra Corretgé) + +* misc: remove reference to pthread-fixes.h from LICENSE (Saúl Ibarra Corretgé) + +* docs: fix guide source code example paths (Anticrisis) + +* android: fix compilation with new NDK versions (Saúl Ibarra Corretgé) + +* misc: add android-toolchain to .gitignore (Saúl Ibarra Corretgé) + +* win, fs: support unusual reparse points (Bartosz Sosnowski) + +* android: fix detection of pthread_condattr_setclock (Saúl Ibarra Corretgé) + +* android: remove no longer needed check (Saúl Ibarra Corretgé) + +* doc: update instructions for building on Android (Saúl Ibarra Corretgé) + +* win, process: support semicolons in PATH variable (Bartosz Sosnowski) + +* doc: document uv_async_(init|send) return values (Ben Noordhuis) + +* doc: add Android as a tier 3 supported platform (Saúl Ibarra Corretgé) + +* unix: add missing semicolon (jBarz) + +* win, test: fix double close in test runner (Bartosz Sosnowski) + +* doc: update supported windows version baseline (Ben Noordhuis) + +* test,zos: skip chown root test (jBarz) + +* test,zos: use gid=-1 to test spawn_setgid_fails (jBarz) + +* zos: fix hr timer resolution (jBarz) + +* android: fix blocking recvmsg due to netlink bug (Jacob Segal) + +* zos: read more accurate rss info from RSM (jBarz) + +* win: allow bound/connected socket in uv_tcp_open() (Maciej Szeptuch + (Neverous)) + +* doc: differentiate SmartOS and SunOS support (cjihrig) + +* unix: make uv_poll_stop() remove fd from pollset (Ben Noordhuis) + +* unix, windows: add basic uv_fs_copyfile() (cjihrig) + + 2017.07.07, Version 1.13.1 (Stable), 2bb4b68758f07cd8617838e68c44c125bc567ba6 Changes since version 1.13.0: diff --git a/deps/uv/LICENSE b/deps/uv/LICENSE index 41ba44c2857a49..28f17339e29ca6 100644 --- a/deps/uv/LICENSE +++ b/deps/uv/LICENSE @@ -62,8 +62,8 @@ The externally maintained libraries used by libuv are: - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three clause BSD license. - - pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile - Communications AB. Three clause BSD license. + - pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB. + Three clause BSD license. - android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 404674baf211d5..b94fdd63b58eea 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -169,6 +169,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-env-vars.c \ test/test-error.c \ test/test-fail-always.c \ + test/test-fs-copyfile.c \ test/test-fs-event.c \ test/test-fs-poll.c \ test/test-fs.c \ @@ -212,10 +213,11 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-pipe-close-stdout-read-stdin.c \ test/test-pipe-set-non-blocking.c \ test/test-platform-output.c \ + test/test-poll.c \ test/test-poll-close.c \ test/test-poll-close-doesnt-corrupt-stack.c \ test/test-poll-closesocket.c \ - test/test-poll.c \ + test/test-poll-oob.c \ test/test-process-title.c \ test/test-queue-foreach-delete.c \ test/test-ref.c \ @@ -333,11 +335,11 @@ if ANDROID include_HEADERS += include/android-ifaddrs.h \ include/pthread-barrier.h libuv_la_SOURCES += src/unix/android-ifaddrs.c \ - src/unix/pthread-fixes.c \ - src/unix/pthread-barrier.c + src/unix/pthread-fixes.c endif if CYGWIN +include_HEADERS += include/uv-posix.h libuv_la_CFLAGS += -D_GNU_SOURCE libuv_la_SOURCES += src/unix/cygwin.c \ src/unix/bsd-ifaddrs.c \ @@ -360,8 +362,7 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/darwin-proctitle.c \ src/unix/fsevents.c \ src/unix/kqueue.c \ - src/unix/proctitle.c \ - src/unix/pthread-barrier.c + src/unix/proctitle.c test_run_tests_LDFLAGS += -lutil endif @@ -436,7 +437,7 @@ libuv_la_SOURCES += src/unix/no-proctitle.c \ endif if OS390 -include_HEADERS += include/pthread-fixes.h include/pthread-barrier.h +include_HEADERS += include/pthread-barrier.h libuv_la_CFLAGS += -D_UNIX03_THREADS \ -D_UNIX03_SOURCE \ -D_OPEN_SYS_IF_EXT=1 \ @@ -453,7 +454,6 @@ libuv_la_CFLAGS += -D_UNIX03_THREADS \ -qFLOAT=IEEE libuv_la_LDFLAGS += -qXPLINK libuv_la_SOURCES += src/unix/pthread-fixes.c \ - src/unix/pthread-barrier.c \ src/unix/no-fsevents.c \ src/unix/os390.c \ src/unix/os390-syscalls.c \ diff --git a/deps/uv/README.md b/deps/uv/README.md index 372d514e049c39..733171be085ab5 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -267,7 +267,14 @@ Make sure that you specify the architecture you wish to build for in the Run: ```bash -$ source ./android-configure NDK_PATH gyp +$ source ./android-configure NDK_PATH gyp [API_LEVEL] +$ make -C out +``` + +The default API level is 24, but a different one can be selected as follows: + +```bash +$ source ./android-configure ~/android-ndk-r15b gyp 21 $ make -C out ``` diff --git a/deps/uv/SUPPORTED_PLATFORMS.md b/deps/uv/SUPPORTED_PLATFORMS.md index 3a000c5dd25e35..08fd5f4a9a1100 100644 --- a/deps/uv/SUPPORTED_PLATFORMS.md +++ b/deps/uv/SUPPORTED_PLATFORMS.md @@ -4,13 +4,15 @@ |---|---|---|---| | GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | | | macOS | Tier 1 | macOS >= 10.7 | | -| Windows | Tier 1 | Windows >= XP SP1 | MSVC 2008 and later are supported | +| Windows | Tier 1 | Windows >= 8.1 | MSVC 2008 and later are supported | | FreeBSD | Tier 1 | >= 9 (see note) | | | AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix | | z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos | | Linux with musl | Tier 2 | musl >= 1.0 | | -| SunOS | Tier 2 | Solaris 121 and later | Maintainers: @libuv/sunos | +| SmartOS | Tier 2 | >= 14.4 | Maintainers: @libuv/smartos | +| Android | Tier 3 | NDK >= r15b | | | MinGW | Tier 3 | MinGW32 and MinGW-w64 | | +| SunOS | Tier 3 | Solaris 121 and later | | | Other | Tier 3 | N/A | | #### Note on FreeBSD 9 diff --git a/deps/uv/android-configure b/deps/uv/android-configure index 7ffc035c1bfbfc..b5c11cd40c6873 100755 --- a/deps/uv/android-configure +++ b/deps/uv/android-configure @@ -2,17 +2,20 @@ export TOOLCHAIN=$PWD/android-toolchain mkdir -p $TOOLCHAIN +API=${3:-24} $1/build/tools/make-standalone-toolchain.sh \ --toolchain=arm-linux-androideabi-4.9 \ --arch=arm \ --install-dir=$TOOLCHAIN \ - --platform=android-21 + --platform=android-$API \ + --force export PATH=$TOOLCHAIN/bin:$PATH export AR=arm-linux-androideabi-ar export CC=arm-linux-androideabi-gcc export CXX=arm-linux-androideabi-g++ export LINK=arm-linux-androideabi-g++ export PLATFORM=android +export CFLAGS="-D__ANDROID_API__=$API" if [[ $2 == 'gyp' ]] then diff --git a/deps/uv/appveyor.yml b/deps/uv/appveyor.yml index be90ef7b435c74..986c0d44030e5b 100644 --- a/deps/uv/appveyor.yml +++ b/deps/uv/appveyor.yml @@ -1,4 +1,7 @@ -version: v1.13.1.build{build} +version: v1.14.1.build{build} + +init: + - git config --global core.autocrlf true install: - cinst -y nsis diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh index 9782718a23266c..ae0e5374f5efba 100755 --- a/deps/uv/checksparse.sh +++ b/deps/uv/checksparse.sh @@ -96,6 +96,7 @@ test/test-embed.c test/test-env-vars.c test/test-error.c test/test-fail-always.c +test/test-fs-copyfile.c test/test-fs-event.c test/test-fs-poll.c test/test-fs.c diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index a52cfc622cbb5f..41349a092c85e6 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.13.1], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.14.1], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/uv/docs/src/async.rst b/deps/uv/docs/src/async.rst index 5c400458244a86..02e6a58e7838db 100644 --- a/deps/uv/docs/src/async.rst +++ b/deps/uv/docs/src/async.rst @@ -35,12 +35,16 @@ API Initialize the handle. A NULL callback is allowed. + :returns: 0 on success, or an error code < 0 on failure. + .. note:: Unlike other handle initialization functions, it immediately starts the handle. .. c:function:: int uv_async_send(uv_async_t* async) - Wakeup the event loop and call the async handle's callback. + Wake up the event loop and call the async handle's callback. + + :returns: 0 on success, or an error code < 0 on failure. .. note:: It's safe to call this function from any thread. The callback will be called on the diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index 3f766e393f2fa7..2db915bc9e6706 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -92,7 +92,8 @@ Data types UV_FS_READLINK, UV_FS_CHOWN, UV_FS_FCHOWN, - UV_FS_REALPATH + UV_FS_REALPATH, + UV_FS_COPYFILE } uv_fs_type; .. c:type:: uv_dirent_t @@ -241,6 +242,22 @@ API Equivalent to :man:`ftruncate(2)`. +.. c:function:: int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb) + + Copies a file from `path` to `new_path`. Supported `flags` are described below. + + - `UV_FS_COPYFILE_EXCL`: If present, `uv_fs_copyfile()` will fail with + `UV_EEXIST` if the destination path already exists. The default behavior + is to overwrite the destination if it exists. + + .. warning:: + If the destination path is created, but an error occurs while copying + the data, then the destination path is removed. There is a brief window + of time between closing and removing the file where another process + could access the file. + + .. versionadded:: 1.14.0 + .. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb) Limited equivalent to :man:`sendfile(2)`. diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 9d7c3617e864bb..3fea708a8d38e2 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -186,17 +186,24 @@ API .. c:function:: int uv_get_process_title(char* buffer, size_t size) - Gets the title of the current process. If `buffer` is `NULL` or `size` is - zero, `UV_EINVAL` is returned. If `size` cannot accommodate the process - title and terminating `NULL` character, the function returns `UV_ENOBUFS`. + Gets the title of the current process. You *must* call `uv_setup_args` + before calling this function. If `buffer` is `NULL` or `size` is zero, + `UV_EINVAL` is returned. If `size` cannot accommodate the process title and + terminating `NULL` character, the function returns `UV_ENOBUFS`. + + .. warning:: + `uv_get_process_title` is not thread safe on any platform except Windows. .. c:function:: int uv_set_process_title(const char* title) - Sets the current process title. On platforms with a fixed size buffer for the - process title the contents of `title` will be copied to the buffer and - truncated if larger than the available space. Other platforms will return - `UV_ENOMEM` if they cannot allocate enough space to duplicate the contents of - `title`. + Sets the current process title. You *must* call `uv_setup_args` before + calling this function. On platforms with a fixed size buffer for the process + title the contents of `title` will be copied to the buffer and truncated if + larger than the available space. Other platforms will return `UV_ENOMEM` if + they cannot allocate enough space to duplicate the contents of `title`. + + .. warning:: + `uv_set_process_title` is not thread safe on any platform except Windows. .. c:function:: int uv_resident_set_memory(size_t* rss) diff --git a/deps/uv/docs/src/poll.rst b/deps/uv/docs/src/poll.rst index 004ff4b92e5ea5..aba8915886bb5f 100644 --- a/deps/uv/docs/src/poll.rst +++ b/deps/uv/docs/src/poll.rst @@ -54,7 +54,8 @@ Data types enum uv_poll_event { UV_READABLE = 1, UV_WRITABLE = 2, - UV_DISCONNECT = 4 + UV_DISCONNECT = 4, + UV_PRIORITIZED = 8 }; @@ -84,10 +85,13 @@ API .. c:function:: int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) - Starts polling the file descriptor. `events` is a bitmask consisting made up - of UV_READABLE, UV_WRITABLE and UV_DISCONNECT. As soon as an event is detected - the callback will be called with `status` set to 0, and the detected events set on the - `events` field. + Starts polling the file descriptor. `events` is a bitmask made up of + UV_READABLE, UV_WRITABLE, UV_PRIORITIZED and UV_DISCONNECT. As soon as an + event is detected the callback will be called with `status` set to 0, and the + detected events set on the `events` field. + + The UV_PRIORITIZED event is used to watch for sysfs interrupts or TCP out-of-band + messages. The UV_DISCONNECT event is optional in the sense that it may not be reported and the user is free to ignore it, but it can help optimize the shutdown @@ -108,6 +112,7 @@ API on the `events` field in the callback. .. versionchanged:: 1.9.0 Added the UV_DISCONNECT event. + .. versionchanged:: 1.14.0 Added the UV_PRIORITIZED event. .. c:function:: int uv_poll_stop(uv_poll_t* poll) diff --git a/deps/uv/docs/src/stream.rst b/deps/uv/docs/src/stream.rst index de492b3578152b..1f4e87e63a9db3 100644 --- a/deps/uv/docs/src/stream.rst +++ b/deps/uv/docs/src/stream.rst @@ -6,7 +6,7 @@ Stream handles provide an abstraction of a duplex communication channel. :c:type:`uv_stream_t` is an abstract type, libuv provides 3 stream implementations -in the for of :c:type:`uv_tcp_t`, :c:type:`uv_pipe_t` and :c:type:`uv_tty_t`. +in the form of :c:type:`uv_tcp_t`, :c:type:`uv_pipe_t` and :c:type:`uv_tty_t`. Data types diff --git a/deps/uv/include/pthread-barrier.h b/deps/uv/include/pthread-barrier.h index 900ebedd308b26..07db9b8a6a27e0 100644 --- a/deps/uv/include/pthread-barrier.h +++ b/deps/uv/include/pthread-barrier.h @@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #endif #define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 +#define UV__PTHREAD_BARRIER_FALLBACK 1 /* * To maintain ABI compatibility with diff --git a/deps/uv/include/uv-errno.h b/deps/uv/include/uv-errno.h index f1371517cc32fe..32bbc5177e4b2d 100644 --- a/deps/uv/include/uv-errno.h +++ b/deps/uv/include/uv-errno.h @@ -416,4 +416,10 @@ # define UV__EHOSTDOWN (-4031) #endif +#if defined(EREMOTEIO) && !defined(_WIN32) +# define UV__EREMOTEIO (-EREMOTEIO) +#else +# define UV__EREMOTEIO (-4030) +#endif + #endif /* UV_ERRNO_H_ */ diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index c80c40ea7f1bb0..9b891499eb5f4a 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -31,7 +31,7 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 13 +#define UV_VERSION_MINOR 14 #define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index f076094ccdc24c..eac63dde445829 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -140,6 +140,7 @@ extern "C" { XX(ENXIO, "no such device or address") \ XX(EMLINK, "too many links") \ XX(EHOSTDOWN, "host is down") \ + XX(EREMOTEIO, "remote I/O error") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ @@ -719,7 +720,8 @@ struct uv_poll_s { enum uv_poll_event { UV_READABLE = 1, UV_WRITABLE = 2, - UV_DISCONNECT = 4 + UV_DISCONNECT = 4, + UV_PRIORITIZED = 8 }; UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd); @@ -1112,7 +1114,8 @@ typedef enum { UV_FS_READLINK, UV_FS_CHOWN, UV_FS_FCHOWN, - UV_FS_REALPATH + UV_FS_REALPATH, + UV_FS_COPYFILE } uv_fs_type; /* uv_fs_t is a subclass of uv_req_t. */ @@ -1157,6 +1160,18 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop, unsigned int nbufs, int64_t offset, uv_fs_cb cb); +/* + * This flag can be used with uv_fs_copyfile() to return an error if the + * destination already exists. + */ +#define UV_FS_COPYFILE_EXCL 0x0001 + +UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + const char* new_path, + int flags, + uv_fs_cb cb); UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index 426f7f4735fd39..56a8f4ffe753e8 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -1108,9 +1108,10 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { uv_interface_address_t* address; - int sockfd, size = 1; + int sockfd, inet6, size = 1; struct ifconf ifc; struct ifreq *ifr, *p, flg; + struct sockaddr_dl* sa_addr; *count = 0; @@ -1174,6 +1175,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, p->ifr_addr.sa_family == AF_INET)) continue; + inet6 = (p->ifr_addr.sa_family == AF_INET6); + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { uv__close(sockfd); @@ -1187,13 +1190,23 @@ int uv_interface_addresses(uv_interface_address_t** addresses, address->name = uv__strdup(p->ifr_name); - if (p->ifr_addr.sa_family == AF_INET6) { + if (inet6) address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); - } else { + else address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); + + sa_addr = (struct sockaddr_dl*) &p->ifr_addr; + memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); + + if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) { + uv__close(sockfd); + return -ENOSYS; } - /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ + if (inet6) + address->netmask.netmask6 = *((struct sockaddr_in6*) &p->ifr_addr); + else + address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; diff --git a/deps/uv/src/unix/android-ifaddrs.c b/deps/uv/src/unix/android-ifaddrs.c index 30f681b7d04a41..1a842ced48f9b5 100644 --- a/deps/uv/src/unix/android-ifaddrs.c +++ b/deps/uv/src/unix/android-ifaddrs.c @@ -43,9 +43,10 @@ typedef struct NetlinkList unsigned int m_size; } NetlinkList; -static int netlink_socket(void) +static int netlink_socket(pid_t *p_pid) { struct sockaddr_nl l_addr; + socklen_t l_len; int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if(l_socket < 0) @@ -61,6 +62,14 @@ static int netlink_socket(void) return -1; } + l_len = sizeof(l_addr); + if(getsockname(l_socket, (struct sockaddr *)&l_addr, &l_len) < 0) + { + close(l_socket); + return -1; + } + *p_pid = l_addr.nl_pid; + return l_socket; } @@ -128,7 +137,7 @@ static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) } } -static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) +static struct nlmsghdr *getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done) { size_t l_size = 4096; void *l_buffer = NULL; @@ -153,11 +162,10 @@ static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_don } if(l_read >= 0) { - pid_t l_pid = getpid(); struct nlmsghdr *l_hdr; for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } @@ -207,7 +215,7 @@ static void freeResultList(NetlinkList *p_list) } } -static NetlinkList *getResultList(int p_socket, int p_request) +static NetlinkList *getResultList(int p_socket, int p_request, pid_t p_pid) { int l_size; int l_done; @@ -227,7 +235,7 @@ static NetlinkList *getResultList(int p_socket, int p_request) { NetlinkList *l_item; - struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); + struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, p_pid, &l_size, &l_done); /* Error */ if(!l_hdr) { @@ -578,18 +586,17 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, return 0; } -static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) +static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) { int l_numLinks = 0; - pid_t l_pid = getpid(); for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) { unsigned int l_nlsize = p_netlinkList->m_size; struct nlmsghdr *l_hdr; for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } @@ -612,16 +619,15 @@ static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifadd return l_numLinks; } -static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) +static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) { - pid_t l_pid = getpid(); for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) { unsigned int l_nlsize = p_netlinkList->m_size; struct nlmsghdr *l_hdr; for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) + if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } @@ -648,6 +654,7 @@ int getifaddrs(struct ifaddrs **ifap) int l_socket; int l_result; int l_numLinks; + pid_t l_pid; NetlinkList *l_linkResults; NetlinkList *l_addrResults; @@ -657,20 +664,20 @@ int getifaddrs(struct ifaddrs **ifap) } *ifap = NULL; - l_socket = netlink_socket(); + l_socket = netlink_socket(&l_pid); if(l_socket < 0) { return -1; } - l_linkResults = getResultList(l_socket, RTM_GETLINK); + l_linkResults = getResultList(l_socket, RTM_GETLINK, l_pid); if(!l_linkResults) { close(l_socket); return -1; } - l_addrResults = getResultList(l_socket, RTM_GETADDR); + l_addrResults = getResultList(l_socket, RTM_GETADDR, l_pid); if(!l_addrResults) { close(l_socket); @@ -679,8 +686,8 @@ int getifaddrs(struct ifaddrs **ifap) } l_result = 0; - l_numLinks = interpretLinks(l_socket, l_linkResults, ifap); - if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1) + l_numLinks = interpretLinks(l_socket, l_pid, l_linkResults, ifap); + if(l_numLinks == -1 || interpretAddrs(l_socket, l_pid, l_addrResults, ifap, l_numLinks) == -1) { l_result = -1; } diff --git a/deps/uv/src/unix/bsd-ifaddrs.c b/deps/uv/src/unix/bsd-ifaddrs.c index 414789451ab3d6..ffcf156440d559 100644 --- a/deps/uv/src/unix/bsd-ifaddrs.c +++ b/deps/uv/src/unix/bsd-ifaddrs.c @@ -31,11 +31,18 @@ #include #endif -static int uv__ifaddr_exclude(struct ifaddrs *ent) { +static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) return 1; if (ent->ifa_addr == NULL) return 1; + /* + * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, just see whether `sa_family` + * equals to `AF_LINK` or not. Otherwise, the result depends on the operation + * system with `AF_LINK` or `PF_INET`. + */ + if (exclude_type == UV__EXCLUDE_IFPHYS) + return (ent->ifa_addr->sa_family != AF_LINK); #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) /* * On BSD getifaddrs returns information related to the raw underlying @@ -63,7 +70,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { /* Count the number of interfaces */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent)) + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) continue; (*count)++; } @@ -78,7 +85,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address = *addresses; for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent)) + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) continue; address->name = uv__strdup(ent->ifa_name); @@ -102,7 +109,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { /* Fill in physical addresses for each interface */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent)) + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS)) continue; address = *addresses; diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 4c744925e29607..bee641cb440410 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -838,7 +838,7 @@ 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) { - assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); + assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI))); assert(0 != events); assert(w->fd >= 0); assert(w->fd < INT_MAX); @@ -866,7 +866,7 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); + assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI))); assert(0 != events); if (w->fd == -1) @@ -898,7 +898,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { void uv__io_close(uv_loop_t* loop, uv__io_t* w) { - uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP); + uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); QUEUE_REMOVE(&w->pending_queue); /* Remove stale events for this file descriptor */ @@ -913,7 +913,7 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w) { int uv__io_active(const uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); + assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI))); assert(0 != events); return 0 != (w->pevents & events); } @@ -1292,6 +1292,9 @@ int uv_os_setenv(const char* name, const char* value) { int uv_os_unsetenv(const char* name) { + if (name == NULL) + return -EINVAL; + if (unsetenv(name) != 0) return -errno; diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index c3c4902be9a568..dba94298d1c06d 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -160,9 +160,13 @@ char** uv_setup_args(int argc, char** argv) { int uv_set_process_title(const char* title) { int oid[4]; + char* new_title; + new_title = uv__strdup(title); + if (process_title == NULL) + return -ENOMEM; uv__free(process_title); - process_title = uv__strdup(title); + process_title = new_title; oid[0] = CTL_KERN; oid[1] = KERN_PROC; diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index f9513ea55a03eb..5a172cc7805171 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -60,8 +60,14 @@ # include #endif +#if defined(__APPLE__) +# include +#endif + #define INIT(subtype) \ do { \ + if (req == NULL) \ + return -EINVAL; \ req->type = UV_FS; \ if (cb != NULL) \ uv__req_init(loop, req, UV_FS); \ @@ -766,6 +772,112 @@ static ssize_t uv__fs_write(uv_fs_t* req) { return r; } +static ssize_t uv__fs_copyfile(uv_fs_t* req) { +#if defined(__APPLE__) && !TARGET_OS_IPHONE + /* On macOS, use the native copyfile(3). */ + copyfile_flags_t flags; + + flags = COPYFILE_ALL; + + if (req->flags & UV_FS_COPYFILE_EXCL) + flags |= COPYFILE_EXCL; + + return copyfile(req->path, req->new_path, NULL, flags); +#else + uv_fs_t fs_req; + uv_file srcfd; + uv_file dstfd; + struct stat statsbuf; + int dst_flags; + int result; + int err; + size_t bytes_to_send; + int64_t in_offset; + + dstfd = -1; + + /* Open the source file. */ + srcfd = uv_fs_open(NULL, &fs_req, req->path, O_RDONLY, 0, NULL); + uv_fs_req_cleanup(&fs_req); + + if (srcfd < 0) + return srcfd; + + /* Get the source file's mode. */ + if (fstat(srcfd, &statsbuf)) { + err = -errno; + goto out; + } + + dst_flags = O_WRONLY | O_CREAT; + + if (req->flags & UV_FS_COPYFILE_EXCL) + dst_flags |= O_EXCL; + + /* Open the destination file. */ + dstfd = uv_fs_open(NULL, + &fs_req, + req->new_path, + dst_flags, + statsbuf.st_mode, + NULL); + uv_fs_req_cleanup(&fs_req); + + if (dstfd < 0) { + err = dstfd; + goto out; + } + + bytes_to_send = statsbuf.st_size; + in_offset = 0; + while (bytes_to_send != 0) { + err = uv_fs_sendfile(NULL, + &fs_req, + dstfd, + srcfd, + in_offset, + bytes_to_send, + NULL); + uv_fs_req_cleanup(&fs_req); + if (err < 0) + break; + bytes_to_send -= fs_req.result; + in_offset += fs_req.result; + } + +out: + if (err < 0) + result = err; + else + result = 0; + + /* Close the source file. */ + err = uv__close_nocheckstdio(srcfd); + + /* Don't overwrite any existing errors. */ + if (err != 0 && result == 0) + result = err; + + /* Close the destination file if it is open. */ + if (dstfd >= 0) { + err = uv__close_nocheckstdio(dstfd); + + /* Don't overwrite any existing errors. */ + if (err != 0 && result == 0) + result = err; + + /* Remove the destination file if something went wrong. */ + if (result != 0) { + uv_fs_unlink(NULL, &fs_req, req->new_path, NULL); + /* Ignore the unlink return value, as an error already happened. */ + uv_fs_req_cleanup(&fs_req); + } + } + + return result; +#endif +} + static void uv__to_stat(struct stat* src, uv_stat_t* dst) { dst->st_dev = src->st_dev; dst->st_mode = src->st_mode; @@ -946,6 +1058,7 @@ static void uv__fs_work(struct uv__work* w) { X(CHMOD, chmod(req->path, req->mode)); X(CHOWN, chown(req->path, req->uid, req->gid)); X(CLOSE, close(req->file)); + X(COPYFILE, uv__fs_copyfile(req)); X(FCHMOD, fchmod(req->file, req->mode)); X(FCHOWN, fchown(req->file, req->uid, req->gid)); X(FDATASYNC, uv__fs_fdatasync(req)); @@ -1186,10 +1299,11 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, unsigned int nbufs, int64_t off, uv_fs_cb cb) { + INIT(READ); + if (bufs == NULL || nbufs == 0) return -EINVAL; - INIT(READ); req->file = file; req->nbufs = nbufs; @@ -1324,10 +1438,11 @@ int uv_fs_write(uv_loop_t* loop, unsigned int nbufs, int64_t off, uv_fs_cb cb) { + INIT(WRITE); + if (bufs == NULL || nbufs == 0) return -EINVAL; - INIT(WRITE); req->file = file; req->nbufs = nbufs; @@ -1349,6 +1464,9 @@ int uv_fs_write(uv_loop_t* loop, void uv_fs_req_cleanup(uv_fs_t* req) { + if (req == NULL) + return; + /* 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 @@ -1367,3 +1485,20 @@ void uv_fs_req_cleanup(uv_fs_t* req) { uv__free(req->ptr); req->ptr = NULL; } + + +int uv_fs_copyfile(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + const char* new_path, + int flags, + uv_fs_cb cb) { + INIT(COPYFILE); + + if (flags & ~UV_FS_COPYFILE_EXCL) + return -EINVAL; + + PATH2; + req->flags = flags; + POST; +} diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 2e3afa6c856827..c0898d982e9815 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -110,6 +110,12 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); # define UV__POLLRDHUP 0x2000 #endif +#ifdef POLLPRI +# define UV__POLLPRI POLLPRI +#else +# define UV__POLLPRI 0 +#endif + #if !defined(O_CLOEXEC) && defined(__FreeBSD__) /* * It may be that we are just missing `__POSIX_VISIBLE >= 200809`. @@ -145,6 +151,12 @@ enum { UV_LOOP_BLOCK_SIGPROF = 1 }; +/* flags of excluding ifaddr */ +enum { + UV__EXCLUDE_IFPHYS, + UV__EXCLUDE_IFADDR +}; + typedef enum { UV_CLOCK_PRECISE = 0, /* Use the highest resolution clock available. */ UV_CLOCK_FAST = 1 /* Use the fastest clock with <= 1ms granularity. */ diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 6bc60bbe46885e..300bac07c3322f 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -34,6 +34,17 @@ #include #include +/* + * Required on + * - Until at least FreeBSD 11.0 + * - Older versions of Mac OS X + * + * http://www.boost.org/doc/libs/1_61_0/boost/asio/detail/kqueue_reactor.hpp + */ +#ifndef EV_OOBAND +#define EV_OOBAND EV_FLAG1 +#endif + static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags); @@ -166,6 +177,16 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } } + if ((w->events & UV__POLLPRI) == 0 && (w->pevents & UV__POLLPRI) != 0) { + EV_SET(events + nevents, w->fd, EV_OOBAND, EV_ADD, 0, 0, 0); + + if (++nevents == ARRAY_SIZE(events)) { + if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) + abort(); + nevents = 0; + } + } + w->events = w->pevents; } @@ -275,6 +296,20 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } } + if (ev->filter == EV_OOBAND) { + if (w->pevents & UV__POLLPRI) { + revents |= UV__POLLPRI; + w->rcount = ev->data; + } else { + /* TODO batch up */ + struct kevent events[1]; + EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); + if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) + if (errno != ENOENT) + abort(); + } + } + if (ev->filter == EVFILT_WRITE) { if (w->pevents & POLLOUT) { revents |= POLLOUT; diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 2866e938545cb3..4d480ce10a2585 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -388,7 +388,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * free when we switch over to edge-triggered I/O. */ if (pe->events == POLLERR || pe->events == POLLHUP) - pe->events |= w->pevents & (POLLIN | POLLOUT); + pe->events |= w->pevents & (POLLIN | POLLOUT | UV__POLLPRI); if (pe->events != 0) { /* Run signal watchers last. This also affects child process watchers @@ -837,7 +837,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } -static int uv__ifaddr_exclude(struct ifaddrs *ent) { +static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) return 1; if (ent->ifa_addr == NULL) @@ -847,8 +847,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) { * devices. We're not interested in this information yet. */ if (ent->ifa_addr->sa_family == PF_PACKET) - return 1; - return 0; + return exclude_type; + return !exclude_type; } int uv_interface_addresses(uv_interface_address_t** addresses, @@ -869,7 +869,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, /* Count the number of interfaces */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent)) + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) continue; (*count)++; @@ -887,7 +887,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, address = *addresses; for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent)) + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) continue; address->name = uv__strdup(ent->ifa_name); @@ -911,7 +911,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, /* Fill in physical addresses for each interface */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent)) + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS)) continue; address = *addresses; diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c index 9b5546b7e6959b..c54c04df28c201 100644 --- a/deps/uv/src/unix/netbsd.c +++ b/deps/uv/src/unix/netbsd.c @@ -124,9 +124,13 @@ char** uv_setup_args(int argc, char** argv) { int uv_set_process_title(const char* title) { - if (process_title) uv__free(process_title); + char* new_title; - process_title = uv__strdup(title); + new_title = uv__strdup(title); + if (process_title == NULL) + return -ENOMEM; + uv__free(process_title); + process_title = new_title; setproctitle("%s", title); return 0; diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index 56f0af15c3ef3f..d1c90289e5691e 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -146,8 +146,13 @@ char** uv_setup_args(int argc, char** argv) { int uv_set_process_title(const char* title) { + char* new_title; + + new_title = uv__strdup(title); + if (process_title == NULL) + return -ENOMEM; uv__free(process_title); - process_title = uv__strdup(title); + process_title = new_title; setproctitle("%s", title); return 0; } diff --git a/deps/uv/src/unix/os390-syscalls.c b/deps/uv/src/unix/os390-syscalls.c index 7edf2358d43a49..08623f4eafa137 100644 --- a/deps/uv/src/unix/os390-syscalls.c +++ b/deps/uv/src/unix/os390-syscalls.c @@ -183,33 +183,22 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, int pollret; int reventcount; - uv_mutex_lock(&global_epoll_lock); - uv_mutex_unlock(&global_epoll_lock); size = lst->size; pfds = lst->items; pollret = poll(pfds, size, timeout); - if(pollret == -1) + if (pollret <= 0) return pollret; reventcount = 0; - for (int i = 0; i < lst->size && i < maxevents; ++i) { + for (int i = 0; + i < lst->size && i < maxevents && reventcount < pollret; ++i) { struct epoll_event ev; - ev.events = 0; - ev.fd = pfds[i].fd; - if(!pfds[i].revents) + if (pfds[i].fd == -1 || pfds[i].revents == 0) continue; - if(pfds[i].revents & POLLRDNORM) - ev.events = ev.events | POLLIN; - - if(pfds[i].revents & POLLWRNORM) - ev.events = ev.events | POLLOUT; - - if(pfds[i].revents & POLLHUP) - ev.events = ev.events | POLLHUP; - - pfds[i].revents = 0; + ev.fd = pfds[i].fd; + ev.events = pfds[i].revents; events[reventcount++] = ev; } diff --git a/deps/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c index de7df91169ad8f..559970de2c3d59 100644 --- a/deps/uv/src/unix/os390.c +++ b/deps/uv/src/unix/os390.c @@ -33,6 +33,7 @@ #endif #define CVT_PTR 0x10 +#define PSA_PTR 0x00 #define CSD_OFFSET 0x294 /* @@ -70,6 +71,18 @@ /* CPC model length from the CSRSI Service. */ #define CPCMODEL_LENGTH 16 +/* Pointer to the home (current) ASCB. */ +#define PSAAOLD 0x224 + +/* Pointer to rsm address space block extension. */ +#define ASCBRSME 0x16C + +/* + NUMBER OF FRAMES CURRENTLY IN USE BY THIS ADDRESS SPACE. + It does not include 2G frames. +*/ +#define RAXFMCT 0x2C + /* Thread Entry constants */ #define PGTH_CURRENT 1 #define PGTH_LEN 26 @@ -77,6 +90,9 @@ #pragma linkage(BPX4GTH, OS) #pragma linkage(BPX1GTH, OS) +/* TOD Clock resolution in nanoseconds */ +#define TOD_RES 4.096 + typedef unsigned data_area_ptr_assign_type; typedef union { @@ -122,7 +138,7 @@ uint64_t uv__hrtime(uv_clocktype_t type) { unsigned long long timestamp; __stckf(×tamp); /* Convert to nanoseconds */ - return timestamp / 10; + return timestamp / TOD_RES; } @@ -339,13 +355,17 @@ uint64_t uv_get_total_memory(void) { int uv_resident_set_memory(size_t* rss) { - W_PSPROC buf; + char* psa; + char* ascb; + char* rax; + size_t nframes; - memset(&buf, 0, sizeof(buf)); - if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1) - return -EINVAL; + psa = PSA_PTR; + ascb = *(char* __ptr32 *)(psa + PSAAOLD); + rax = *(char* __ptr32 *)(ascb + ASCBRSME); + nframes = *(unsigned int*)(rax + RAXFMCT); - *rss = buf.ps_size; + *rss = nframes * sysconf(_SC_PAGESIZE); return 0; } @@ -747,9 +767,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { SAVE_ERRNO(uv__update_time(loop)); if (nfds == 0) { assert(timeout != -1); - timeout = real_timeout - timeout; - if (timeout > 0) + + if (timeout > 0) { + timeout = real_timeout - timeout; continue; + } return; } diff --git a/deps/uv/src/unix/poll.c b/deps/uv/src/unix/poll.c index 370994bd572ceb..816c7dc2eb9e0b 100644 --- a/deps/uv/src/unix/poll.c +++ b/deps/uv/src/unix/poll.c @@ -33,8 +33,19 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { handle = container_of(w, uv_poll_t, io_watcher); - if (events & POLLERR) { - uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP); + /* + * As documented in the kernel source fs/kernfs/file.c #780 + * poll will return POLLERR|POLLPRI in case of sysfs + * polling. This does not happen in case of out-of-band + * TCP messages. + * + * The above is the case on (at least) FreeBSD and Linux. + * + * So to properly determine a POLLPRI or a POLLERR we need + * to check for both. + */ + if ((events & POLLERR) && !(events & UV__POLLPRI)) { + uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); uv__handle_stop(handle); handle->poll_cb(handle, -EBADF, 0); return; @@ -43,6 +54,8 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { pevents = 0; if (events & POLLIN) pevents |= UV_READABLE; + if (events & UV__POLLPRI) + pevents |= UV_PRIORITIZED; if (events & POLLOUT) pevents |= UV_WRITABLE; if (events & UV__POLLRDHUP) @@ -86,8 +99,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, static void uv__poll_stop(uv_poll_t* handle) { uv__io_stop(handle->loop, &handle->io_watcher, - POLLIN | POLLOUT | UV__POLLRDHUP); + POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); uv__handle_stop(handle); + uv__platform_invalidate_fd(handle->loop, handle->io_watcher.fd); } @@ -101,7 +115,8 @@ int uv_poll_stop(uv_poll_t* handle) { int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { int events; - assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); + assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT | + UV_PRIORITIZED)) == 0); assert(!uv__is_closing(handle)); uv__poll_stop(handle); @@ -112,6 +127,8 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { events = 0; if (pevents & UV_READABLE) events |= POLLIN; + if (pevents & UV_PRIORITIZED) + events |= UV__POLLPRI; if (pevents & UV_WRITABLE) events |= POLLOUT; if (pevents & UV_DISCONNECT) diff --git a/deps/uv/src/unix/pthread-barrier.c b/deps/uv/src/unix/pthread-barrier.c deleted file mode 100644 index b6e604d46d825c..00000000000000 --- a/deps/uv/src/unix/pthread-barrier.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright (c) 2016, Kari Tristan Helgason - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -#include "uv-common.h" -#include "pthread-barrier.h" - -#include -#include - -/* TODO: support barrier_attr */ -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count) { - int rc; - _uv_barrier* b; - - if (barrier == NULL || count == 0) - return EINVAL; - - if (barrier_attr != NULL) - return ENOTSUP; - - b = uv__malloc(sizeof(*b)); - if (b == NULL) - return ENOMEM; - - b->in = 0; - b->out = 0; - b->threshold = count; - - if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0) - goto error2; - if ((rc = pthread_cond_init(&b->cond, NULL)) != 0) - goto error; - - barrier->b = b; - return 0; - -error: - pthread_mutex_destroy(&b->mutex); -error2: - uv__free(b); - return rc; -} - -int pthread_barrier_wait(pthread_barrier_t* barrier) { - int rc; - _uv_barrier* b; - - if (barrier == NULL || barrier->b == NULL) - return EINVAL; - - b = barrier->b; - /* Lock the mutex*/ - if ((rc = pthread_mutex_lock(&b->mutex)) != 0) - return rc; - - /* Increment the count. If this is the first thread to reach the threshold, - wake up waiters, unlock the mutex, then return - PTHREAD_BARRIER_SERIAL_THREAD. */ - if (++b->in == b->threshold) { - b->in = 0; - b->out = b->threshold - 1; - rc = pthread_cond_signal(&b->cond); - assert(rc == 0); - - pthread_mutex_unlock(&b->mutex); - return PTHREAD_BARRIER_SERIAL_THREAD; - } - /* Otherwise, wait for other threads until in is set to 0, - then return 0 to indicate this is not the first thread. */ - do { - if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0) - break; - } while (b->in != 0); - - /* mark thread exit */ - b->out--; - pthread_cond_signal(&b->cond); - pthread_mutex_unlock(&b->mutex); - return rc; -} - -int pthread_barrier_destroy(pthread_barrier_t* barrier) { - int rc; - _uv_barrier* b; - - if (barrier == NULL || barrier->b == NULL) - return EINVAL; - - b = barrier->b; - - if ((rc = pthread_mutex_lock(&b->mutex)) != 0) - return rc; - - if (b->in > 0 || b->out > 0) - rc = EBUSY; - - pthread_mutex_unlock(&b->mutex); - - if (rc) - return rc; - - pthread_cond_destroy(&b->cond); - pthread_mutex_destroy(&b->mutex); - uv__free(barrier->b); - barrier->b = NULL; - return 0; -} diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index a9b5e4c02a8e9a..f8846225910a80 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -41,6 +41,110 @@ #define NANOSEC ((uint64_t) 1e9) +#if defined(UV__PTHREAD_BARRIER_FALLBACK) +/* TODO: support barrier_attr */ +int pthread_barrier_init(pthread_barrier_t* barrier, + const void* barrier_attr, + unsigned count) { + int rc; + _uv_barrier* b; + + if (barrier == NULL || count == 0) + return EINVAL; + + if (barrier_attr != NULL) + return ENOTSUP; + + b = uv__malloc(sizeof(*b)); + if (b == NULL) + return ENOMEM; + + b->in = 0; + b->out = 0; + b->threshold = count; + + if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0) + goto error2; + if ((rc = pthread_cond_init(&b->cond, NULL)) != 0) + goto error; + + barrier->b = b; + return 0; + +error: + pthread_mutex_destroy(&b->mutex); +error2: + uv__free(b); + return rc; +} + +int pthread_barrier_wait(pthread_barrier_t* barrier) { + int rc; + _uv_barrier* b; + + if (barrier == NULL || barrier->b == NULL) + return EINVAL; + + b = barrier->b; + /* Lock the mutex*/ + if ((rc = pthread_mutex_lock(&b->mutex)) != 0) + return rc; + + /* Increment the count. If this is the first thread to reach the threshold, + wake up waiters, unlock the mutex, then return + PTHREAD_BARRIER_SERIAL_THREAD. */ + if (++b->in == b->threshold) { + b->in = 0; + b->out = b->threshold - 1; + rc = pthread_cond_signal(&b->cond); + assert(rc == 0); + + pthread_mutex_unlock(&b->mutex); + return PTHREAD_BARRIER_SERIAL_THREAD; + } + /* Otherwise, wait for other threads until in is set to 0, + then return 0 to indicate this is not the first thread. */ + do { + if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0) + break; + } while (b->in != 0); + + /* mark thread exit */ + b->out--; + pthread_cond_signal(&b->cond); + pthread_mutex_unlock(&b->mutex); + return rc; +} + +int pthread_barrier_destroy(pthread_barrier_t* barrier) { + int rc; + _uv_barrier* b; + + if (barrier == NULL || barrier->b == NULL) + return EINVAL; + + b = barrier->b; + + if ((rc = pthread_mutex_lock(&b->mutex)) != 0) + return rc; + + if (b->in > 0 || b->out > 0) + rc = EBUSY; + + pthread_mutex_unlock(&b->mutex); + + if (rc) + return rc; + + pthread_cond_destroy(&b->cond); + pthread_mutex_destroy(&b->mutex); + uv__free(barrier->b); + barrier->b = NULL; + return 0; +} +#endif + + int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { int err; pthread_attr_t* attr; @@ -283,16 +387,19 @@ int uv_sem_init(uv_sem_t* sem, unsigned int value) { uv_sem_t semid; struct sembuf buf; int err; + union { + int val; + struct semid_ds* buf; + unsigned short* array; + } arg; - buf.sem_num = 0; - buf.sem_op = value; - buf.sem_flg = 0; semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR); if (semid == -1) return -errno; - if (-1 == semop(semid, &buf, 1)) { + arg.val = value; + if (-1 == semctl(semid, 0, SETVAL, arg)) { err = errno; if (-1 == semctl(*sem, 0, IPC_RMID)) abort(); @@ -424,7 +531,7 @@ int uv_cond_init(uv_cond_t* cond) { if (err) return -err; -#if !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) +#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21) err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); if (err) goto error2; @@ -511,7 +618,8 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { timeout += uv__hrtime(UV_CLOCK_PRECISE); ts.tv_sec = timeout / NANOSEC; ts.tv_nsec = timeout % NANOSEC; -#if defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + /* * The bionic pthread implementation doesn't support CLOCK_MONOTONIC, * but has this alternative function instead. @@ -519,7 +627,7 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts); #else r = pthread_cond_timedwait(cond, mutex, &ts); -#endif /* __ANDROID__ */ +#endif /* __ANDROID_API__ */ #endif diff --git a/deps/uv/src/win/dl.c b/deps/uv/src/win/dl.c index 39e400ab2dbd19..d454014d8adf6e 100644 --- a/deps/uv/src/win/dl.c +++ b/deps/uv/src/win/dl.c @@ -22,7 +22,7 @@ #include "uv.h" #include "internal.h" -static int uv__dlerror(uv_lib_t* lib, int errorno); +static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno); int uv_dlopen(const char* filename, uv_lib_t* lib) { @@ -37,12 +37,12 @@ int uv_dlopen(const char* filename, uv_lib_t* lib) { -1, filename_w, ARRAY_SIZE(filename_w))) { - return uv__dlerror(lib, GetLastError()); + return uv__dlerror(lib, filename, GetLastError()); } lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (lib->handle == NULL) { - return uv__dlerror(lib, GetLastError()); + return uv__dlerror(lib, filename, GetLastError()); } return 0; @@ -65,7 +65,7 @@ void uv_dlclose(uv_lib_t* lib) { int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) { *ptr = (void*) GetProcAddress(lib->handle, name); - return uv__dlerror(lib, *ptr ? 0 : GetLastError()); + return uv__dlerror(lib, "", *ptr ? 0 : GetLastError()); } @@ -88,31 +88,46 @@ static void uv__format_fallback_error(uv_lib_t* lib, int errorno){ -static int uv__dlerror(uv_lib_t* lib, int errorno) { +static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) { + static const char not_win32_app_msg[] = "%1 is not a valid Win32 application"; + DWORD_PTR arg; DWORD res; if (lib->errmsg) { - LocalFree((void*)lib->errmsg); + LocalFree(lib->errmsg); lib->errmsg = NULL; } - if (errorno) { + if (errorno == 0) + return 0; + + res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + (LPSTR) &lib->errmsg, 0, NULL); + + if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - (LPSTR) &lib->errmsg, 0, NULL); - if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { - res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - 0, (LPSTR) &lib->errmsg, 0, NULL); - } - - if (!res) { - uv__format_fallback_error(lib, errorno); - } + 0, (LPSTR) &lib->errmsg, 0, NULL); + } + + /* Inexpert hack to get the filename into the error message. */ + if (res && strstr(lib->errmsg, not_win32_app_msg)) { + LocalFree(lib->errmsg); + lib->errmsg = NULL; + arg = (DWORD_PTR) filename; + res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_ARGUMENT_ARRAY | + FORMAT_MESSAGE_FROM_STRING, + not_win32_app_msg, + 0, 0, (LPSTR) &lib->errmsg, 0, (va_list*) &arg); } - return errorno ? -1 : 0; + if (!res) + uv__format_fallback_error(lib, errorno); + + return -1; } diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 8223d6f655d1df..c374a82ca01f75 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -43,11 +43,26 @@ #define UV_FS_CLEANEDUP 0x0010 -#define QUEUE_FS_TP_JOB(loop, req) \ - do { \ - uv__req_register(loop, req); \ - uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); \ - } while (0) +#define INIT(subtype) \ + do { \ + if (req == NULL) \ + return UV_EINVAL; \ + uv_fs_req_init(loop, req, subtype, cb); \ + } \ + while (0) + +#define POST \ + do { \ + if (cb != NULL) { \ + uv__req_register(loop, req); \ + uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \ + return 0; \ + } else { \ + uv__fs_work(&req->work_req); \ + return req->result; \ + } \ + } \ + while (0) #define SET_REQ_RESULT(req, result_value) \ do { \ @@ -113,6 +128,7 @@ const WCHAR LONG_PATH_PREFIX_LEN = 4; const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\"; const WCHAR UNC_PATH_PREFIX_LEN = 8; +static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; void uv_fs_init(void) { _fmode = _O_BINARY; @@ -220,6 +236,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, uv_fs_type fs_type, const uv_fs_cb cb) { + uv__once_init(); UV_REQ_INIT(req, UV_FS); req->loop = loop; req->flags = 0; @@ -1118,8 +1135,6 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf) { */ if (fs__readlink_handle(handle, NULL, &statbuf->st_size) == 0) { statbuf->st_mode |= S_IFLNK; - } else if (GetLastError() != ERROR_NOT_A_REPARSE_POINT) { - return -1; } } @@ -1333,6 +1348,22 @@ static void fs__ftruncate(uv_fs_t* req) { } +static void fs__copyfile(uv_fs_t* req) { + int flags; + int overwrite; + + flags = req->fs.info.file_flags; + overwrite = flags & UV_FS_COPYFILE_EXCL; + + if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + SET_REQ_RESULT(req, 0); +} + + static void fs__sendfile(uv_fs_t* req) { int fd_in = req->file.fd, fd_out = req->fs.info.fd_out; size_t length = req->fs.info.bufsml[0].len; @@ -1699,25 +1730,46 @@ static void fs__create_junction(uv_fs_t* req, const WCHAR* path, static void fs__symlink(uv_fs_t* req) { - WCHAR* pathw = req->file.pathw; - WCHAR* new_pathw = req->fs.info.new_pathw; - int flags = req->fs.info.file_flags; - int result; + WCHAR* pathw; + WCHAR* new_pathw; + int flags; + int err; + pathw = req->file.pathw; + new_pathw = req->fs.info.new_pathw; - if (flags & UV_FS_SYMLINK_JUNCTION) { + if (req->fs.info.file_flags & UV_FS_SYMLINK_JUNCTION) { fs__create_junction(req, pathw, new_pathw); - } else if (pCreateSymbolicLinkW) { - result = pCreateSymbolicLinkW(new_pathw, - pathw, - flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1; - if (result == -1) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } else { - SET_REQ_RESULT(req, result); - } - } else { + return; + } + if (!pCreateSymbolicLinkW) { SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); + return; + } + + if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR) + flags = SYMBOLIC_LINK_FLAG_DIRECTORY; + else + flags = uv__file_symlink_usermode_flag; + + if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) { + SET_REQ_RESULT(req, 0); + return; + } + + /* Something went wrong. We will test if it is because of user-mode + * symlinks. + */ + err = GetLastError(); + if (err == ERROR_INVALID_PARAMETER && + flags & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) { + /* This system does not support user-mode symlinks. We will clear the + * unsupported flag and retry. + */ + uv__file_symlink_usermode_flag = 0; + fs__symlink(req); + } else { + SET_REQ_WIN32_ERROR(req, err); } } @@ -1855,6 +1907,7 @@ static void uv__fs_work(struct uv__work* w) { XX(CLOSE, close) XX(READ, read) XX(WRITE, write) + XX(COPYFILE, copyfile) XX(SENDFILE, sendfile) XX(STAT, stat) XX(LSTAT, lstat) @@ -1901,6 +1954,9 @@ static void uv__fs_done(struct uv__work* w, int status) { void uv_fs_req_cleanup(uv_fs_t* req) { + if (req == NULL) + return; + if (req->flags & UV_FS_CLEANEDUP) return; @@ -1931,8 +1987,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_OPEN, cb); - + INIT(UV_FS_OPEN); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); @@ -1940,28 +1995,14 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, req->fs.info.file_flags = flags; req->fs.info.mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__open(req); - return req->result; - } + POST; } int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_CLOSE, cb); + INIT(UV_FS_CLOSE); req->file.fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__close(req); - return req->result; - } + POST; } @@ -1972,11 +2013,11 @@ int uv_fs_read(uv_loop_t* loop, unsigned int nbufs, int64_t offset, uv_fs_cb cb) { + INIT(UV_FS_READ); + if (bufs == NULL || nbufs == 0) return UV_EINVAL; - uv_fs_req_init(loop, req, UV_FS_READ, cb); - req->file.fd = fd; req->fs.info.nbufs = nbufs; @@ -1990,14 +2031,7 @@ int uv_fs_read(uv_loop_t* loop, memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs)); req->fs.info.offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__read(req); - return req->result; - } + POST; } @@ -2008,11 +2042,11 @@ int uv_fs_write(uv_loop_t* loop, unsigned int nbufs, int64_t offset, uv_fs_cb cb) { + INIT(UV_FS_WRITE); + if (bufs == NULL || nbufs == 0) return UV_EINVAL; - uv_fs_req_init(loop, req, UV_FS_WRITE, cb); - req->file.fd = fd; req->fs.info.nbufs = nbufs; @@ -2026,14 +2060,7 @@ int uv_fs_write(uv_loop_t* loop, memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs)); req->fs.info.offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__write(req); - return req->result; - } + POST; } @@ -2041,20 +2068,13 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_UNLINK, cb); - + INIT(UV_FS_UNLINK); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__unlink(req); - return req->result; - } + POST; } @@ -2062,22 +2082,14 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_MKDIR, cb); - + INIT(UV_FS_MKDIR); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } req->fs.info.mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__mkdir(req); - return req->result; - } + POST; } @@ -2085,39 +2097,25 @@ int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_MKDTEMP, cb); - + INIT(UV_FS_MKDTEMP); err = fs__capture_path(req, tpl, NULL, TRUE); if (err) return uv_translate_sys_error(err); - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__mkdtemp(req); - return req->result; - } + POST; } int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_RMDIR, cb); - + INIT(UV_FS_RMDIR); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__rmdir(req); - return req->result; - } + POST; } @@ -2125,22 +2123,14 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb); - + INIT(UV_FS_SCANDIR); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } req->fs.info.file_flags = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__scandir(req); - return req->result; - } + POST; } @@ -2148,20 +2138,13 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_LINK, cb); - + INIT(UV_FS_LINK); err = fs__capture_path(req, path, new_path, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__link(req); - return req->result; - } + POST; } @@ -2169,22 +2152,14 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_SYMLINK, cb); - + INIT(UV_FS_SYMLINK); err = fs__capture_path(req, path, new_path, cb != NULL); if (err) { return uv_translate_sys_error(err); } req->fs.info.file_flags = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__symlink(req); - return req->result; - } + POST; } @@ -2192,20 +2167,13 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_READLINK, cb); - + INIT(UV_FS_READLINK); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__readlink(req); - return req->result; - } + POST; } @@ -2213,24 +2181,18 @@ int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; - if (!req || !path) { + INIT(UV_FS_REALPATH); + + if (!path) { return UV_EINVAL; } - uv_fs_req_init(loop, req, UV_FS_REALPATH, cb); - err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__realpath(req); - return req->result; - } + POST; } @@ -2238,88 +2200,53 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_CHOWN, cb); - + INIT(UV_FS_CHOWN); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__chown(req); - return req->result; - } + POST; } int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FCHOWN, cb); - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fchown(req); - return req->result; - } + INIT(UV_FS_FCHOWN); + POST; } int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_STAT, cb); - + INIT(UV_FS_STAT); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__stat(req); - return req->result; - } + POST; } int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_LSTAT, cb); - + INIT(UV_FS_LSTAT); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__lstat(req); - return req->result; - } + POST; } int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FSTAT, cb); + INIT(UV_FS_FSTAT); req->file.fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fstat(req); - return req->result; - } + POST; } @@ -2327,85 +2254,70 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_RENAME, cb); - + INIT(UV_FS_RENAME); err = fs__capture_path(req, path, new_path, cb != NULL); if (err) { return uv_translate_sys_error(err); } - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__rename(req); - return req->result; - } + POST; } int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FSYNC, cb); + INIT(UV_FS_FSYNC); req->file.fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fsync(req); - return req->result; - } + POST; } int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FDATASYNC, cb); + INIT(UV_FS_FDATASYNC); req->file.fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fdatasync(req); - return req->result; - } + POST; } int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int64_t offset, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FTRUNCATE, cb); - + INIT(UV_FS_FTRUNCATE); req->file.fd = fd; req->fs.info.offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__ftruncate(req); - return req->result; - } + POST; } +int uv_fs_copyfile(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + const char* new_path, + int flags, + uv_fs_cb cb) { + int err; + + INIT(UV_FS_COPYFILE); + + if (flags & ~UV_FS_COPYFILE_EXCL) + return UV_EINVAL; + + err = fs__capture_path(req, path, new_path, cb != NULL); + + if (err) + return uv_translate_sys_error(err); + + req->fs.info.file_flags = flags; + POST; +} + int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out, uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_SENDFILE, cb); - + INIT(UV_FS_SENDFILE); req->file.fd = fd_in; req->fs.info.fd_out = fd_out; req->fs.info.offset = in_offset; req->fs.info.bufsml[0].len = length; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__sendfile(req); - return req->result; - } + POST; } @@ -2416,21 +2328,13 @@ int uv_fs_access(uv_loop_t* loop, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_ACCESS, cb); - + INIT(UV_FS_ACCESS); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) return uv_translate_sys_error(err); req->fs.info.mode = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } - - fs__access(req); - return req->result; + POST; } @@ -2438,39 +2342,23 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_CHMOD, cb); - + INIT(UV_FS_CHMOD); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } req->fs.info.mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__chmod(req); - return req->result; - } + POST; } int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FCHMOD, cb); - + INIT(UV_FS_FCHMOD); req->file.fd = fd; req->fs.info.mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fchmod(req); - return req->result; - } + POST; } @@ -2478,8 +2366,7 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_UTIME, cb); - + INIT(UV_FS_UTIME); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); @@ -2487,30 +2374,15 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, req->fs.time.atime = atime; req->fs.time.mtime = mtime; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__utime(req); - return req->result; - } + POST; } int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime, double mtime, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FUTIME, cb); - + INIT(UV_FS_FUTIME); req->file.fd = fd; req->fs.time.atime = atime; req->fs.time.mtime = mtime; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__futime(req); - return req->result; - } + POST; } diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 9b10cc9fe22bf6..5c666788fd67f5 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -1913,6 +1913,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { if (os_handle == INVALID_HANDLE_VALUE) return UV_EBADF; + uv__once_init(); /* In order to avoid closing a stdio file descriptor 0-2, duplicate the * underlying OS handle and forget about the original fd. * We could also opt to use the original OS handle and just never close it, @@ -1986,6 +1987,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) unsigned int name_len; int err; + uv__once_init(); name_info = NULL; if (handle->handle == INVALID_HANDLE_VALUE) { diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c index d141601607851b..97b67ca529582e 100644 --- a/deps/uv/src/win/process.c +++ b/deps/uv/src/win/process.c @@ -405,8 +405,15 @@ static WCHAR* search_path(const WCHAR *file, /* Next slice starts just after where the previous one ended */ dir_start = dir_end; + /* If path is quoted, find quote end */ + if (*dir_start == L'"' || *dir_start == L'\'') { + dir_end = wcschr(dir_start + 1, *dir_start); + if (dir_end == NULL) { + dir_end = wcschr(dir_start, L'\0'); + } + } /* Slice until the next ; or \0 is found */ - dir_end = wcschr(dir_start, L';'); + dir_end = wcschr(dir_end, L';'); if (dir_end == NULL) { dir_end = wcschr(dir_start, L'\0'); } diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index 972539f4df49d0..e63a63e7712af1 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -1446,6 +1446,8 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { WSAPROTOCOL_INFOW protocol_info; int opt_len; int err; + struct sockaddr_storage saddr; + int saddr_len; /* Detect the address family of the socket. */ opt_len = (int) sizeof protocol_info; @@ -1466,6 +1468,19 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { return uv_translate_sys_error(err); } + /* Support already active socket. */ + saddr_len = sizeof(saddr); + if (!uv_tcp_getsockname(handle, (struct sockaddr*) &saddr, &saddr_len)) { + /* Socket is already bound. */ + handle->flags |= UV_HANDLE_BOUND; + saddr_len = sizeof(saddr); + if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) { + /* Socket is already connected. */ + uv_connection_init((uv_stream_t*) handle); + handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; + } + } + return 0; } diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index a6f583956fe6b3..c4f99bdc7961b8 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -148,6 +148,7 @@ 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; + uv__once_init(); handle = (HANDLE) uv__get_osfhandle(fd); if (handle == INVALID_HANDLE_VALUE) return UV_EBADF; diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 9401676fbdc3ad..6c699bfe170c25 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4104,6 +4104,10 @@ # define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000 #endif +#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE +# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x00000002 +#endif + /* from winternl.h */ typedef struct _UNICODE_STRING { USHORT Length; diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c index 0f1b56e777c6cb..d86fda3c5d7b8c 100644 --- a/deps/uv/test/runner-win.c +++ b/deps/uv/test/runner-win.c @@ -300,7 +300,6 @@ int process_reap(process_info_t *p) { void process_cleanup(process_info_t *p) { CloseHandle(p->process); CloseHandle(p->stdio_in); - CloseHandle(p->stdio_out); } diff --git a/deps/uv/test/test-dlerror.c b/deps/uv/test/test-dlerror.c index 091200edbed591..8f7697b594129c 100644 --- a/deps/uv/test/test-dlerror.c +++ b/deps/uv/test/test-dlerror.c @@ -42,11 +42,13 @@ TEST_IMPL(dlerror) { msg = uv_dlerror(&lib); ASSERT(msg != NULL); + ASSERT(strstr(msg, path) != NULL); ASSERT(strstr(msg, dlerror_no_error) == NULL); /* Should return the same error twice in a row. */ msg = uv_dlerror(&lib); ASSERT(msg != NULL); + ASSERT(strstr(msg, path) != NULL); ASSERT(strstr(msg, dlerror_no_error) == NULL); uv_dlclose(&lib); diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c new file mode 100644 index 00000000000000..2d1f9079a5f915 --- /dev/null +++ b/deps/uv/test/test-fs-copyfile.c @@ -0,0 +1,150 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#if defined(__unix__) || defined(__POSIX__) || \ + defined(__APPLE__) || defined(_AIX) || defined(__MVS__) +#include /* unlink, etc. */ +#else +# include +# include +# define unlink _unlink +#endif + +static const char fixture[] = "test/fixtures/load_error.node"; +static const char dst[] = "test_file_dst"; +static int result_check_count; + + +static void handle_result(uv_fs_t* req) { + uv_fs_t stat_req; + uint64_t size; + uint64_t mode; + int r; + + ASSERT(req->fs_type == UV_FS_COPYFILE); + ASSERT(req->result == 0); + + /* Verify that the file size and mode are the same. */ + r = uv_fs_stat(NULL, &stat_req, req->path, NULL); + ASSERT(r == 0); + size = stat_req.statbuf.st_size; + mode = stat_req.statbuf.st_mode; + uv_fs_req_cleanup(&stat_req); + r = uv_fs_stat(NULL, &stat_req, dst, NULL); + ASSERT(r == 0); + ASSERT(stat_req.statbuf.st_size == size); + ASSERT(stat_req.statbuf.st_mode == mode); + uv_fs_req_cleanup(&stat_req); + uv_fs_req_cleanup(req); + result_check_count++; +} + + +static void touch_file(const char* name, unsigned int size) { + uv_file file; + uv_fs_t req; + uv_buf_t buf; + int r; + unsigned int i; + + r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); + uv_fs_req_cleanup(&req); + ASSERT(r >= 0); + file = r; + + buf = uv_buf_init("a", 1); + + /* Inefficient but simple. */ + for (i = 0; i < size; i++) { + r = uv_fs_write(NULL, &req, file, &buf, 1, i, NULL); + uv_fs_req_cleanup(&req); + ASSERT(r >= 0); + } + + r = uv_fs_close(NULL, &req, file, NULL); + uv_fs_req_cleanup(&req); + ASSERT(r == 0); +} + + +TEST_IMPL(fs_copyfile) { + const char src[] = "test_file_src"; + uv_loop_t* loop; + uv_fs_t req; + int r; + + loop = uv_default_loop(); + + /* Fails with EINVAL if bad flags are passed. */ + r = uv_fs_copyfile(NULL, &req, src, dst, -1, NULL); + ASSERT(r == UV_EINVAL); + uv_fs_req_cleanup(&req); + + /* Fails with ENOENT if source does not exist. */ + unlink(src); + unlink(dst); + r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL); + ASSERT(req.result == UV_ENOENT); + ASSERT(r == UV_ENOENT); + uv_fs_req_cleanup(&req); + /* The destination should not exist. */ + r = uv_fs_stat(NULL, &req, dst, NULL); + ASSERT(r != 0); + uv_fs_req_cleanup(&req); + + /* Copies file synchronously. Creates new file. */ + unlink(dst); + r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); + ASSERT(r == 0); + handle_result(&req); + + /* Copies file synchronously. Overwrites existing file. */ + r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); + ASSERT(r == 0); + handle_result(&req); + + /* Fails to overwrites existing file. */ + r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_EXCL, NULL); + ASSERT(r == UV_EEXIST); + uv_fs_req_cleanup(&req); + + /* Copies a larger file. */ + unlink(dst); + touch_file(src, 4096 * 2); + r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL); + ASSERT(r == 0); + handle_result(&req); + unlink(src); + + /* Copies file asynchronously */ + unlink(dst); + r = uv_fs_copyfile(loop, &req, fixture, dst, 0, handle_result); + ASSERT(r == 0); + ASSERT(result_check_count == 3); + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(result_check_count == 4); + unlink(dst); /* Cleanup */ + + return 0; +} diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 404d0426f38aed..0000e563a73ffc 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -1492,12 +1492,14 @@ TEST_IMPL(fs_chown) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(chown_cb_count == 1); +#ifndef __MVS__ /* chown to root (fail) */ chown_cb_count = 0; r = uv_fs_chown(loop, &req, "test_file", 0, 0, chown_root_cb); ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); ASSERT(chown_cb_count == 1); +#endif /* async fchown */ r = uv_fs_fchown(loop, &req, file, -1, -1, fchown_cb); @@ -2749,19 +2751,23 @@ TEST_IMPL(fs_write_alotof_bufs_with_offset) { TEST_IMPL(fs_read_write_null_arguments) { int r; - r = uv_fs_read(NULL, NULL, 0, NULL, 0, -1, NULL); + r = uv_fs_read(NULL, &read_req, 0, NULL, 0, -1, NULL); ASSERT(r == UV_EINVAL); + uv_fs_req_cleanup(&read_req); - r = uv_fs_write(NULL, NULL, 0, NULL, 0, -1, NULL); + r = uv_fs_write(NULL, &write_req, 0, NULL, 0, -1, NULL); ASSERT(r == UV_EINVAL); + uv_fs_req_cleanup(&write_req); iov = uv_buf_init(NULL, 0); - r = uv_fs_read(NULL, NULL, 0, &iov, 0, -1, NULL); + r = uv_fs_read(NULL, &read_req, 0, &iov, 0, -1, NULL); ASSERT(r == UV_EINVAL); + uv_fs_req_cleanup(&read_req); iov = uv_buf_init(NULL, 0); - r = uv_fs_write(NULL, NULL, 0, &iov, 0, -1, NULL); + r = uv_fs_write(NULL, &write_req, 0, &iov, 0, -1, NULL); ASSERT(r == UV_EINVAL); + uv_fs_req_cleanup(&write_req); return 0; } @@ -2844,3 +2850,100 @@ TEST_IMPL(fs_file_pos_after_op_with_offset) { MAKE_VALGRIND_HAPPY(); return 0; } + +TEST_IMPL(fs_null_req) { + /* Verify that all fs functions return UV_EINVAL when the request is NULL. */ + int r; + + r = uv_fs_open(NULL, NULL, NULL, 0, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_close(NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + 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); + + r = uv_fs_unlink(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_mkdir(NULL, NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_mkdtemp(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_rmdir(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_scandir(NULL, NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_link(NULL, NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_symlink(NULL, NULL, NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_readlink(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_realpath(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_chown(NULL, NULL, NULL, 0, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_fchown(NULL, NULL, 0, 0, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_stat(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_lstat(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_fstat(NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_rename(NULL, NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_fsync(NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_fdatasync(NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_ftruncate(NULL, NULL, 0, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_copyfile(NULL, NULL, NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_sendfile(NULL, NULL, 0, 0, 0, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_access(NULL, NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_chmod(NULL, NULL, NULL, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_fchmod(NULL, NULL, 0, 0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_utime(NULL, NULL, NULL, 0.0, 0.0, NULL); + ASSERT(r == UV_EINVAL); + + r = uv_fs_futime(NULL, NULL, 0, 0.0, 0.0, NULL); + ASSERT(r == UV_EINVAL); + + /* This should be a no-op. */ + uv_fs_req_cleanup(NULL); + + return 0; +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 0c32d84d2038ba..6e84653e8b4f83 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -81,6 +81,8 @@ TEST_DECLARE (tcp_try_write) TEST_DECLARE (tcp_write_queue_order) TEST_DECLARE (tcp_open) TEST_DECLARE (tcp_open_twice) +TEST_DECLARE (tcp_open_bound) +TEST_DECLARE (tcp_open_connected) TEST_DECLARE (tcp_connect_error_after_write) TEST_DECLARE (tcp_shutdown_after_write) TEST_DECLARE (tcp_bind_error_addrinuse) @@ -256,6 +258,7 @@ TEST_DECLARE (spawn_auto_unref) TEST_DECLARE (spawn_closed_process_io) TEST_DECLARE (spawn_reads_child_path) TEST_DECLARE (spawn_inherit_streams) +TEST_DECLARE (spawn_quoted_path) TEST_DECLARE (fs_poll) TEST_DECLARE (fs_poll_getpath) TEST_DECLARE (kill) @@ -271,6 +274,7 @@ TEST_DECLARE (fs_mkdtemp) TEST_DECLARE (fs_fstat) TEST_DECLARE (fs_access) TEST_DECLARE (fs_chmod) +TEST_DECLARE (fs_copyfile) TEST_DECLARE (fs_unlink_readonly) TEST_DECLARE (fs_chown) TEST_DECLARE (fs_link) @@ -312,6 +316,7 @@ TEST_DECLARE (get_osfhandle_valid_handle) TEST_DECLARE (fs_write_alotof_bufs) TEST_DECLARE (fs_write_alotof_bufs_with_offset) TEST_DECLARE (fs_file_pos_after_op_with_offset) +TEST_DECLARE (fs_null_req) TEST_DECLARE (threadpool_queue_work_simple) TEST_DECLARE (threadpool_queue_work_einval) TEST_DECLARE (threadpool_multiple_event_loops) @@ -328,6 +333,10 @@ TEST_DECLARE (thread_rwlock_trylock) TEST_DECLARE (thread_create) TEST_DECLARE (thread_equal) TEST_DECLARE (dlerror) +#if (defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))) && \ + !defined(__sun) +TEST_DECLARE (poll_oob) +#endif TEST_DECLARE (poll_duplex) TEST_DECLARE (poll_unidirectional) TEST_DECLARE (poll_close) @@ -486,6 +495,9 @@ TASK_LIST_START TEST_ENTRY (tcp_open) TEST_HELPER (tcp_open, tcp4_echo_server) TEST_ENTRY (tcp_open_twice) + TEST_ENTRY (tcp_open_bound) + TEST_ENTRY (tcp_open_connected) + TEST_HELPER (tcp_open_connected, tcp4_echo_server) TEST_ENTRY (tcp_shutdown_after_write) TEST_HELPER (tcp_shutdown_after_write, tcp4_echo_server) @@ -681,6 +693,11 @@ TASK_LIST_START TEST_ENTRY (poll_unidirectional) TEST_ENTRY (poll_close) TEST_ENTRY (poll_bad_fdtype) +#if (defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))) && \ + !defined(__sun) + TEST_ENTRY (poll_oob) +#endif + #ifdef __linux__ TEST_ENTRY (poll_nested_epoll) #endif @@ -714,6 +731,7 @@ TASK_LIST_START TEST_ENTRY (spawn_closed_process_io) TEST_ENTRY (spawn_reads_child_path) TEST_ENTRY (spawn_inherit_streams) + TEST_ENTRY (spawn_quoted_path) TEST_ENTRY (fs_poll) TEST_ENTRY (fs_poll_getpath) TEST_ENTRY (kill) @@ -762,6 +780,7 @@ TASK_LIST_START TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_access) TEST_ENTRY (fs_chmod) + TEST_ENTRY (fs_copyfile) TEST_ENTRY (fs_unlink_readonly) TEST_ENTRY (fs_chown) TEST_ENTRY (fs_utime) @@ -801,6 +820,7 @@ TASK_LIST_START TEST_ENTRY (fs_write_alotof_bufs_with_offset) TEST_ENTRY (fs_read_write_null_arguments) TEST_ENTRY (fs_file_pos_after_op_with_offset) + TEST_ENTRY (fs_null_req) TEST_ENTRY (get_osfhandle_valid_handle) TEST_ENTRY (threadpool_queue_work_simple) TEST_ENTRY (threadpool_queue_work_einval) diff --git a/deps/uv/test/test-poll-oob.c b/deps/uv/test/test-poll-oob.c new file mode 100644 index 00000000000000..2a6da843c616ad --- /dev/null +++ b/deps/uv/test/test-poll-oob.c @@ -0,0 +1,205 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#if !defined(_WIN32) + +#include "uv.h" +#include "task.h" + +#include +#include +#include +#include +#include + +static uv_tcp_t server_handle; +static uv_tcp_t client_handle; +static uv_tcp_t peer_handle; +static uv_poll_t poll_req[2]; +static uv_idle_t idle; +static uv_os_fd_t client_fd; +static uv_os_fd_t server_fd; +static int ticks; +static const int kMaxTicks = 10; +static int cli_pr_check = 0; +static int cli_rd_check = 0; +static int srv_rd_check = 0; + +static int got_eagain(void) { + return errno == EAGAIN + || errno == EINPROGRESS +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif + ; +} + +static void idle_cb(uv_idle_t* idle) { + uv_sleep(100); + if (++ticks < kMaxTicks) + return; + + uv_poll_stop(&poll_req[0]); + uv_poll_stop(&poll_req[1]); + uv_close((uv_handle_t*) &server_handle, NULL); + uv_close((uv_handle_t*) &client_handle, NULL); + uv_close((uv_handle_t*) &peer_handle, NULL); + uv_close((uv_handle_t*) idle, NULL); +} + +static void poll_cb(uv_poll_t* handle, int status, int events) { + char buffer[5]; + int n; + int fd; + + ASSERT(0 == uv_fileno((uv_handle_t*)handle, &fd)); + memset(buffer, 0, 5); + + if (events & UV_PRIORITIZED) { + do + n = recv(client_fd, &buffer, 5, MSG_OOB); + while (n == -1 && errno == EINTR); + ASSERT(n >= 0 || errno != EINVAL); + cli_pr_check = 1; + ASSERT(0 == uv_poll_stop(&poll_req[0])); + ASSERT(0 == uv_poll_start(&poll_req[0], + UV_READABLE | UV_WRITABLE, + poll_cb)); + } + if (events & UV_READABLE) { + if (fd == client_fd) { + do + n = recv(client_fd, &buffer, 5, 0); + while (n == -1 && errno == EINTR); + ASSERT(n >= 0 || errno != EINVAL); + if (cli_rd_check == 1) { + ASSERT(strncmp(buffer, "world", n) == 0); + ASSERT(5 == n); + cli_rd_check = 2; + } + if (cli_rd_check == 0) { + ASSERT(n == 4); + ASSERT(strncmp(buffer, "hello", n) == 0); + cli_rd_check = 1; + do { + do + n = recv(server_fd, &buffer, 5, 0); + while (n == -1 && errno == EINTR); + if (n > 0) { + ASSERT(n == 5); + ASSERT(strncmp(buffer, "world", n) == 0); + cli_rd_check = 2; + } + } while (n > 0); + + ASSERT(got_eagain()); + } + } + if (fd == server_fd) { + do + n = recv(server_fd, &buffer, 3, 0); + while (n == -1 && errno == EINTR); + ASSERT(n >= 0 || errno != EINVAL); + ASSERT(3 == n); + ASSERT(strncmp(buffer, "foo", n) == 0); + srv_rd_check = 1; + uv_poll_stop(&poll_req[1]); + } + } + if (events & UV_WRITABLE) { + do { + n = send(client_fd, "foo", 3, 0); + } while (n < 0 && errno == EINTR); + ASSERT(3 == n); + } +} + +static void connection_cb(uv_stream_t* handle, int status) { + int r; + + ASSERT(0 == status); + ASSERT(0 == uv_accept(handle, (uv_stream_t*) &peer_handle)); + ASSERT(0 == uv_fileno((uv_handle_t*) &peer_handle, &server_fd)); + ASSERT(0 == uv_poll_init_socket(uv_default_loop(), &poll_req[0], client_fd)); + ASSERT(0 == uv_poll_init_socket(uv_default_loop(), &poll_req[1], server_fd)); + ASSERT(0 == uv_poll_start(&poll_req[0], + UV_PRIORITIZED | UV_READABLE | UV_WRITABLE, + poll_cb)); + ASSERT(0 == uv_poll_start(&poll_req[1], + UV_READABLE, + poll_cb)); + do { + r = send(server_fd, "hello", 5, MSG_OOB); + } while (r < 0 && errno == EINTR); + ASSERT(5 == r); + + do { + r = send(server_fd, "world", 5, 0); + } while (r < 0 && errno == EINTR); + ASSERT(5 == r); + + ASSERT(0 == uv_idle_start(&idle, idle_cb)); +} + + +TEST_IMPL(poll_oob) { + struct sockaddr_in addr; + int r = 0; + uv_loop_t* loop; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + loop = uv_default_loop(); + + ASSERT(0 == uv_tcp_init(loop, &server_handle)); + ASSERT(0 == uv_tcp_init(loop, &client_handle)); + ASSERT(0 == uv_tcp_init(loop, &peer_handle)); + ASSERT(0 == uv_idle_init(loop, &idle)); + ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0)); + ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 1, connection_cb)); + + /* Ensure two separate packets */ + ASSERT(0 == uv_tcp_nodelay(&client_handle, 1)); + + client_fd = socket(PF_INET, SOCK_STREAM, 0); + ASSERT(client_fd >= 0); + do { + errno = 0; + r = connect(client_fd, (const struct sockaddr*)&addr, sizeof(addr)); + } while (r == -1 && errno == EINTR); + ASSERT(r == 0); + + ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + + ASSERT(ticks == kMaxTicks); + + /* Did client receive the POLLPRI message */ + ASSERT(cli_pr_check == 1); + /* Did client receive the POLLIN message */ + ASSERT(cli_rd_check == 2); + /* Could we write with POLLOUT and did the server receive our POLLOUT message + * through POLLIN. + */ + ASSERT(srv_rd_check == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index bb35e32b28a285..91d831e19b92fe 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -1,3 +1,4 @@ + /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -1350,10 +1351,14 @@ TEST_IMPL(spawn_setgid_fails) { init_process_options("spawn_helper1", fail_cb); options.flags |= UV_PROCESS_SETGID; +#if defined(__MVS__) + options.gid = -1; +#else options.gid = 0; +#endif r = uv_spawn(uv_default_loop(), &process, &options); -#if defined(__CYGWIN__) +#if defined(__CYGWIN__) || defined(__MVS__) ASSERT(r == UV_EINVAL); #else ASSERT(r == UV_EPERM); @@ -1711,6 +1716,31 @@ TEST_IMPL(spawn_inherit_streams) { return 0; } +TEST_IMPL(spawn_quoted_path) { +#ifndef _WIN32 + RETURN_SKIP("Test for Windows"); +#else + char* quoted_path_env[2]; + options.file = "not_existing"; + args[0] = options.file; + args[1] = NULL; + options.args = args; + options.exit_cb = exit_cb; + options.flags = 0; + /* We test if search_path works correctly with semicolons in quoted path. */ + /* We will use invalid drive, so we are sure no executable is spawned */ + quoted_path_env[0] = "PATH=\"xyz:\\test;\";xyz:\\other"; + quoted_path_env[1] = NULL; + options.env = quoted_path_env; + + /* We test if libuv will not segfault. */ + uv_spawn(uv_default_loop(), &process, &options); + + MAKE_VALGRIND_HAPPY(); + return 0; +#endif +} + /* Helper for child process of spawn_inherit_streams */ #ifndef _WIN32 int spawn_stdin_stdout(void) { diff --git a/deps/uv/test/test-tcp-oob.c b/deps/uv/test/test-tcp-oob.c index fc011ee495f1f6..4f1397a82ffed7 100644 --- a/deps/uv/test/test-tcp-oob.c +++ b/deps/uv/test/test-tcp-oob.c @@ -56,8 +56,21 @@ static void idle_cb(uv_idle_t* idle) { static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { +#ifdef __MVS__ + char lbuf[12]; +#endif + uv_os_fd_t fd; + ASSERT(nread > 0); + ASSERT(0 == uv_fileno((uv_handle_t*)handle, &fd)); ASSERT(0 == uv_idle_start(&idle, idle_cb)); + +#ifdef __MVS__ + /* Need to flush out the OOB data. Otherwise, this callback will get + * triggered on every poll with nread = 0. + */ + ASSERT(-1 != recv(fd, lbuf, sizeof(lbuf), MSG_OOB)); +#endif } diff --git a/deps/uv/test/test-tcp-open.c b/deps/uv/test/test-tcp-open.c index 6c8d43d0009e79..cb74c50e2c9929 100644 --- a/deps/uv/test/test-tcp-open.c +++ b/deps/uv/test/test-tcp-open.c @@ -218,3 +218,60 @@ TEST_IMPL(tcp_open_twice) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(tcp_open_bound) { + struct sockaddr_in addr; + uv_tcp_t server; + uv_os_sock_t sock; + + startup(); + sock = create_tcp_socket(); + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + ASSERT(0 == uv_tcp_init(uv_default_loop(), &server)); + + ASSERT(0 == bind(sock, (struct sockaddr*) &addr, sizeof(addr))); + + ASSERT(0 == uv_tcp_open(&server, sock)); + + ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, NULL)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(tcp_open_connected) { + struct sockaddr_in addr; + uv_tcp_t client; + uv_os_sock_t sock; + uv_buf_t buf = uv_buf_init("PING", 4); + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + startup(); + sock = create_tcp_socket(); + + ASSERT(0 == connect(sock, (struct sockaddr*) &addr, sizeof(addr))); + + ASSERT(0 == uv_tcp_init(uv_default_loop(), &client)); + + ASSERT(0 == uv_tcp_open(&client, sock)); + + ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &client, &buf, 1, write_cb)); + + ASSERT(0 == uv_shutdown(&shutdown_req, (uv_stream_t*) &client, shutdown_cb)); + + ASSERT(0 == uv_read_start((uv_stream_t*) &client, alloc_cb, read_cb)); + + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + ASSERT(shutdown_cb_called == 1); + ASSERT(write_cb_called == 1); + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 6f61d725a90b99..cac6da819b2196 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -217,8 +217,7 @@ 'sources': [ 'src/unix/darwin.c', 'src/unix/fsevents.c', - 'src/unix/darwin-proctitle.c', - 'src/unix/pthread-barrier.c' + 'src/unix/darwin-proctitle.c' ], 'defines': [ '_DARWIN_USE_64_BIT_INODE=1', @@ -253,7 +252,6 @@ 'src/unix/linux-syscalls.h', 'src/unix/pthread-fixes.c', 'src/unix/android-ifaddrs.c', - 'src/unix/pthread-barrier.c', 'src/unix/procfs-exepath.c', 'src/unix/sysinfo-loadavg.c', 'src/unix/sysinfo-memory.c', @@ -322,7 +320,6 @@ ['OS=="os390"', { 'sources': [ 'src/unix/pthread-fixes.c', - 'src/unix/pthread-barrier.c', 'src/unix/no-fsevents.c', 'src/unix/os390.c', 'src/unix/os390-syscalls.c' @@ -362,6 +359,7 @@ 'test/test-fail-always.c', 'test/test-fork.c', 'test/test-fs.c', + 'test/test-fs-copyfile.c', 'test/test-fs-event.c', 'test/test-get-currentexe.c', 'test/test-get-memory.c', @@ -405,6 +403,7 @@ 'test/test-poll-close.c', 'test/test-poll-close-doesnt-corrupt-stack.c', 'test/test-poll-closesocket.c', + 'test/test-poll-oob.c', 'test/test-process-title.c', 'test/test-queue-foreach-delete.c', 'test/test-ref.c', diff --git a/deps/uv/vcbuild.bat b/deps/uv/vcbuild.bat index e33573d108e16f..698044df490c02 100644 --- a/deps/uv/vcbuild.bat +++ b/deps/uv/vcbuild.bat @@ -43,6 +43,9 @@ shift goto next-arg :args-done +if defined WindowsSDKDir goto select-target +if defined VCINSTALLDIR goto select-target + @rem Look for Visual Studio 2017 only if explicitly requested. if "%target_env%" NEQ "vs2017" goto vs-set-2015 echo Looking for Visual Studio 2017 @@ -168,9 +171,7 @@ echo Failed to create vc project files. exit /b 1 :help - -echo "vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild] [vs2017] [x86/x64] [static/shared]" - +echo vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild] [vs2017] [x86/x64] [static/shared] echo Examples: echo vcbuild.bat : builds debug build echo vcbuild.bat test : builds debug build and runs tests