summaryrefslogtreecommitdiff
path: root/deps/uv
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2018-09-21 10:14:00 -0400
committerDaniel Bevenius <daniel.bevenius@gmail.com>2018-09-24 07:14:45 +0200
commit2790db5e3d74c4f7521cc27a1115228700dd4049 (patch)
tree14690a4e418d74d387491dc7afcbcde02c62e99b /deps/uv
parentea8000f1195801cf602946c6bd85b8b5dbe83d43 (diff)
downloadandroid-node-v8-2790db5e3d74c4f7521cc27a1115228700dd4049.tar.gz
android-node-v8-2790db5e3d74c4f7521cc27a1115228700dd4049.tar.bz2
android-node-v8-2790db5e3d74c4f7521cc27a1115228700dd4049.zip
deps: upgrade to libuv 1.23.1
PR-URL: https://github.com/nodejs/node/pull/22997 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Diffstat (limited to 'deps/uv')
-rw-r--r--deps/uv/AUTHORS5
-rw-r--r--deps/uv/ChangeLog46
-rw-r--r--deps/uv/MAINTAINERS.md1
-rw-r--r--deps/uv/README.md79
-rwxr-xr-xdeps/uv/android-configure-arm (renamed from deps/uv/android-configure)2
-rwxr-xr-xdeps/uv/android-configure-arm6423
-rwxr-xr-xdeps/uv/android-configure-x8623
-rwxr-xr-xdeps/uv/android-configure-x86_6425
-rw-r--r--deps/uv/configure.ac2
-rw-r--r--deps/uv/docs/src/misc.rst4
-rw-r--r--deps/uv/docs/src/signal.rst10
-rw-r--r--deps/uv/docs/src/stream.rst2
-rw-r--r--deps/uv/docs/src/tcp.rst4
-rw-r--r--deps/uv/docs/src/tty.rst11
-rw-r--r--deps/uv/include/uv/version.h2
-rw-r--r--deps/uv/src/threadpool.c86
-rw-r--r--deps/uv/src/unix/fs.c106
-rw-r--r--deps/uv/src/unix/getaddrinfo.c1
-rw-r--r--deps/uv/src/unix/getnameinfo.c1
-rw-r--r--deps/uv/src/unix/ibmi.c3
-rw-r--r--deps/uv/src/unix/linux-core.c92
-rw-r--r--deps/uv/src/unix/linux-syscalls.c133
-rw-r--r--deps/uv/src/unix/linux-syscalls.h34
-rw-r--r--deps/uv/src/unix/os390-syscalls.h4
-rw-r--r--deps/uv/src/unix/os390.c12
-rw-r--r--deps/uv/src/unix/pipe.c20
-rw-r--r--deps/uv/src/unix/stream.c1
-rw-r--r--deps/uv/src/unix/tty.c37
-rw-r--r--deps/uv/src/uv-common.h7
-rw-r--r--deps/uv/src/win/core.c57
-rw-r--r--deps/uv/src/win/fs.c6
-rw-r--r--deps/uv/src/win/getaddrinfo.c1
-rw-r--r--deps/uv/src/win/getnameinfo.c1
-rw-r--r--deps/uv/src/win/tty.c12
-rw-r--r--deps/uv/src/win/udp.c4
-rw-r--r--deps/uv/src/win/winapi.c13
-rw-r--r--deps/uv/src/win/winapi.h11
-rw-r--r--deps/uv/test/test-condvar.c2
-rw-r--r--deps/uv/test/test-fork.c6
-rw-r--r--deps/uv/test/test-handle-fileno.c6
-rw-r--r--deps/uv/test/test-pipe-close-stdout-read-stdin.c3
-rw-r--r--deps/uv/test/test-spawn.c10
-rw-r--r--deps/uv/test/test-tty.c45
43 files changed, 587 insertions, 366 deletions
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index 0ba7c06768..6504800766 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -346,3 +346,8 @@ Paolo Greppi <paolo.greppi@libpf.com>
Shelley Vohr <shelley.vohr@gmail.com>
Ujjwal Sharma <usharma1998@gmail.com>
MichaƂ Kozakiewicz <michalkozakiewicz3@gmail.com>
+Emil Bay <github@tixz.dk>
+Jeremiah Senkpiel <fishrock123@rocketmail.com>
+Andy Zhang <zhangyong232@gmail.com>
+dmabupt <dmabupt@gmail.com>
+Ryan Liptak <squeek502@hotmail.com>
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index b57cea4baf..d01b06f08a 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,3 +1,49 @@
+2018.09.22, Version 1.23.1 (Stable), d2282b3d67821dc53c907c2155fa8c5c6ce25180
+
+Changes since version 1.23.0:
+
+* unix,win: limit concurrent DNS calls to nthreads/2 (Anna Henningsen)
+
+* doc: add addaleax to maintainers (Anna Henningsen)
+
+* doc: add missing slash in stream.rst (Emil Bay)
+
+* unix,fs: use utimes & friends for uv_fs_utime (Jeremiah Senkpiel)
+
+* unix,fs: remove linux fallback from utimesat() (Jeremiah Senkpiel)
+
+* unix,fs: remove uv__utimesat() syscall fallback (Jeremiah Senkpiel)
+
+* doc: fix argument name in tcp.rts (Emil Bay)
+
+* doc: notes on running tests, benchmarks, tools (Jamie Davis)
+
+* linux: remove epoll syscall wrappers (Ben Noordhuis)
+
+* linux: drop code path for epoll_pwait-less kernels (Ben Noordhuis)
+
+* Partially revert "win,code: remove GetQueuedCompletionStatus-based poller"
+ (Jameson Nash)
+
+* build: add compile for android arm64/x86/x86-64 (Andy Zhang)
+
+* doc: clarify that some remarks apply to windows (Bert Belder)
+
+* test: fix compiler warnings (Jamie Davis)
+
+* ibmi: return 0 from uv_resident_set_memory() (dmabupt)
+
+* win: fix uv_udp_recv_start() error translation (Ryan Liptak)
+
+* win,doc: improve uv_os_setpriority() documentation (Bartosz Sosnowski)
+
+* test: increase upper bound in condvar_5 (Jamie Davis)
+
+* win,tty: remove deadcode (Jameson Nash)
+
+* stream: autodetect direction (Jameson Nash)
+
+
2018.08.18, Version 1.23.0 (Stable), 7ebb26225f2eaae6db22f4ef34ce76fa16ff89ec
Changes since version 1.22.0:
diff --git a/deps/uv/MAINTAINERS.md b/deps/uv/MAINTAINERS.md
index 889ee4988c..543dc3cda7 100644
--- a/deps/uv/MAINTAINERS.md
+++ b/deps/uv/MAINTAINERS.md
@@ -3,6 +3,7 @@
libuv is currently managed by the following individuals:
+* **Anna Henningsen** ([@addaleax](https://github.com/addaleax))
* **Bartosz Sosnowski** ([@bzoz](https://github.com/bzoz))
* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis))
- GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis)
diff --git a/deps/uv/README.md b/deps/uv/README.md
index cb9e26c1e0..b24b722612 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -282,8 +282,31 @@ Make sure that you specify the architecture you wish to build for in the
Run:
+For arm
+
+```bash
+$ source ./android-configure-arm NDK_PATH gyp [API_LEVEL]
+$ make -C out
+```
+
+or for arm64
+
+```bash
+$ source ./android-configure-arm64 NDK_PATH gyp [API_LEVEL]
+$ make -C out
+```
+
+or for x86
+
+```bash
+$ source ./android-configure-x86 NDK_PATH gyp [API_LEVEL]
+$ make -C out
+```
+
+or for x86_64
+
```bash
-$ source ./android-configure NDK_PATH gyp [API_LEVEL]
+$ source ./android-configure-x86_64 NDK_PATH gyp [API_LEVEL]
$ make -C out
```
@@ -310,14 +333,66 @@ $ ninja -C out/Release
### Running tests
-Run:
+#### Build
+
+Build (includes tests):
```bash
$ ./gyp_uv.py -f make
$ make -C out
+```
+
+#### Run all tests
+
+```bash
$ ./out/Debug/run-tests
```
+#### Run one test
+
+The list of all tests is in `test/test-list.h`.
+
+This invocation will cause the `run-tests` driver to fork and execute `TEST_NAME` in a child process:
+
+```bash
+$ ./out/Debug/run-tests TEST_NAME
+```
+
+This invocation will cause the `run-tests` driver to execute the test within the `run-tests` process:
+
+```bash
+$ ./out/Debug/run-tests TEST_NAME TEST_NAME
+```
+
+#### Debugging tools
+
+When running the test from within the `run-tests` process (`run-tests TEST_NAME TEST_NAME`), tools like gdb and valgrind work normally.
+When running the test from a child of the `run-tests` process (`run-tests TEST_NAME`), use these tools in a fork-aware manner.
+
+##### Fork-aware gdb
+
+Use the [follow-fork-mode](https://sourceware.org/gdb/onlinedocs/gdb/Forks.html) setting:
+
+```
+$ gdb --args out/Debug/run-tests TEST_NAME
+
+(gdb) set follow-fork-mode child
+...
+```
+
+##### Fork-aware valgrind
+
+Use the `--trace-children=yes` parameter:
+
+```bash
+$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck.log out/Debug/run-tests TEST_NAME
+```
+
+### Running benchmarks
+
+See the section on running tests.
+The benchmark driver is `out/Debug/run-benchmarks` and the benchmarks are listed in `test/benchmark-list.h`.
+
## Supported Platforms
Check the [SUPPORTED_PLATFORMS file](SUPPORTED_PLATFORMS.md).
diff --git a/deps/uv/android-configure b/deps/uv/android-configure-arm
index b5c11cd40c..331fdd9ebc 100755
--- a/deps/uv/android-configure
+++ b/deps/uv/android-configure-arm
@@ -1,6 +1,6 @@
#!/bin/bash
-export TOOLCHAIN=$PWD/android-toolchain
+export TOOLCHAIN=$PWD/android-toolchain-arm
mkdir -p $TOOLCHAIN
API=${3:-24}
$1/build/tools/make-standalone-toolchain.sh \
diff --git a/deps/uv/android-configure-arm64 b/deps/uv/android-configure-arm64
new file mode 100755
index 0000000000..1acd905d77
--- /dev/null
+++ b/deps/uv/android-configure-arm64
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+export TOOLCHAIN=$PWD/android-toolchain-arm64
+mkdir -p $TOOLCHAIN
+API=${3:-24}
+$1/build/tools/make-standalone-toolchain.sh \
+ --toolchain=aarch64-linux-android-4.9 \
+ --arch=arm64 \
+ --install-dir=$TOOLCHAIN \
+ --platform=android-$API \
+ --force
+export PATH=$TOOLCHAIN/bin:$PATH
+export AR=aarch64-linux-android-ar
+export CC=aarch64-linux-android-gcc
+export CXX=aarch64-linux-android-g++
+export LINK=aarch64-linux-android-g++
+export PLATFORM=android
+export CFLAGS="-D__ANDROID_API__=$API"
+
+if [[ $2 == 'gyp' ]]
+ then
+ ./gyp_uv.py -Dtarget_arch=arm64 -DOS=android -f make-android
+fi
diff --git a/deps/uv/android-configure-x86 b/deps/uv/android-configure-x86
new file mode 100755
index 0000000000..a149715f37
--- /dev/null
+++ b/deps/uv/android-configure-x86
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+export TOOLCHAIN=$PWD/android-toolchain-x86
+mkdir -p $TOOLCHAIN
+API=${3:-24}
+$1/build/tools/make-standalone-toolchain.sh \
+ --toolchain=x86-4.9 \
+ --arch=x86 \
+ --install-dir=$TOOLCHAIN \
+ --platform=android-$API \
+ --force
+export PATH=$TOOLCHAIN/bin:$PATH
+export AR=i686-linux-android-ar
+export CC=i686-linux-android-gcc
+export CXX=i686-linux-android-g++
+export LINK=i686-linux-android-g++
+export PLATFORM=android
+export CFLAGS="-D__ANDROID_API__=$API"
+
+if [[ $2 == 'gyp' ]]
+ then
+ ./gyp_uv.py -Dtarget_arch=x86 -DOS=android -f make-android
+fi
diff --git a/deps/uv/android-configure-x86_64 b/deps/uv/android-configure-x86_64
new file mode 100755
index 0000000000..ff045957f7
--- /dev/null
+++ b/deps/uv/android-configure-x86_64
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+export TOOLCHAIN=$PWD/android-toolchain-x86_64
+mkdir -p $TOOLCHAIN
+API=${3:-24}
+$1/build/tools/make-standalone-toolchain.sh \
+ --toolchain=x86_64-4.9 \
+ --arch=x86_64 \
+ --install-dir=$TOOLCHAIN \
+ --platform=android-$API \
+ --force
+export PATH=$TOOLCHAIN/bin:$PATH
+export AR=x86_64-linux-android-ar
+export CC=x86_64-linux-android-gcc
+export CXX=x86_64-linux-android-g++
+export LINK=x86_64-linux-android-g++
+export PLATFORM=android
+export CFLAGS="-D__ANDROID_API__=$API -fPIC"
+export CXXFLAGS="-D__ANDROID_API__=$API -fPIC"
+export LDFLAGS="-fPIC"
+
+if [[ $2 == 'gyp' ]]
+ then
+ ./gyp_uv.py -Dtarget_arch=x86_64 -DOS=android -f make-android
+fi
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index 6e084fd04d..ce307b1d70 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.23.0], [https://github.com/libuv/libuv/issues])
+AC_INIT([libuv], [1.23.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/misc.rst b/deps/uv/docs/src/misc.rst
index 529d588c5d..cf4a7895cd 100644
--- a/deps/uv/docs/src/misc.rst
+++ b/deps/uv/docs/src/misc.rst
@@ -544,4 +544,8 @@ API
process priority, the result will equal one of the `UV_PRIORITY`
constants, and not necessarily the exact value of `priority`.
+ .. note::
+ On Windows, setting `PRIORITY_HIGHEST` will only work for elevated user,
+ for others it will be silently reduced to `PRIORITY_HIGH`.
+
.. versionadded:: 1.23.0
diff --git a/deps/uv/docs/src/signal.rst b/deps/uv/docs/src/signal.rst
index 24354e4f7c..f52b64706a 100644
--- a/deps/uv/docs/src/signal.rst
+++ b/deps/uv/docs/src/signal.rst
@@ -17,12 +17,12 @@ Reception of some signals is emulated on Windows:
program is given approximately 10 seconds to perform cleanup. After that
Windows will unconditionally terminate it.
-Watchers for other signals can be successfully created, but these signals
-are never received. These signals are: `SIGILL`, `SIGABRT`, `SIGFPE`, `SIGSEGV`,
-`SIGTERM` and `SIGKILL.`
+* Watchers for other signals can be successfully created, but these signals
+ are never received. These signals are: `SIGILL`, `SIGABRT`, `SIGFPE`, `SIGSEGV`,
+ `SIGTERM` and `SIGKILL.`
-Calls to raise() or abort() to programmatically raise a signal are
-not detected by libuv; these will not trigger a signal watcher.
+* Calls to raise() or abort() to programmatically raise a signal are
+ not detected by libuv; these will not trigger a signal watcher.
.. note::
On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads library to
diff --git a/deps/uv/docs/src/stream.rst b/deps/uv/docs/src/stream.rst
index 9ec2362251..6a704367b1 100644
--- a/deps/uv/docs/src/stream.rst
+++ b/deps/uv/docs/src/stream.rst
@@ -45,7 +45,7 @@ Data types
`nread` might be 0, which does *not* indicate an error or EOF. This
is equivalent to ``EAGAIN`` or ``EWOULDBLOCK`` under ``read(2)``.
- The callee is responsible for stopping closing the stream when an error happens
+ The callee is responsible for stopping/closing the stream when an error happens
by calling :c:func:`uv_read_stop` or :c:func:`uv_close`. Trying to read
from the stream again is undefined.
diff --git a/deps/uv/docs/src/tcp.rst b/deps/uv/docs/src/tcp.rst
index e761b460d0..d20a6362af 100644
--- a/deps/uv/docs/src/tcp.rst
+++ b/deps/uv/docs/src/tcp.rst
@@ -86,13 +86,13 @@ API
.. c:function:: int uv_tcp_getsockname(const uv_tcp_t* handle, struct sockaddr* name, int* namelen)
- Get the current address to which the handle is bound. `addr` must point to
+ Get the current address to which the handle is bound. `name` must point to
a valid and big enough chunk of memory, ``struct sockaddr_storage`` is
recommended for IPv4 and IPv6 support.
.. c:function:: int uv_tcp_getpeername(const uv_tcp_t* handle, struct sockaddr* name, int* namelen)
- Get the address of the peer connected to the handle. `addr` must point to
+ Get the address of the peer connected to the handle. `name` must point to
a valid and big enough chunk of memory, ``struct sockaddr_storage`` is
recommended for IPv4 and IPv6 support.
diff --git a/deps/uv/docs/src/tty.rst b/deps/uv/docs/src/tty.rst
index 01a0585287..9889a0a0b6 100644
--- a/deps/uv/docs/src/tty.rst
+++ b/deps/uv/docs/src/tty.rst
@@ -46,7 +46,7 @@ N/A
API
---
-.. c:function:: int uv_tty_init(uv_loop_t* loop, uv_tty_t* handle, uv_file fd, int readable)
+.. c:function:: int uv_tty_init(uv_loop_t* loop, uv_tty_t* handle, uv_file fd, int unused)
Initialize a new TTY stream with the given file descriptor. Usually the
file descriptor will be:
@@ -55,9 +55,6 @@ API
* 1 = stdout
* 2 = stderr
- `readable`, specifies if you plan on calling :c:func:`uv_read_start` with
- this stream. stdin is readable, stdout is not.
-
On Unix this function will determine the path of the fd of the terminal
using :man:`ttyname_r(3)`, open it, and use it if the passed file descriptor
refers to a TTY. This lets libuv put the tty in non-blocking mode without
@@ -67,8 +64,10 @@ API
ioctl TIOCGPTN or TIOCPTYGNAME, for instance OpenBSD and Solaris.
.. note::
- If reopening the TTY fails, libuv falls back to blocking writes for
- non-readable TTY streams.
+ If reopening the TTY fails, libuv falls back to blocking writes.
+
+ .. versionchanged:: 1.23.1: the `readable` parameter is now unused and ignored.
+ The correct value will now be auto-detected from the kernel.
.. versionchanged:: 1.9.0: the path of the TTY is determined by
:man:`ttyname_r(3)`. In earlier versions libuv opened
diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h
index 30e1d5a6f9..9db3d130cd 100644
--- a/deps/uv/include/uv/version.h
+++ b/deps/uv/include/uv/version.h
@@ -32,7 +32,7 @@
#define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 23
-#define UV_VERSION_PATCH 0
+#define UV_VERSION_PATCH 1
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
diff --git a/deps/uv/src/threadpool.c b/deps/uv/src/threadpool.c
index 413d1c204c..4875f27beb 100644
--- a/deps/uv/src/threadpool.c
+++ b/deps/uv/src/threadpool.c
@@ -33,12 +33,18 @@ static uv_once_t once = UV_ONCE_INIT;
static uv_cond_t cond;
static uv_mutex_t mutex;
static unsigned int idle_threads;
+static unsigned int slow_io_work_running;
static unsigned int nthreads;
static uv_thread_t* threads;
static uv_thread_t default_threads[4];
static QUEUE exit_message;
static QUEUE wq;
+static QUEUE run_slow_work_message;
+static QUEUE slow_io_pending_wq;
+static unsigned int slow_work_thread_threshold(void) {
+ return (nthreads + 1) / 2;
+}
static void uv__cancelled(struct uv__work* w) {
abort();
@@ -51,6 +57,7 @@ static void uv__cancelled(struct uv__work* w) {
static void worker(void* arg) {
struct uv__work* w;
QUEUE* q;
+ int is_slow_work;
uv_sem_post((uv_sem_t*) arg);
arg = NULL;
@@ -58,31 +65,65 @@ static void worker(void* arg) {
for (;;) {
uv_mutex_lock(&mutex);
- while (QUEUE_EMPTY(&wq)) {
+ wait_for_work:
+ /* Keep waiting while either no work is present or only slow I/O
+ and we're at the threshold for that. */
+ while (QUEUE_EMPTY(&wq) ||
+ (QUEUE_HEAD(&wq) == &run_slow_work_message &&
+ QUEUE_NEXT(&run_slow_work_message) == &wq &&
+ slow_io_work_running >= slow_work_thread_threshold())) {
idle_threads += 1;
uv_cond_wait(&cond, &mutex);
idle_threads -= 1;
}
q = QUEUE_HEAD(&wq);
-
- if (q == &exit_message)
+ if (q == &exit_message) {
uv_cond_signal(&cond);
- else {
+ uv_mutex_unlock(&mutex);
+ break;
+ }
+
+ QUEUE_REMOVE(q);
+ QUEUE_INIT(q); /* Signal uv_cancel() that the work req is executing. */
+
+ is_slow_work = 0;
+ if (q == &run_slow_work_message) {
+ /* If we're at the slow I/O threshold, re-schedule until after all
+ other work in the queue is done. */
+ if (slow_io_work_running >= slow_work_thread_threshold()) {
+ QUEUE_INSERT_TAIL(&wq, q);
+ goto wait_for_work;
+ }
+
+ /* If we encountered a request to run slow I/O work but there is none
+ to run, that means it's cancelled => Start over. */
+ if (QUEUE_EMPTY(&slow_io_pending_wq))
+ goto wait_for_work;
+
+ is_slow_work = 1;
+ slow_io_work_running++;
+
+ q = QUEUE_HEAD(&slow_io_pending_wq);
QUEUE_REMOVE(q);
- QUEUE_INIT(q); /* Signal uv_cancel() that the work req is
- executing. */
+ QUEUE_INIT(q);
+
+ /* If there is more slow I/O work, schedule it to be run as well. */
+ if (!QUEUE_EMPTY(&slow_io_pending_wq)) {
+ QUEUE_INSERT_TAIL(&wq, &run_slow_work_message);
+ if (idle_threads > 0)
+ uv_cond_signal(&cond);
+ }
}
uv_mutex_unlock(&mutex);
- if (q == &exit_message)
- break;
-
w = QUEUE_DATA(q, struct uv__work, wq);
w->work(w);
uv_mutex_lock(&w->loop->wq_mutex);
+ if (is_slow_work)
+ slow_io_work_running--;
w->work = NULL; /* Signal uv_cancel() that the work req is done
executing. */
QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);
@@ -92,8 +133,20 @@ static void worker(void* arg) {
}
-static void post(QUEUE* q) {
+static void post(QUEUE* q, enum uv__work_kind kind) {
uv_mutex_lock(&mutex);
+ if (kind == UV__WORK_SLOW_IO) {
+ /* Insert into a separate queue. */
+ QUEUE_INSERT_TAIL(&slow_io_pending_wq, q);
+ if (!QUEUE_EMPTY(&run_slow_work_message)) {
+ /* Running slow I/O tasks is already scheduled => Nothing to do here.
+ The worker that runs said other task will schedule this one as well. */
+ uv_mutex_unlock(&mutex);
+ return;
+ }
+ q = &run_slow_work_message;
+ }
+
QUEUE_INSERT_TAIL(&wq, q);
if (idle_threads > 0)
uv_cond_signal(&cond);
@@ -108,7 +161,7 @@ UV_DESTRUCTOR(static void cleanup(void)) {
if (nthreads == 0)
return;
- post(&exit_message);
+ post(&exit_message, UV__WORK_CPU);
for (i = 0; i < nthreads; i++)
if (uv_thread_join(threads + i))
@@ -156,6 +209,8 @@ static void init_threads(void) {
abort();
QUEUE_INIT(&wq);
+ QUEUE_INIT(&slow_io_pending_wq);
+ QUEUE_INIT(&run_slow_work_message);
if (uv_sem_init(&sem, 0))
abort();
@@ -194,13 +249,14 @@ static void init_once(void) {
void uv__work_submit(uv_loop_t* loop,
struct uv__work* w,
+ enum uv__work_kind kind,
void (*work)(struct uv__work* w),
void (*done)(struct uv__work* w, int status)) {
uv_once(&once, init_once);
w->loop = loop;
w->work = work;
w->done = done;
- post(&w->wq);
+ post(&w->wq, kind);
}
@@ -284,7 +340,11 @@ int uv_queue_work(uv_loop_t* loop,
req->loop = loop;
req->work_cb = work_cb;
req->after_work_cb = after_work_cb;
- uv__work_submit(loop, &req->work_req, uv__queue_work, uv__queue_done);
+ uv__work_submit(loop,
+ &req->work_req,
+ UV__WORK_CPU,
+ uv__queue_work,
+ uv__queue_done);
return 0;
}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 652cdfd734..c3f7951f11 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -43,7 +43,6 @@
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
-#include <utime.h>
#include <poll.h>
#if defined(__DragonFly__) || \
@@ -67,6 +66,10 @@
# define FICLONE _IOW(0x94, 9, int)
#endif
+#if defined(_AIX) && !defined(_AIX71)
+# include <utime.h>
+#endif
+
#define INIT(subtype) \
do { \
if (req == NULL) \
@@ -120,7 +123,11 @@
do { \
if (cb != NULL) { \
uv__req_register(loop, req); \
- uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
+ uv__work_submit(loop, \
+ &req->work_req, \
+ UV__WORK_FAST_IO, \
+ uv__fs_work, \
+ uv__fs_done); \
return 0; \
} \
else { \
@@ -165,59 +172,17 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
static ssize_t uv__fs_futime(uv_fs_t* req) {
-#if defined(__linux__)
+#if defined(__linux__) \
+ || defined(_AIX71)
/* utimesat() has nanosecond resolution but we stick to microseconds
* for the sake of consistency with other platforms.
*/
- static int no_utimesat;
struct timespec ts[2];
- struct timeval tv[2];
- char path[sizeof("/proc/self/fd/") + 3 * sizeof(int)];
- int r;
-
- if (no_utimesat)
- goto skip;
-
ts[0].tv_sec = req->atime;
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
ts[1].tv_sec = req->mtime;
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
-
- r = uv__utimesat(req->file, NULL, ts, 0);
- if (r == 0)
- return r;
-
- if (errno != ENOSYS)
- return r;
-
- no_utimesat = 1;
-
-skip:
-
- tv[0].tv_sec = req->atime;
- tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
- tv[1].tv_sec = req->mtime;
- tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
- snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file);
-
- r = utimes(path, tv);
- if (r == 0)
- return r;
-
- switch (errno) {
- case ENOENT:
- if (fcntl(req->file, F_GETFL) == -1 && errno == EBADF)
- break;
- /* Fall through. */
-
- case EACCES:
- case ENOTDIR:
- errno = ENOSYS;
- break;
- }
-
- return r;
-
+ return futimens(req->file, ts);
#elif defined(__APPLE__) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
@@ -235,13 +200,6 @@ skip:
# else
return futimes(req->file, tv);
# endif
-#elif defined(_AIX71)
- struct timespec ts[2];
- ts[0].tv_sec = req->atime;
- ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
- ts[1].tv_sec = req->mtime;
- ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
- return futimens(req->file, ts);
#elif defined(__MVS__)
attrib_t atr;
memset(&atr, 0, sizeof(atr));
@@ -698,10 +656,48 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
static ssize_t uv__fs_utime(uv_fs_t* req) {
+#if defined(__linux__) \
+ || defined(_AIX71) \
+ || defined(__sun)
+ /* utimesat() has nanosecond resolution but we stick to microseconds
+ * for the sake of consistency with other platforms.
+ */
+ struct timespec ts[2];
+ ts[0].tv_sec = req->atime;
+ ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
+ ts[1].tv_sec = req->mtime;
+ ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
+ return utimensat(AT_FDCWD, req->path, ts, 0);
+#elif defined(__APPLE__) \
+ || defined(__DragonFly__) \
+ || defined(__FreeBSD__) \
+ || defined(__FreeBSD_kernel__) \
+ || defined(__NetBSD__) \
+ || defined(__OpenBSD__)
+ struct timeval tv[2];
+ tv[0].tv_sec = req->atime;
+ tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
+ tv[1].tv_sec = req->mtime;
+ tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
+ return utimes(req->path, tv);
+#elif defined(_AIX) \
+ && !defined(_AIX71)
struct utimbuf buf;
buf.actime = req->atime;
buf.modtime = req->mtime;
- return utime(req->path, &buf); /* TODO use utimes() where available */
+ return utime(req->path, &buf);
+#elif defined(__MVS__)
+ attrib_t atr;
+ memset(&atr, 0, sizeof(atr));
+ atr.att_mtimechg = 1;
+ atr.att_atimechg = 1;
+ atr.att_mtime = req->mtime;
+ atr.att_atime = req->atime;
+ return __lchattr(req->path, &atr, sizeof(atr));
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
}
diff --git a/deps/uv/src/unix/getaddrinfo.c b/deps/uv/src/unix/getaddrinfo.c
index 10e8afd75e..25827c1fee 100644
--- a/deps/uv/src/unix/getaddrinfo.c
+++ b/deps/uv/src/unix/getaddrinfo.c
@@ -186,6 +186,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
if (cb) {
uv__work_submit(loop,
&req->work_req,
+ UV__WORK_SLOW_IO,
uv__getaddrinfo_work,
uv__getaddrinfo_done);
return 0;
diff --git a/deps/uv/src/unix/getnameinfo.c b/deps/uv/src/unix/getnameinfo.c
index 9a4367224c..991002a67d 100644
--- a/deps/uv/src/unix/getnameinfo.c
+++ b/deps/uv/src/unix/getnameinfo.c
@@ -109,6 +109,7 @@ int uv_getnameinfo(uv_loop_t* loop,
if (getnameinfo_cb) {
uv__work_submit(loop,
&req->work_req,
+ UV__WORK_SLOW_IO,
uv__getnameinfo_work,
uv__getnameinfo_done);
return 0;
diff --git a/deps/uv/src/unix/ibmi.c b/deps/uv/src/unix/ibmi.c
index c50a4e76f8..b1ab549c23 100644
--- a/deps/uv/src/unix/ibmi.c
+++ b/deps/uv/src/unix/ibmi.c
@@ -72,7 +72,8 @@ void uv_loadavg(double avg[3]) {
int uv_resident_set_memory(size_t* rss) {
- return UV_ENOSYS;
+ *rss = 0;
+ return 0;
}
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index d09bbcdd6f..124a0a57f4 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -20,7 +20,7 @@
/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their
* EPOLL* counterparts. We use the POLL* variants in this file because that
- * is what libuv uses elsewhere and it avoids a dependency on <sys/epoll.h>.
+ * is what libuv uses elsewhere.
*/
#include "uv.h"
@@ -34,6 +34,7 @@
#include <errno.h>
#include <net/if.h>
+#include <sys/epoll.h>
#include <sys/param.h>
#include <sys/prctl.h>
#include <sys/sysinfo.h>
@@ -84,13 +85,13 @@ static unsigned long read_cpufreq(unsigned int cpunum);
int uv__platform_loop_init(uv_loop_t* loop) {
int fd;
- fd = uv__epoll_create1(UV__EPOLL_CLOEXEC);
+ fd = epoll_create1(EPOLL_CLOEXEC);
/* epoll_create1() can fail either because it's not implemented (old kernel)
* or because it doesn't understand the EPOLL_CLOEXEC flag.
*/
if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
- fd = uv__epoll_create(256);
+ fd = epoll_create(256);
if (fd != -1)
uv__cloexec(fd, 1);
@@ -134,20 +135,20 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
- struct uv__epoll_event* events;
- struct uv__epoll_event dummy;
+ struct epoll_event* events;
+ struct epoll_event dummy;
uintptr_t i;
uintptr_t nfds;
assert(loop->watchers != NULL);
- events = (struct uv__epoll_event*) loop->watchers[loop->nwatchers];
+ events = (struct epoll_event*) loop->watchers[loop->nwatchers];
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
if (events != NULL)
/* Invalidate events with same file descriptor */
for (i = 0; i < nfds; i++)
- if ((int) events[i].data == fd)
- events[i].data = -1;
+ if (events[i].data.fd == fd)
+ events[i].data.fd = -1;
/* Remove the file descriptor from the epoll.
* This avoids a problem where the same file description remains open
@@ -160,25 +161,25 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
* has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
*/
memset(&dummy, 0, sizeof(dummy));
- uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy);
+ epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);
}
}
int uv__io_check_fd(uv_loop_t* loop, int fd) {
- struct uv__epoll_event e;
+ struct epoll_event e;
int rc;
e.events = POLLIN;
- e.data = -1;
+ e.data.fd = -1;
rc = 0;
- if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e))
+ if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))
if (errno != EEXIST)
rc = UV__ERR(errno);
if (rc == 0)
- if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e))
+ if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))
abort();
return rc;
@@ -195,16 +196,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* that being the largest value I have seen in the wild (and only once.)
*/
static const int max_safe_timeout = 1789569;
- static int no_epoll_pwait;
- static int no_epoll_wait;
- struct uv__epoll_event events[1024];
- struct uv__epoll_event* pe;
- struct uv__epoll_event e;
+ struct epoll_event events[1024];
+ struct epoll_event* pe;
+ struct epoll_event e;
int real_timeout;
QUEUE* q;
uv__io_t* w;
sigset_t sigset;
- uint64_t sigmask;
+ sigset_t* psigset;
uint64_t base;
int have_signals;
int nevents;
@@ -230,35 +229,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
assert(w->fd < (int) loop->nwatchers);
e.events = w->pevents;
- e.data = w->fd;
+ e.data.fd = w->fd;
if (w->events == 0)
- op = UV__EPOLL_CTL_ADD;
+ op = EPOLL_CTL_ADD;
else
- op = UV__EPOLL_CTL_MOD;
+ op = EPOLL_CTL_MOD;
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
* events, skip the syscall and squelch the events after epoll_wait().
*/
- if (uv__epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
+ if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
if (errno != EEXIST)
abort();
- assert(op == UV__EPOLL_CTL_ADD);
+ assert(op == EPOLL_CTL_ADD);
/* We've reactivated a file descriptor that's been watched before. */
- if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_MOD, w->fd, &e))
+ if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))
abort();
}
w->events = w->pevents;
}
- sigmask = 0;
+ psigset = NULL;
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
sigemptyset(&sigset);
sigaddset(&sigset, SIGPROF);
- sigmask |= 1 << (SIGPROF - 1);
+ psigset = &sigset;
}
assert(timeout >= -1);
@@ -273,30 +272,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
timeout = max_safe_timeout;
- if (sigmask != 0 && no_epoll_pwait != 0)
- if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
- abort();
-
- if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
- nfds = uv__epoll_pwait(loop->backend_fd,
- events,
- ARRAY_SIZE(events),
- timeout,
- sigmask);
- if (nfds == -1 && errno == ENOSYS)
- no_epoll_pwait = 1;
- } else {
- nfds = uv__epoll_wait(loop->backend_fd,
- events,
- ARRAY_SIZE(events),
- timeout);
- if (nfds == -1 && errno == ENOSYS)
- no_epoll_wait = 1;
- }
-
- if (sigmask != 0 && no_epoll_pwait != 0)
- if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
- abort();
+ nfds = epoll_pwait(loop->backend_fd,
+ events,
+ ARRAY_SIZE(events),
+ timeout,
+ psigset);
/* Update loop->time unconditionally. It's tempting to skip the update when
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
@@ -317,12 +297,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
if (nfds == -1) {
- if (errno == ENOSYS) {
- /* epoll_wait() or epoll_pwait() failed, try the other system call. */
- assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
- continue;
- }
-
if (errno != EINTR)
abort();
@@ -344,7 +318,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
for (i = 0; i < nfds; i++) {
pe = events + i;
- fd = pe->data;
+ fd = pe->data.fd;
/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
@@ -361,7 +335,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* Ignore all errors because we may be racing with another thread
* when the file descriptor is closed.
*/
- uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, pe);
+ epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);
continue;
}
diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c
index 89998ded26..bfd7544879 100644
--- a/deps/uv/src/unix/linux-syscalls.c
+++ b/deps/uv/src/unix/linux-syscalls.c
@@ -77,56 +77,6 @@
# endif
#endif /* __NR_eventfd2 */
-#ifndef __NR_epoll_create
-# if defined(__x86_64__)
-# define __NR_epoll_create 213
-# elif defined(__i386__)
-# define __NR_epoll_create 254
-# elif defined(__arm__)
-# define __NR_epoll_create (UV_SYSCALL_BASE + 250)
-# endif
-#endif /* __NR_epoll_create */
-
-#ifndef __NR_epoll_create1
-# if defined(__x86_64__)
-# define __NR_epoll_create1 291
-# elif defined(__i386__)
-# define __NR_epoll_create1 329
-# elif defined(__arm__)
-# define __NR_epoll_create1 (UV_SYSCALL_BASE + 357)
-# endif
-#endif /* __NR_epoll_create1 */
-
-#ifndef __NR_epoll_ctl
-# if defined(__x86_64__)
-# define __NR_epoll_ctl 233 /* used to be 214 */
-# elif defined(__i386__)
-# define __NR_epoll_ctl 255
-# elif defined(__arm__)
-# define __NR_epoll_ctl (UV_SYSCALL_BASE + 251)
-# endif
-#endif /* __NR_epoll_ctl */
-
-#ifndef __NR_epoll_wait
-# if defined(__x86_64__)
-# define __NR_epoll_wait 232 /* used to be 215 */
-# elif defined(__i386__)
-# define __NR_epoll_wait 256
-# elif defined(__arm__)
-# define __NR_epoll_wait (UV_SYSCALL_BASE + 252)
-# endif
-#endif /* __NR_epoll_wait */
-
-#ifndef __NR_epoll_pwait
-# if defined(__x86_64__)
-# define __NR_epoll_pwait 281
-# elif defined(__i386__)
-# define __NR_epoll_pwait 319
-# elif defined(__arm__)
-# define __NR_epoll_pwait (UV_SYSCALL_BASE + 346)
-# endif
-#endif /* __NR_epoll_pwait */
-
#ifndef __NR_inotify_init
# if defined(__x86_64__)
# define __NR_inotify_init 253
@@ -285,76 +235,6 @@ int uv__eventfd2(unsigned int count, int flags) {
}
-int uv__epoll_create(int size) {
-#if defined(__NR_epoll_create)
- return syscall(__NR_epoll_create, size);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__epoll_create1(int flags) {
-#if defined(__NR_epoll_create1)
- return syscall(__NR_epoll_create1, flags);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event* events) {
-#if defined(__NR_epoll_ctl)
- return syscall(__NR_epoll_ctl, epfd, op, fd, events);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__epoll_wait(int epfd,
- struct uv__epoll_event* events,
- int nevents,
- int timeout) {
-#if defined(__NR_epoll_wait)
- int result;
- result = syscall(__NR_epoll_wait, epfd, events, nevents, timeout);
-#if MSAN_ACTIVE
- if (result > 0)
- __msan_unpoison(events, sizeof(events[0]) * result);
-#endif
- return result;
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__epoll_pwait(int epfd,
- struct uv__epoll_event* events,
- int nevents,
- int timeout,
- uint64_t sigmask) {
-#if defined(__NR_epoll_pwait)
- int result;
- result = syscall(__NR_epoll_pwait,
- epfd,
- events,
- nevents,
- timeout,
- &sigmask,
- sizeof(sigmask));
-#if MSAN_ACTIVE
- if (result > 0)
- __msan_unpoison(events, sizeof(events[0]) * result);
-#endif
- return result;
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
int uv__inotify_init(void) {
#if defined(__NR_inotify_init)
return syscall(__NR_inotify_init);
@@ -431,19 +311,6 @@ int uv__recvmmsg(int fd,
}
-int uv__utimesat(int dirfd,
- const char* path,
- const struct timespec times[2],
- int flags)
-{
-#if defined(__NR_utimensat)
- return syscall(__NR_utimensat, dirfd, path, times, flags);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
#if defined(__NR_preadv)
return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h
index 4c095e9b53..3dfd329d6c 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -66,12 +66,6 @@
# define UV__SOCK_NONBLOCK UV__O_NONBLOCK
#endif
-/* epoll flags */
-#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC
-#define UV__EPOLL_CTL_ADD 1
-#define UV__EPOLL_CTL_DEL 2
-#define UV__EPOLL_CTL_MOD 3
-
/* inotify flags */
#define UV__IN_ACCESS 0x001
#define UV__IN_MODIFY 0x002
@@ -86,18 +80,6 @@
#define UV__IN_DELETE_SELF 0x400
#define UV__IN_MOVE_SELF 0x800
-#if defined(__x86_64__)
-struct uv__epoll_event {
- uint32_t events;
- uint64_t data;
-} __attribute__((packed));
-#else
-struct uv__epoll_event {
- uint32_t events;
- uint64_t data;
-};
-#endif
-
struct uv__inotify_event {
int32_t wd;
uint32_t mask;
@@ -113,18 +95,6 @@ struct uv__mmsghdr {
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
int uv__eventfd(unsigned int count);
-int uv__epoll_create(int size);
-int uv__epoll_create1(int flags);
-int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event *ev);
-int uv__epoll_wait(int epfd,
- struct uv__epoll_event* events,
- int nevents,
- int timeout);
-int uv__epoll_pwait(int epfd,
- struct uv__epoll_event* events,
- int nevents,
- int timeout,
- uint64_t sigmask);
int uv__eventfd2(unsigned int count, int flags);
int uv__inotify_init(void);
int uv__inotify_init1(int flags);
@@ -140,10 +110,6 @@ int uv__sendmmsg(int fd,
struct uv__mmsghdr* mmsg,
unsigned int vlen,
unsigned int flags);
-int uv__utimesat(int dirfd,
- const char* path,
- const struct timespec times[2],
- int flags);
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
int uv__dup3(int oldfd, int newfd, int flags);
diff --git a/deps/uv/src/unix/os390-syscalls.h b/deps/uv/src/unix/os390-syscalls.h
index 6e34a88cb9..ea599107b3 100644
--- a/deps/uv/src/unix/os390-syscalls.h
+++ b/deps/uv/src/unix/os390-syscalls.h
@@ -36,10 +36,6 @@
#define MAX_ITEMS_PER_EPOLL 1024
#define UV__O_CLOEXEC 0x80000
-#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC
-#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD
-#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL
-#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD
struct epoll_event {
int events;
diff --git a/deps/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c
index f766b39339..5e93178f6f 100644
--- a/deps/uv/src/unix/os390.c
+++ b/deps/uv/src/unix/os390.c
@@ -662,7 +662,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
/* Remove the file descriptor from the epoll. */
if (loop->ep != NULL)
- epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy);
+ epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, &dummy);
}
@@ -838,9 +838,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
e.fd = w->fd;
if (w->events == 0)
- op = UV__EPOLL_CTL_ADD;
+ op = EPOLL_CTL_ADD;
else
- op = UV__EPOLL_CTL_MOD;
+ op = EPOLL_CTL_MOD;
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
* events, skip the syscall and squelch the events after epoll_wait().
@@ -849,10 +849,10 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (errno != EEXIST)
abort();
- assert(op == UV__EPOLL_CTL_ADD);
+ assert(op == EPOLL_CTL_ADD);
/* We've reactivated a file descriptor that's been watched before. */
- if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e))
+ if (epoll_ctl(loop->ep, EPOLL_CTL_MOD, w->fd, &e))
abort();
}
@@ -934,7 +934,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* Ignore all errors because we may be racing with another thread
* when the file descriptor is closed.
*/
- epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe);
+ epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, pe);
continue;
}
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index 0718bc81b8..e450a30e9c 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -132,11 +132,21 @@ void uv__pipe_close(uv_pipe_t* handle) {
int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
+ int flags;
+ int mode;
int err;
+ flags = 0;
if (uv__fd_exists(handle->loop, fd))
return UV_EEXIST;
+ do
+ mode = fcntl(fd, F_GETFL);
+ while (mode == -1 && errno == EINTR);
+
+ if (mode == -1)
+ return UV__ERR(errno); /* according to docs, must be EBADF */
+
err = uv__nonblock(fd, 1);
if (err)
return err;
@@ -147,9 +157,13 @@ int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
return err;
#endif /* defined(__APPLE__) */
- return uv__stream_open((uv_stream_t*)handle,
- fd,
- UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
+ mode &= O_ACCMODE;
+ if (mode != O_WRONLY)
+ flags |= UV_HANDLE_READABLE;
+ if (mode != O_RDONLY)
+ flags |= UV_HANDLE_WRITABLE;
+
+ return uv__stream_open((uv_stream_t*)handle, fd, flags);
}
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 5a96b66b17..2e84eeeb82 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -1676,6 +1676,7 @@ void uv__stream_close(uv_stream_t* handle) {
uv__io_close(handle->loop, &handle->io_watcher);
uv_read_stop(handle);
uv__handle_stop(handle);
+ handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
if (handle->io_watcher.fd != -1) {
/* Don't close stdio file descriptors. Nothing good comes from it. */
diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c
index 1b92b5c914..74d3d75d76 100644
--- a/deps/uv/src/unix/tty.c
+++ b/deps/uv/src/unix/tty.c
@@ -92,13 +92,15 @@ static int uv__tty_is_slave(const int fd) {
return result;
}
-int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
+int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) {
uv_handle_type type;
int flags;
int newfd;
int r;
int saved_flags;
+ int mode;
char path[256];
+ (void)unused; /* deprecated parameter is no longer needed */
/* File descriptors that refer to files cannot be monitored with epoll.
* That restriction also applies to character devices like /dev/random
@@ -111,6 +113,15 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
flags = 0;
newfd = -1;
+ /* Save the fd flags in case we need to restore them due to an error. */
+ do
+ saved_flags = fcntl(fd, F_GETFL);
+ while (saved_flags == -1 && errno == EINTR);
+
+ if (saved_flags == -1)
+ return UV__ERR(errno);
+ mode = saved_flags & O_ACCMODE;
+
/* Reopen the file descriptor when it refers to a tty. This lets us put the
* tty in non-blocking mode without affecting other processes that share it
* with us.
@@ -128,13 +139,13 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
* slave device.
*/
if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0)
- r = uv__open_cloexec(path, O_RDWR);
+ r = uv__open_cloexec(path, mode);
else
r = -1;
if (r < 0) {
/* fallback to using blocking writes */
- if (!readable)
+ if (mode != O_RDONLY)
flags |= UV_HANDLE_BLOCKING_WRITES;
goto skip;
}
@@ -154,22 +165,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
fd = newfd;
}
-#if defined(__APPLE__)
- /* Save the fd flags in case we need to restore them due to an error. */
- do
- saved_flags = fcntl(fd, F_GETFL);
- while (saved_flags == -1 && errno == EINTR);
-
- if (saved_flags == -1) {
- if (newfd != -1)
- uv__close(newfd);
- return UV__ERR(errno);
- }
-#endif
-
- /* Pacify the compiler. */
- (void) &saved_flags;
-
skip:
uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY);
@@ -194,9 +189,9 @@ skip:
}
#endif
- if (readable)
+ if (mode != O_WRONLY)
flags |= UV_HANDLE_READABLE;
- else
+ if (mode != O_RDONLY)
flags |= UV_HANDLE_WRITABLE;
uv__stream_open((uv_stream_t*) tty, fd, flags);
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index 3289950d00..5555f83aee 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -164,8 +164,15 @@ void uv__fs_poll_close(uv_fs_poll_t* handle);
int uv__getaddrinfo_translate_error(int sys_err); /* EAI_* error. */
+enum uv__work_kind {
+ UV__WORK_CPU,
+ UV__WORK_FAST_IO,
+ UV__WORK_SLOW_IO
+};
+
void uv__work_submit(uv_loop_t* loop,
struct uv__work *w,
+ enum uv__work_kind kind,
void (*work)(struct uv__work *w),
void (*done)(struct uv__work *w, int status));
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index afdf01e787..bf80d77e27 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -381,6 +381,57 @@ int uv_backend_timeout(const uv_loop_t* loop) {
}
+static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
+ DWORD bytes;
+ ULONG_PTR key;
+ OVERLAPPED* overlapped;
+ uv_req_t* req;
+ int repeat;
+ uint64_t timeout_time;
+
+ timeout_time = loop->time + timeout;
+
+ for (repeat = 0; ; repeat++) {
+ GetQueuedCompletionStatus(loop->iocp,
+ &bytes,
+ &key,
+ &overlapped,
+ timeout);
+
+ if (overlapped) {
+ /* Package was dequeued */
+ req = uv_overlapped_to_req(overlapped);
+ uv_insert_pending_req(loop, req);
+
+ /* Some time might have passed waiting for I/O,
+ * so update the loop time here.
+ */
+ uv_update_time(loop);
+ } else if (GetLastError() != WAIT_TIMEOUT) {
+ /* Serious error */
+ uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
+ } else if (timeout > 0) {
+ /* GetQueuedCompletionStatus can occasionally return a little early.
+ * Make sure that the desired timeout target time is reached.
+ */
+ uv_update_time(loop);
+ if (timeout_time > loop->time) {
+ timeout = (DWORD)(timeout_time - loop->time);
+ /* The first call to GetQueuedCompletionStatus should return very
+ * close to the target time and the second should reach it, but
+ * this is not stated in the documentation. To make sure a busy
+ * loop cannot happen, the timeout is increased exponentially
+ * starting on the third round.
+ */
+ timeout += repeat ? (1 << (repeat - 1)) : 0;
+ continue;
+ }
+ }
+ break;
+ }
+}
+
+
static void uv__poll(uv_loop_t* loop, DWORD timeout) {
BOOL success;
uv_req_t* req;
@@ -473,7 +524,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
- uv__poll(loop, timeout);
+ if (pGetQueuedCompletionStatusEx)
+ uv__poll(loop, timeout);
+ else
+ uv__poll_wine(loop, timeout);
+
uv_check_invoke(loop);
uv_process_endgames(loop);
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 71b6a81a0d..0886d79982 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -55,7 +55,11 @@
do { \
if (cb != NULL) { \
uv__req_register(loop, req); \
- uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
+ uv__work_submit(loop, \
+ &req->work_req, \
+ UV__WORK_FAST_IO, \
+ uv__fs_work, \
+ uv__fs_done); \
return 0; \
} else { \
uv__fs_work(&req->work_req); \
diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c
index 063b4937cd..614ea8e376 100644
--- a/deps/uv/src/win/getaddrinfo.c
+++ b/deps/uv/src/win/getaddrinfo.c
@@ -368,6 +368,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
if (getaddrinfo_cb) {
uv__work_submit(loop,
&req->work_req,
+ UV__WORK_SLOW_IO,
uv__getaddrinfo_work,
uv__getaddrinfo_done);
return 0;
diff --git a/deps/uv/src/win/getnameinfo.c b/deps/uv/src/win/getnameinfo.c
index 71785a9fa6..b3773380c2 100644
--- a/deps/uv/src/win/getnameinfo.c
+++ b/deps/uv/src/win/getnameinfo.c
@@ -145,6 +145,7 @@ int uv_getnameinfo(uv_loop_t* loop,
if (getnameinfo_cb) {
uv__work_submit(loop,
&req->work_req,
+ UV__WORK_SLOW_IO,
uv__getnameinfo_work,
uv__getnameinfo_done);
return 0;
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index d62aafb7d8..7045b11540 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -172,9 +172,12 @@ void uv_console_init(void) {
}
-int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
+int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
+ BOOL readable;
+ DWORD NumberOfEvents;
HANDLE handle;
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
+ (void)unused;
uv__once_init();
handle = (HANDLE) uv__get_osfhandle(fd);
@@ -199,6 +202,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
fd = -1;
}
+ readable = GetNumberOfConsoleInputEvents(handle, &NumberOfEvents);
if (!readable) {
/* Obtain the screen buffer info with the output handle. */
if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) {
@@ -382,12 +386,6 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
}
-int uv_is_tty(uv_file file) {
- DWORD result;
- return GetConsoleMode((HANDLE) _get_osfhandle(file), &result) != 0;
-}
-
-
int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
CONSOLE_SCREEN_BUFFER_INFO info;
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index 402aeea666..37df849f8f 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -366,7 +366,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
int err;
if (handle->flags & UV_HANDLE_READING) {
- return WSAEALREADY;
+ return UV_EALREADY;
}
err = uv_udp_maybe_bind(handle,
@@ -374,7 +374,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
sizeof(uv_addr_ip4_any_),
0);
if (err)
- return err;
+ return uv_translate_sys_error(err);
handle->flags |= UV_HANDLE_READING;
INCREASE_ACTIVE_COUNT(loop, handle);
diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c
index 0fd598eacb..2c09b448a9 100644
--- a/deps/uv/src/win/winapi.c
+++ b/deps/uv/src/win/winapi.c
@@ -34,6 +34,9 @@ sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
sNtQueryDirectoryFile pNtQueryDirectoryFile;
sNtQuerySystemInformation pNtQuerySystemInformation;
+/* Kernel32 function pointers */
+sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
+
/* Powrprof.dll function pointer */
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
@@ -45,6 +48,7 @@ void uv_winapi_init(void) {
HMODULE ntdll_module;
HMODULE powrprof_module;
HMODULE user32_module;
+ HMODULE kernel32_module;
ntdll_module = GetModuleHandleA("ntdll.dll");
if (ntdll_module == NULL) {
@@ -98,6 +102,15 @@ void uv_winapi_init(void) {
uv_fatal_error(GetLastError(), "GetProcAddress");
}
+ kernel32_module = GetModuleHandleA("kernel32.dll");
+ if (kernel32_module == NULL) {
+ uv_fatal_error(GetLastError(), "GetModuleHandleA");
+ }
+
+ pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress(
+ kernel32_module,
+ "GetQueuedCompletionStatusEx");
+
powrprof_module = LoadLibraryA("powrprof.dll");
if (powrprof_module != NULL) {
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h
index d0fcfd8e7a..cfbac52eb1 100644
--- a/deps/uv/src/win/winapi.h
+++ b/deps/uv/src/win/winapi.h
@@ -4642,6 +4642,14 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
# define ERROR_MUI_FILE_NOT_LOADED 15105
#endif
+typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
+ (HANDLE CompletionPort,
+ LPOVERLAPPED_ENTRY lpCompletionPortEntries,
+ ULONG ulCount,
+ PULONG ulNumEntriesRemoved,
+ DWORD dwMilliseconds,
+ BOOL fAlertable);
+
/* from powerbase.h */
#ifndef DEVICE_NOTIFY_CALLBACK
# define DEVICE_NOTIFY_CALLBACK 2
@@ -4704,6 +4712,9 @@ extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
extern sNtQuerySystemInformation pNtQuerySystemInformation;
+/* Kernel32 function pointers */
+extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
+
/* Powrprof.dll function pointer */
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
diff --git a/deps/uv/test/test-condvar.c b/deps/uv/test/test-condvar.c
index ec60f16403..50f3c047c0 100644
--- a/deps/uv/test/test-condvar.c
+++ b/deps/uv/test/test-condvar.c
@@ -259,7 +259,7 @@ TEST_IMPL(condvar_5) {
* https://msdn.microsoft.com/en-us/library/ms687069(VS.85).aspx */
elapsed = after - before;
ASSERT(0.75 * timeout <= elapsed); /* 1.0 too large for Windows. */
- ASSERT(elapsed <= 1.5 * timeout); /* 1.1 too small for OSX. */
+ ASSERT(elapsed <= 5.0 * timeout); /* MacOS has reported failures up to 1.75. */
worker_config_destroy(&wc);
diff --git a/deps/uv/test/test-fork.c b/deps/uv/test/test-fork.c
index 2a1ddc497a..f47ae3e656 100644
--- a/deps/uv/test/test-fork.c
+++ b/deps/uv/test/test-fork.c
@@ -283,6 +283,7 @@ TEST_IMPL(fork_signal_to_child_closed) {
int sync_pipe[2];
int sync_pipe2[2];
char sync_buf[1];
+ int r;
fork_signal_cb_called = 0; /* reset */
@@ -326,9 +327,10 @@ TEST_IMPL(fork_signal_to_child_closed) {
/* Don't run the loop. Wait for the parent to call us */
printf("Waiting on parent in child\n");
/* Wait for parent. read may fail if the parent tripped an ASSERT
- and exited, so this isn't in an ASSERT.
+ and exited, so this ASSERT is generous.
*/
- read(sync_pipe2[0], sync_buf, 1);
+ r = read(sync_pipe2[0], sync_buf, 1);
+ ASSERT(-1 <= r && r <= 1);
ASSERT(0 == fork_signal_cb_called);
printf("Exiting child \n");
/* Note that we're deliberately not running the loop
diff --git a/deps/uv/test/test-handle-fileno.c b/deps/uv/test/test-handle-fileno.c
index 3fe933adeb..8a093e2ea4 100644
--- a/deps/uv/test/test-handle-fileno.c
+++ b/deps/uv/test/test-handle-fileno.c
@@ -27,7 +27,7 @@ static int get_tty_fd(void) {
/* Make sure we have an FD that refers to a tty */
#ifdef _WIN32
HANDLE handle;
- handle = CreateFileA("conout$",
+ handle = CreateFileA("conin$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
@@ -107,11 +107,15 @@ TEST_IMPL(handle_fileno) {
} else {
r = uv_tty_init(loop, &tty, tty_fd, 0);
ASSERT(r == 0);
+ ASSERT(uv_is_readable((uv_stream_t*) &tty));
+ ASSERT(!uv_is_writable((uv_stream_t*) &tty));
r = uv_fileno((uv_handle_t*) &tty, &fd);
ASSERT(r == 0);
uv_close((uv_handle_t*) &tty, NULL);
r = uv_fileno((uv_handle_t*) &tty, &fd);
ASSERT(r == UV_EBADF);
+ ASSERT(!uv_is_readable((uv_stream_t*) &tty));
+ ASSERT(!uv_is_writable((uv_stream_t*) &tty));
}
uv_run(loop, UV_RUN_DEFAULT);
diff --git a/deps/uv/test/test-pipe-close-stdout-read-stdin.c b/deps/uv/test/test-pipe-close-stdout-read-stdin.c
index 4ab14789a3..c8804b0e18 100644
--- a/deps/uv/test/test-pipe-close-stdout-read-stdin.c
+++ b/deps/uv/test/test-pipe-close-stdout-read-stdin.c
@@ -66,7 +66,8 @@ TEST_IMPL(pipe_close_stdout_read_stdin) {
*/
close(fd[1]);
/* block until write end of pipe is closed */
- read(fd[0], &buf, 1);
+ r = read(fd[0], &buf, 1);
+ ASSERT(-1 <= r && r <= 1);
close(0);
r = dup(fd[0]);
ASSERT(r != -1);
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index 1ab6e78807..4fcd905eed 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/test/test-spawn.c
@@ -1733,6 +1733,7 @@ TEST_IMPL(spawn_inherit_streams) {
uv_buf_t buf;
unsigned int i;
int r;
+ int bidir;
uv_write_t write_req;
uv_loop_t* loop;
@@ -1751,6 +1752,15 @@ TEST_IMPL(spawn_inherit_streams) {
ASSERT(uv_pipe_open(&pipe_stdout_child, fds_stdout[1]) == 0);
ASSERT(uv_pipe_open(&pipe_stdin_parent, fds_stdin[1]) == 0);
ASSERT(uv_pipe_open(&pipe_stdout_parent, fds_stdout[0]) == 0);
+ ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdin_child));
+ ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdout_child));
+ ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdin_parent));
+ ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdout_parent));
+ /* Some systems (SVR4) open a bidirectional pipe, most don't. */
+ bidir = uv_is_writable((uv_stream_t*) &pipe_stdin_child);
+ ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdout_child) == bidir);
+ ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdin_parent) == bidir);
+ ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdout_parent) == bidir);
child_stdio[0].flags = UV_INHERIT_STREAM;
child_stdio[0].data.stream = (uv_stream_t *)&pipe_stdin_child;
diff --git a/deps/uv/test/test-tty.c b/deps/uv/test/test-tty.c
index 6aaeda8f59..3bbdfad780 100644
--- a/deps/uv/test/test-tty.c
+++ b/deps/uv/test/test-tty.c
@@ -96,9 +96,13 @@ TEST_IMPL(tty) {
r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1); /* Readable. */
ASSERT(r == 0);
+ ASSERT(uv_is_readable((uv_stream_t*) &tty_in));
+ ASSERT(!uv_is_writable((uv_stream_t*) &tty_in));
r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */
ASSERT(r == 0);
+ ASSERT(!uv_is_readable((uv_stream_t*) &tty_out));
+ ASSERT(uv_is_writable((uv_stream_t*) &tty_out));
r = uv_tty_get_winsize(&tty_out, &width, &height);
ASSERT(r == 0);
@@ -186,6 +190,8 @@ TEST_IMPL(tty_raw) {
r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1); /* Readable. */
ASSERT(r == 0);
+ ASSERT(uv_is_readable((uv_stream_t*) &tty_in));
+ ASSERT(!uv_is_writable((uv_stream_t*) &tty_in));
r = uv_read_start((uv_stream_t*)&tty_in, tty_raw_alloc, tty_raw_read);
ASSERT(r == 0);
@@ -242,6 +248,8 @@ TEST_IMPL(tty_empty_write) {
r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */
ASSERT(r == 0);
+ ASSERT(!uv_is_readable((uv_stream_t*) &tty_out));
+ ASSERT(uv_is_writable((uv_stream_t*) &tty_out));
bufs[0].len = 0;
bufs[0].base = &dummy[0];
@@ -309,6 +317,8 @@ TEST_IMPL(tty_file) {
#ifndef _WIN32
uv_loop_t loop;
uv_tty_t tty;
+ uv_tty_t tty_ro;
+ uv_tty_t tty_wo;
int fd;
ASSERT(0 == uv_loop_init(&loop));
@@ -334,13 +344,40 @@ TEST_IMPL(tty_file) {
ASSERT(0 == close(fd));
}
- fd = open("/dev/tty", O_RDONLY);
+ fd = open("/dev/tty", O_RDWR);
if (fd != -1) {
ASSERT(0 == uv_tty_init(&loop, &tty, fd, 1));
- ASSERT(0 == close(fd));
+ ASSERT(0 == close(fd)); /* TODO: it's indeterminate who owns fd now */
+ ASSERT(uv_is_readable((uv_stream_t*) &tty));
+ ASSERT(uv_is_writable((uv_stream_t*) &tty));
uv_close((uv_handle_t*) &tty, NULL);
+ ASSERT(!uv_is_readable((uv_stream_t*) &tty));
+ ASSERT(!uv_is_writable((uv_stream_t*) &tty));
+ }
+
+ fd = open("/dev/tty", O_RDONLY);
+ if (fd != -1) {
+ ASSERT(0 == uv_tty_init(&loop, &tty_ro, fd, 1));
+ ASSERT(0 == close(fd)); /* TODO: it's indeterminate who owns fd now */
+ ASSERT(uv_is_readable((uv_stream_t*) &tty_ro));
+ ASSERT(!uv_is_writable((uv_stream_t*) &tty_ro));
+ uv_close((uv_handle_t*) &tty_ro, NULL);
+ ASSERT(!uv_is_readable((uv_stream_t*) &tty_ro));
+ ASSERT(!uv_is_writable((uv_stream_t*) &tty_ro));
}
+ fd = open("/dev/tty", O_WRONLY);
+ if (fd != -1) {
+ ASSERT(0 == uv_tty_init(&loop, &tty_wo, fd, 0));
+ ASSERT(0 == close(fd)); /* TODO: it's indeterminate who owns fd now */
+ ASSERT(!uv_is_readable((uv_stream_t*) &tty_wo));
+ ASSERT(uv_is_writable((uv_stream_t*) &tty_wo));
+ uv_close((uv_handle_t*) &tty_wo, NULL);
+ ASSERT(!uv_is_readable((uv_stream_t*) &tty_wo));
+ ASSERT(!uv_is_writable((uv_stream_t*) &tty_wo));
+ }
+
+
ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT));
ASSERT(0 == uv_loop_close(&loop));
@@ -370,6 +407,10 @@ TEST_IMPL(tty_pty) {
ASSERT(0 == uv_tty_init(&loop, &slave_tty, slave_fd, 0));
ASSERT(0 == uv_tty_init(&loop, &master_tty, master_fd, 0));
+ ASSERT(uv_is_readable((uv_stream_t*) &slave_tty));
+ ASSERT(uv_is_writable((uv_stream_t*) &slave_tty));
+ ASSERT(uv_is_readable((uv_stream_t*) &master_tty));
+ ASSERT(uv_is_writable((uv_stream_t*) &master_tty));
/* Check if the file descriptor was reopened. If it is,
* UV_HANDLE_BLOCKING_WRITES (value 0x100000) isn't set on flags.
*/