summaryrefslogtreecommitdiff
path: root/deps/uv
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2019-03-16 14:38:18 -0400
committercjihrig <cjihrig@gmail.com>2019-03-18 14:42:24 -0400
commitd6f6d7f8541327b72667d38777c47b9ea675125d (patch)
treebabcc15f478453e5a7a426f1227c3372cb79e869 /deps/uv
parent04f30e1a7a5a2f49b611314578758e2009ec2152 (diff)
downloadandroid-node-v8-d6f6d7f8541327b72667d38777c47b9ea675125d.tar.gz
android-node-v8-d6f6d7f8541327b72667d38777c47b9ea675125d.tar.bz2
android-node-v8-d6f6d7f8541327b72667d38777c47b9ea675125d.zip
deps: upgrade to libuv 1.27.0
Notable changes: - `statx()` is used to retrieve file birth times on supported platforms. - Improved support of running under Windows safe mode. - Add support for UDP connected sockets. Several functions can now return `UV_EBADF` instead of `UV_EINVAL`. - SunOS support is improved. PR-URL: https://github.com/nodejs/node/pull/26707 Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'deps/uv')
-rw-r--r--deps/uv/AUTHORS2
-rw-r--r--deps/uv/CMakeLists.txt6
-rw-r--r--deps/uv/ChangeLog59
-rw-r--r--deps/uv/Makefile.am24
-rw-r--r--deps/uv/README.md2
-rw-r--r--deps/uv/configure.ac21
-rw-r--r--deps/uv/docs/src/loop.rst2
-rw-r--r--deps/uv/docs/src/signal.rst24
-rw-r--r--deps/uv/docs/src/threading.rst4
-rw-r--r--deps/uv/docs/src/udp.rst54
-rw-r--r--deps/uv/include/uv.h4
-rw-r--r--deps/uv/include/uv/version.h2
-rw-r--r--deps/uv/src/fs-poll.c63
-rw-r--r--deps/uv/src/unix/atomic-ops.h4
-rw-r--r--deps/uv/src/unix/core.c26
-rw-r--r--deps/uv/src/unix/fs.c82
-rw-r--r--deps/uv/src/unix/getaddrinfo.c2
-rw-r--r--deps/uv/src/unix/internal.h10
-rw-r--r--deps/uv/src/unix/kqueue.c5
-rw-r--r--deps/uv/src/unix/linux-syscalls.c28
-rw-r--r--deps/uv/src/unix/linux-syscalls.h35
-rw-r--r--deps/uv/src/unix/pipe.c10
-rw-r--r--deps/uv/src/unix/sunos.c18
-rw-r--r--deps/uv/src/unix/tcp.c34
-rw-r--r--deps/uv/src/unix/thread.c2
-rw-r--r--deps/uv/src/unix/udp.c115
-rw-r--r--deps/uv/src/uv-common.c92
-rw-r--r--deps/uv/src/uv-common.h9
-rw-r--r--deps/uv/src/uv-data-getter-setters.c2
-rw-r--r--deps/uv/src/win/core.c27
-rw-r--r--deps/uv/src/win/handle.c1
-rw-r--r--deps/uv/src/win/internal.h8
-rw-r--r--deps/uv/src/win/tcp.c40
-rw-r--r--deps/uv/src/win/udp.c103
-rw-r--r--deps/uv/src/win/winsock.c15
-rw-r--r--deps/uv/test/run-tests.c7
-rw-r--r--deps/uv/test/task.h3
-rw-r--r--deps/uv/test/test-fs-copyfile.c3
-rw-r--r--deps/uv/test/test-fs-poll.c74
-rw-r--r--deps/uv/test/test-fs.c13
-rw-r--r--deps/uv/test/test-hrtime.c8
-rw-r--r--deps/uv/test/test-ipc.c2
-rw-r--r--deps/uv/test/test-list.h13
-rw-r--r--deps/uv/test/test-loop-handles.c2
-rw-r--r--deps/uv/test/test-poll.c12
-rw-r--r--deps/uv/test/test-spawn.c10
-rw-r--r--deps/uv/test/test-udp-connect.c182
-rw-r--r--deps/uv/test/test-udp-open.c81
-rw-r--r--deps/uv/test/test.gyp1
49 files changed, 1146 insertions, 200 deletions
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index 25447eb0e6..2c1d8ae685 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -369,3 +369,5 @@ Kevin Adler <kadler@us.ibm.com>
Stephen Belanger <admin@stephenbelanger.com>
yeyuanfeng <yeyuanfeng@bytedance.com>
erw7 <erw7.github@gmail.com>
+Thomas Karl Pietrowski <thopiekar@gmail.com>
+evgley <evgley@gmail.com>
diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt
index 5dc61eb825..01a7c47e57 100644
--- a/deps/uv/CMakeLists.txt
+++ b/deps/uv/CMakeLists.txt
@@ -153,6 +153,7 @@ set(uv_test_sources
test/test-tty.c
test/test-udp-alloc-cb-fail.c
test/test-udp-bind.c
+ test/test-udp-connect.c
test/test-udp-create-socket-early.c
test/test-udp-dgram-too-big.c
test/test-udp-ipv6.c
@@ -351,7 +352,8 @@ target_link_libraries(uv_a ${uv_libraries})
if(BUILD_TESTING)
include(CTest)
add_executable(uv_run_tests ${uv_test_sources})
- target_compile_definitions(uv_run_tests PRIVATE ${uv_defines})
+ target_compile_definitions(uv_run_tests
+ PRIVATE ${uv_defines} USING_UV_SHARED=1)
target_compile_options(uv_run_tests PRIVATE ${uv_cflags})
target_include_directories(uv_run_tests PRIVATE include)
target_link_libraries(uv_run_tests uv ${uv_test_libraries})
@@ -383,7 +385,7 @@ if(UNIX)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
- install(FILES LICENSE ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index 7f02045e03..62d6073d7d 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,3 +1,62 @@
+2019.03.17, Version 1.27.0 (Stable), a4fc9a66cc35256dbc4dcd67c910174f05b6daa6
+
+Changes since version 1.26.0:
+
+* doc: describe unix signal handling better (Vladimír Čunát)
+
+* linux: use statx() to obtain file birth time (Ben Noordhuis)
+
+* src: fill sockaddr_in6.sin6_len when it's defined (Santiago Gimeno)
+
+* test: relax uv_hrtime() test assumptions (Ben Noordhuis)
+
+* build: make cmake install LICENSE only once (Thomas Karl Pietrowski)
+
+* bsd: plug uv_fs_event_start() error path fd leak (Ben Noordhuis)
+
+* unix: fix __FreeBSD_kernel__ typo (cjihrig)
+
+* doc: add note about uv_run() not being reentrant (Ben Noordhuis)
+
+* unix, win: make fs-poll close wait for resource cleanup (Anna Henningsen)
+
+* doc: fix typo in uv_thread_options_t definition (Ryan Liptak)
+
+* win: skip winsock initialization in safe mode (evgley)
+
+* unix: refactor getsockname/getpeername methods (Santiago Gimeno)
+
+* win,udp: allow to use uv_udp_open on bound sockets (Santiago Gimeno)
+
+* udp: add support for UDP connected sockets (Santiago Gimeno)
+
+* build: fix uv_test shared uv Windows cmake build (ptlomholt)
+
+* build: add android-configure scripts to EXTRA_DIST (Ben Noordhuis)
+
+* build: add missing header (cjihrig)
+
+* sunos: add perror() output prior to abort() (Andrew Paprocki)
+
+* test,sunos: disable UV_DISCONNECT handling (Andrew Paprocki)
+
+* sunos: disable __attribute__((unused)) (Andrew Paprocki)
+
+* test,sunos: use unistd.h code branch (Andrew Paprocki)
+
+* build,sunos: better handling of non-GCC compiler (Andrew Paprocki)
+
+* test,sunos: fix statement not reached warnings (Andrew Paprocki)
+
+* sunos: fix argument/prototype mismatch in atomics (Andrew Paprocki)
+
+* test,sunos: test-ipc.c lacks newline at EOF (Andrew Paprocki)
+
+* test: change spawn_stdin_stdout return to void (Andrew Paprocki)
+
+* test: remove call to floor() in test driver (Andrew Paprocki)
+
+
2019.02.11, Version 1.26.0 (Stable), 8669d8d3e93cddb62611b267ef62a3ddb5ba3ca0
Changes since version 1.25.0:
diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am
index 7e49d8ad0b..595a5aea03 100644
--- a/deps/uv/Makefile.am
+++ b/deps/uv/Makefile.am
@@ -32,6 +32,7 @@ libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0
libuv_la_SOURCES = src/fs-poll.c \
src/heap-inl.h \
src/idna.c \
+ src/idna.h \
src/inet.c \
src/queue.h \
src/strscpy.c \
@@ -44,10 +45,12 @@ libuv_la_SOURCES = src/fs-poll.c \
src/version.c
if SUNOS
+if GCC
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
# on other platforms complain that the argument is unused during compilation.
libuv_la_CFLAGS += -pthreads
endif
+endif
if WINNT
@@ -121,11 +124,13 @@ EXTRA_DIST = test/fixtures/empty_file \
docs \
img \
samples \
- android-configure \
+ android-configure-arm \
+ android-configure-arm64 \
+ android-configure-x86 \
+ android-configure-x86_64 \
CONTRIBUTING.md \
LICENSE \
README.md \
- checksparse.sh \
vcbuild.bat \
common.gypi \
gyp_uv.py \
@@ -138,14 +143,20 @@ check_PROGRAMS = test/run-tests
if OS390
test_run_tests_CFLAGS =
else
+if GCC
test_run_tests_CFLAGS = -Wno-long-long
+else
+test_run_tests_CFLAGS =
+endif
endif
if SUNOS
+if GCC
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
# on other platforms complain that the argument is unused during compilation.
test_run_tests_CFLAGS += -pthreads
endif
+endif
test_run_tests_LDFLAGS =
test_run_tests_SOURCES = test/blackhole-server.c \
@@ -281,6 +292,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-tty.c \
test/test-udp-alloc-cb-fail.c \
test/test-udp-bind.c \
+ test/test-udp-connect.c \
test/test-udp-create-socket-early.c \
test/test-udp-dgram-too-big.c \
test/test-udp-ipv6.c \
@@ -320,7 +332,9 @@ test_run_tests_CFLAGS += -D_GNU_SOURCE
endif
if SUNOS
-test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
+test_run_tests_CFLAGS += -D__EXTENSIONS__ \
+ -D_XOPEN_SOURCE=500 \
+ -D_REENTRANT
endif
if OS390
@@ -458,7 +472,9 @@ endif
if SUNOS
uvinclude_HEADERS += include/uv/sunos.h
-libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
+libuv_la_CFLAGS += -D__EXTENSIONS__ \
+ -D_XOPEN_SOURCE=500 \
+ -D_REENTRANT
libuv_la_SOURCES += src/unix/no-proctitle.c \
src/unix/sunos.c
endif
diff --git a/deps/uv/README.md b/deps/uv/README.md
index fb5971d3e3..4e92a8174a 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -312,7 +312,7 @@ $ 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
+$ source ./android-configure-arm ~/android-ndk-r15b gyp 21
$ make -C out
```
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index 931ac3e361..336e55b15f 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.26.0], [https://github.com/libuv/libuv/issues])
+AC_INIT([libuv], [1.27.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
@@ -24,16 +24,18 @@ AC_ENABLE_SHARED
AC_ENABLE_STATIC
AC_PROG_CC
AM_PROG_CC_C_O
-AS_IF([AS_CASE([$host_os],[openedition*], [false], [true])], [
- CC_CHECK_CFLAGS_APPEND([-pedantic])
-])
CC_FLAG_VISIBILITY #[-fvisibility=hidden]
CC_CHECK_CFLAGS_APPEND([-g])
-CC_CHECK_CFLAGS_APPEND([-std=gnu89])
-CC_CHECK_CFLAGS_APPEND([-Wall])
-CC_CHECK_CFLAGS_APPEND([-Wextra])
-CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
-CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes])
+AS_IF([test "x$GCC" = xyes], [
+ AS_IF([AS_CASE([$host_os], [openedition*], [false], [true])], [
+ CC_CHECK_CFLAGS_APPEND([-pedantic])
+ ])
+ CC_CHECK_CFLAGS_APPEND([-std=gnu89])
+ CC_CHECK_CFLAGS_APPEND([-Wall])
+ CC_CHECK_CFLAGS_APPEND([-Wextra])
+ CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
+ CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes])
+])
# AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12.
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
# autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR.
@@ -50,6 +52,7 @@ AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([sendfile], [sendfile])
AC_CHECK_LIB([socket], [socket])
AC_SYS_LARGEFILE
+AM_CONDITIONAL([GCC], [AS_IF([test "x$GCC" = xyes], [true], [false])])
AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])])
AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])])
AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])])
diff --git a/deps/uv/docs/src/loop.rst b/deps/uv/docs/src/loop.rst
index 86a99adf5d..d642ac1d2f 100644
--- a/deps/uv/docs/src/loop.rst
+++ b/deps/uv/docs/src/loop.rst
@@ -107,6 +107,8 @@ API
or requests left), or non-zero if more callbacks are expected (meaning
you should run the event loop again sometime in the future).
+ :c:func:`uv_run` is not reentrant. It must not be called from a callback.
+
.. c:function:: int uv_loop_alive(const uv_loop_t* loop)
Returns non-zero if there are referenced active handles, active
diff --git a/deps/uv/docs/src/signal.rst b/deps/uv/docs/src/signal.rst
index f52b64706a..f5a809ab0b 100644
--- a/deps/uv/docs/src/signal.rst
+++ b/deps/uv/docs/src/signal.rst
@@ -6,7 +6,10 @@
Signal handles implement Unix style signal handling on a per-event loop bases.
-Reception of some signals is emulated on Windows:
+Windows notes
+-------------
+
+Reception of some signals is emulated:
* SIGINT is normally delivered when the user presses CTRL+C. However, like
on Unix, it is not generated when terminal raw mode is enabled.
@@ -24,13 +27,22 @@ Reception of some signals is emulated on Windows:
* 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
- manage threads. Installing watchers for those signals will lead to unpredictable behavior
- and is strongly discouraged. Future versions of libuv may simply reject them.
-
.. versionchanged:: 1.15.0 SIGWINCH support on Windows was improved.
+Unix notes
+----------
+
+* SIGKILL and SIGSTOP are impossible to catch.
+
+* Handling SIGBUS, SIGFPE, SIGILL or SIGSEGV via libuv results into undefined behavior.
+
+* SIGABRT will not be caught by libuv if generated by `abort()`, e.g. through `assert()`.
+
+* On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads library to
+ manage threads. Installing watchers for those signals will lead to unpredictable behavior
+ and is strongly discouraged. Future versions of libuv may simply reject them.
+
+
Data types
----------
diff --git a/deps/uv/docs/src/threading.rst b/deps/uv/docs/src/threading.rst
index a5759a38a6..7ca1d4b7a5 100644
--- a/deps/uv/docs/src/threading.rst
+++ b/deps/uv/docs/src/threading.rst
@@ -61,13 +61,13 @@ Threads
::
- typedef struct uv_process_options_s {
+ typedef struct uv_thread_options_s {
enum {
UV_THREAD_NO_FLAGS = 0x00,
UV_THREAD_HAS_STACK_SIZE = 0x01
} flags;
size_t stack_size;
- } uv_process_options_t;
+ } uv_thread_options_t;
More fields may be added to this struct at any time, so its exact
layout and size should not be relied upon.
diff --git a/deps/uv/docs/src/udp.rst b/deps/uv/docs/src/udp.rst
index 8148828522..f3de53fbab 100644
--- a/deps/uv/docs/src/udp.rst
+++ b/deps/uv/docs/src/udp.rst
@@ -150,6 +150,44 @@ API
:returns: 0 on success, or an error code < 0 on failure.
+.. c:function:: int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr)
+
+ Associate the UDP handle to a remote address and port, so every
+ message sent by this handle is automatically sent to that destination.
+ Calling this function with a `NULL` `addr` disconnects the handle.
+ Trying to call `uv_udp_connect()` on an already connected handle will result
+ in an `UV_EISCONN` error. Trying to disconnect a handle that is not
+ connected will return an `UV_ENOTCONN` error.
+
+ :param handle: UDP handle. Should have been initialized with
+ :c:func:`uv_udp_init`.
+
+ :param addr: `struct sockaddr_in` or `struct sockaddr_in6`
+ with the address and port to associate to.
+
+ :returns: 0 on success, or an error code < 0 on failure.
+
+ .. versionadded:: 1.27.0
+
+.. c:function:: int uv_udp_getpeername(const uv_udp_t* handle, struct sockaddr* name, int* namelen)
+
+ Get the remote IP and port of the UDP handle on connected UDP handles.
+ On unconnected handles, it returns `UV_ENOTCONN`.
+
+ :param handle: UDP handle. Should have been initialized with
+ :c:func:`uv_udp_init` and bound.
+
+ :param name: Pointer to the structure to be filled with the address data.
+ In order to support IPv4 and IPv6 `struct sockaddr_storage` should be
+ used.
+
+ :param namelen: On input it indicates the data of the `name` field. On
+ output it indicates how much of it was filled.
+
+ :returns: 0 on success, or an error code < 0 on failure
+
+ .. versionadded:: 1.27.0
+
.. c:function:: int uv_udp_getsockname(const uv_udp_t* handle, struct sockaddr* name, int* namelen)
Get the local IP and port of the UDP handle.
@@ -247,6 +285,12 @@ API
(``0.0.0.0`` or ``::``) it will be changed to point to ``localhost``.
This is done to match the behavior of Linux systems.
+ For connected UDP handles, `addr` must be set to `NULL`, otherwise it will
+ return `UV_EISCONN` error.
+
+ For connectionless UDP handles, `addr` cannot be `NULL`, otherwise it will
+ return `UV_EDESTADDRREQ` error.
+
:param req: UDP request handle. Need not be initialized.
:param handle: UDP handle. Should have been initialized with
@@ -266,15 +310,25 @@ API
.. versionchanged:: 1.19.0 added ``0.0.0.0`` and ``::`` to ``localhost``
mapping
+ .. versionchanged:: 1.27.0 added support for connected sockets
+
.. c:function:: int uv_udp_try_send(uv_udp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr* addr)
Same as :c:func:`uv_udp_send`, but won't queue a send request if it can't
be completed immediately.
+ For connected UDP handles, `addr` must be set to `NULL`, otherwise it will
+ return `UV_EISCONN` error.
+
+ For connectionless UDP handles, `addr` cannot be `NULL`, otherwise it will
+ return `UV_EDESTADDRREQ` error.
+
:returns: >= 0: number of bytes sent (it matches the given buffer size).
< 0: negative error code (``UV_EAGAIN`` is returned when the message
can't be sent immediately).
+ .. versionchanged:: 1.27.0 added support for connected sockets
+
.. c:function:: int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb)
Prepare for receiving data. If the socket has not previously been bound
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index 1578bbd568..43895ac80d 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -630,7 +630,11 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned int flags);
+UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr);
+UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle,
+ struct sockaddr* name,
+ int* namelen);
UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen);
diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h
index fa7320cf4d..4f65398307 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 26
+#define UV_VERSION_MINOR 27
#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c
index 6c82dfc1d7..40cb147e8d 100644
--- a/deps/uv/src/fs-poll.c
+++ b/deps/uv/src/fs-poll.c
@@ -22,12 +22,20 @@
#include "uv.h"
#include "uv-common.h"
+#ifdef _WIN32
+#include "win/internal.h"
+#include "win/handle-inl.h"
+#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
+#else
+#include "unix/internal.h"
+#endif
+
#include <assert.h>
#include <stdlib.h>
#include <string.h>
struct poll_ctx {
- uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */
+ uv_fs_poll_t* parent_handle;
int busy_polling;
unsigned int interval;
uint64_t start_time;
@@ -36,6 +44,7 @@ struct poll_ctx {
uv_timer_t timer_handle;
uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */
uv_stat_t statbuf;
+ struct poll_ctx* previous; /* context from previous start()..stop() period */
char path[1]; /* variable length */
};
@@ -49,6 +58,7 @@ static uv_stat_t zero_statbuf;
int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
+ handle->poll_ctx = NULL;
return 0;
}
@@ -62,7 +72,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
size_t len;
int err;
- if (uv__is_active(handle))
+ if (uv_is_active((uv_handle_t*)handle))
return 0;
loop = handle->loop;
@@ -90,6 +100,8 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
if (err < 0)
goto error;
+ if (handle->poll_ctx != NULL)
+ ctx->previous = handle->poll_ctx;
handle->poll_ctx = ctx;
uv__handle_start(handle);
@@ -104,19 +116,17 @@ error:
int uv_fs_poll_stop(uv_fs_poll_t* handle) {
struct poll_ctx* ctx;
- if (!uv__is_active(handle))
+ if (!uv_is_active((uv_handle_t*)handle))
return 0;
ctx = handle->poll_ctx;
assert(ctx != NULL);
- assert(ctx->parent_handle != NULL);
- ctx->parent_handle = NULL;
- handle->poll_ctx = NULL;
+ assert(ctx->parent_handle == handle);
/* Close the timer if it's active. If it's inactive, there's a stat request
* in progress and poll_cb will take care of the cleanup.
*/
- if (uv__is_active(&ctx->timer_handle))
+ if (uv_is_active((uv_handle_t*)&ctx->timer_handle))
uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
uv__handle_stop(handle);
@@ -129,7 +139,7 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
struct poll_ctx* ctx;
size_t required_len;
- if (!uv__is_active(handle)) {
+ if (!uv_is_active((uv_handle_t*)handle)) {
*size = 0;
return UV_EINVAL;
}
@@ -153,6 +163,9 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
void uv__fs_poll_close(uv_fs_poll_t* handle) {
uv_fs_poll_stop(handle);
+
+ if (handle->poll_ctx == NULL)
+ uv__make_close_pending((uv_handle_t*)handle);
}
@@ -173,14 +186,13 @@ static void poll_cb(uv_fs_t* req) {
uv_stat_t* statbuf;
struct poll_ctx* ctx;
uint64_t interval;
+ uv_fs_poll_t* handle;
ctx = container_of(req, struct poll_ctx, fs_req);
+ handle = ctx->parent_handle;
- if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */
- uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
- uv_fs_req_cleanup(req);
- return;
- }
+ if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle))
+ goto out;
if (req->result != 0) {
if (ctx->busy_polling != req->result) {
@@ -205,7 +217,7 @@ static void poll_cb(uv_fs_t* req) {
out:
uv_fs_req_cleanup(req);
- if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */
+ if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle)) {
uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
return;
}
@@ -219,8 +231,27 @@ out:
}
-static void timer_close_cb(uv_handle_t* handle) {
- uv__free(container_of(handle, struct poll_ctx, timer_handle));
+static void timer_close_cb(uv_handle_t* timer) {
+ struct poll_ctx* ctx;
+ struct poll_ctx* it;
+ struct poll_ctx* last;
+ uv_fs_poll_t* handle;
+
+ ctx = container_of(timer, struct poll_ctx, timer_handle);
+ handle = ctx->parent_handle;
+ if (ctx == handle->poll_ctx) {
+ handle->poll_ctx = ctx->previous;
+ if (handle->poll_ctx == NULL)
+ uv__make_close_pending((uv_handle_t*)handle);
+ } else {
+ for (last = handle->poll_ctx, it = last->previous;
+ it != ctx;
+ last = it, it = it->previous) {
+ assert(last->previous != NULL);
+ }
+ last->previous = ctx->previous;
+ }
+ uv__free(ctx);
}
diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h
index 7cac1f9889..fb46978859 100644
--- a/deps/uv/src/unix/atomic-ops.h
+++ b/deps/uv/src/unix/atomic-ops.h
@@ -49,7 +49,7 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
else
return op4;
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
- return atomic_cas_uint(ptr, oldval, newval);
+ return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif
@@ -85,7 +85,7 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
else
return op4;
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
- return atomic_cas_ulong(ptr, oldval, newval);
+ return atomic_cas_ulong((ulong_t *)ptr, (ulong_t)oldval, (ulong_t)newval);
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 7e42337b9a..ca0e345da0 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -161,7 +161,9 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
case UV_FS_POLL:
uv__fs_poll_close((uv_fs_poll_t*)handle);
- break;
+ /* Poll handles use file system requests, and one of them may still be
+ * running. The poll code will call uv__make_close_pending() for us. */
+ return;
case UV_SIGNAL:
uv__signal_close((uv_signal_t*) handle);
@@ -1405,3 +1407,25 @@ error:
buffer->machine[0] = '\0';
return r;
}
+
+int uv__getsockpeername(const uv_handle_t* handle,
+ uv__peersockfunc func,
+ struct sockaddr* name,
+ int* namelen) {
+ socklen_t socklen;
+ uv_os_fd_t fd;
+ int r;
+
+ r = uv_fileno(handle, &fd);
+ if (r < 0)
+ return r;
+
+ /* sizeof(socklen_t) != sizeof(int) on some systems. */
+ socklen = (socklen_t) *namelen;
+
+ if (func(fd, name, &socklen))
+ return UV__ERR(errno);
+
+ *namelen = (int) socklen;
+ return 0;
+}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 91bb82f725..f4b4280ca0 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -47,7 +47,7 @@
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
- defined(__FreeBSD_kernel_) || \
+ defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
# define HAVE_PREADV 1
@@ -1053,10 +1053,82 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
}
+static int uv__fs_statx(int fd,
+ const char* path,
+ int is_fstat,
+ int is_lstat,
+ uv_stat_t* buf) {
+ STATIC_ASSERT(UV_ENOSYS != -1);
+#ifdef __linux__
+ static int no_statx;
+ struct uv__statx statxbuf;
+ int dirfd;
+ int flags;
+ int mode;
+ int rc;
+
+ if (no_statx)
+ return UV_ENOSYS;
+
+ dirfd = AT_FDCWD;
+ flags = 0; /* AT_STATX_SYNC_AS_STAT */
+ mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
+
+ if (is_fstat) {
+ dirfd = fd;
+ flags |= 0x1000; /* AT_EMPTY_PATH */
+ }
+
+ if (is_lstat)
+ flags |= AT_SYMLINK_NOFOLLOW;
+
+ rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
+
+ if (rc == -1) {
+ /* EPERM happens when a seccomp filter rejects the system call.
+ * Has been observed with libseccomp < 2.3.3 and docker < 18.04.
+ */
+ if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
+ return -1;
+
+ no_statx = 1;
+ return UV_ENOSYS;
+ }
+
+ buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
+ buf->st_mode = statxbuf.stx_mode;
+ buf->st_nlink = statxbuf.stx_nlink;
+ buf->st_uid = statxbuf.stx_uid;
+ buf->st_gid = statxbuf.stx_gid;
+ buf->st_rdev = statxbuf.stx_rdev_major;
+ buf->st_ino = statxbuf.stx_ino;
+ buf->st_size = statxbuf.stx_size;
+ buf->st_blksize = statxbuf.stx_blksize;
+ buf->st_blocks = statxbuf.stx_blocks;
+ buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
+ buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
+ buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
+ buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
+ buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
+ buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
+ buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
+ buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
+
+ return 0;
+#else
+ return UV_ENOSYS;
+#endif /* __linux__ */
+}
+
+
static int uv__fs_stat(const char *path, uv_stat_t *buf) {
struct stat pbuf;
int ret;
+ ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
+ if (ret != UV_ENOSYS)
+ return ret;
+
ret = stat(path, &pbuf);
if (ret == 0)
uv__to_stat(&pbuf, buf);
@@ -1069,6 +1141,10 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
struct stat pbuf;
int ret;
+ ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
+ if (ret != UV_ENOSYS)
+ return ret;
+
ret = lstat(path, &pbuf);
if (ret == 0)
uv__to_stat(&pbuf, buf);
@@ -1081,6 +1157,10 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) {
struct stat pbuf;
int ret;
+ ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
+ if (ret != UV_ENOSYS)
+ return ret;
+
ret = fstat(fd, &pbuf);
if (ret == 0)
uv__to_stat(&pbuf, buf);
diff --git a/deps/uv/src/unix/getaddrinfo.c b/deps/uv/src/unix/getaddrinfo.c
index 6d23fbe02a..d7ca7d1a44 100644
--- a/deps/uv/src/unix/getaddrinfo.c
+++ b/deps/uv/src/unix/getaddrinfo.c
@@ -92,7 +92,9 @@ int uv__getaddrinfo_translate_error(int sys_err) {
}
assert(!"unknown EAI_* error code");
abort();
+#ifndef __SUNPRO_C
return 0; /* Pacify compiler. */
+#endif
}
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index c059893a46..a084697032 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -95,8 +95,7 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
*/
#if defined(__clang__) || \
defined(__GNUC__) || \
- defined(__INTEL_COMPILER) || \
- defined(__SUNPRO_C)
+ defined(__INTEL_COMPILER)
# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
# define UV_UNUSED(declaration) __attribute__((unused)) declaration
#else
@@ -306,4 +305,11 @@ UV_UNUSED(static char* uv__basename_r(const char* path)) {
int uv__inotify_fork(uv_loop_t* loop, void* old_watchers);
#endif
+typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
+
+int uv__getsockpeername(const uv_handle_t* handle,
+ uv__peersockfunc func,
+ struct sockaddr* name,
+ int* namelen);
+
#endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index 38c88d7da7..092005161f 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -490,8 +490,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
return UV__ERR(errno);
handle->path = uv__strdup(path);
- if (handle->path == NULL)
+ if (handle->path == NULL) {
+ uv__close_nocheckstdio(fd);
return UV_ENOMEM;
+ }
+
handle->cb = cb;
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c
index bfd7544879..beaba4ed9a 100644
--- a/deps/uv/src/unix/linux-syscalls.c
+++ b/deps/uv/src/unix/linux-syscalls.c
@@ -187,6 +187,21 @@
# endif
#endif /* __NR_pwritev */
+#ifndef __NR_statx
+# if defined(__x86_64__)
+# define __NR_statx 332
+# elif defined(__i386__)
+# define __NR_statx 383
+# elif defined(__aarch64__)
+# define __NR_statx 397
+# elif defined(__arm__)
+# define __NR_statx (UV_SYSCALL_BASE + 397)
+# elif defined(__ppc__)
+# define __NR_statx 383
+# elif defined(__s390__)
+# define __NR_statx 379
+# endif
+#endif /* __NR_statx */
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
#if defined(__i386__)
@@ -336,3 +351,16 @@ int uv__dup3(int oldfd, int newfd, int flags) {
return errno = ENOSYS, -1;
#endif
}
+
+
+int uv__statx(int dirfd,
+ const char* path,
+ int flags,
+ unsigned int mask,
+ struct uv__statx* statxbuf) {
+#if defined(__NR_statx)
+ return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h
index 3dfd329d6c..7e58bfa218 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -80,6 +80,36 @@
#define UV__IN_DELETE_SELF 0x400
#define UV__IN_MOVE_SELF 0x800
+struct uv__statx_timestamp {
+ int64_t tv_sec;
+ uint32_t tv_nsec;
+ int32_t unused0;
+};
+
+struct uv__statx {
+ uint32_t stx_mask;
+ uint32_t stx_blksize;
+ uint64_t stx_attributes;
+ uint32_t stx_nlink;
+ uint32_t stx_uid;
+ uint32_t stx_gid;
+ uint16_t stx_mode;
+ uint16_t unused0;
+ uint64_t stx_ino;
+ uint64_t stx_size;
+ uint64_t stx_blocks;
+ uint64_t stx_attributes_mask;
+ struct uv__statx_timestamp stx_atime;
+ struct uv__statx_timestamp stx_btime;
+ struct uv__statx_timestamp stx_ctime;
+ struct uv__statx_timestamp stx_mtime;
+ uint32_t stx_rdev_major;
+ uint32_t stx_rdev_minor;
+ uint32_t stx_dev_major;
+ uint32_t stx_dev_minor;
+ uint64_t unused1[14];
+};
+
struct uv__inotify_event {
int32_t wd;
uint32_t mask;
@@ -113,5 +143,10 @@ int uv__sendmmsg(int fd,
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);
+int uv__statx(int dirfd,
+ const char* path,
+ int flags,
+ unsigned int mask,
+ struct uv__statx* statxbuf);
#endif /* UV_LINUX_SYSCALL_H_ */
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index 228d158800..8347668632 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -233,9 +233,6 @@ out:
}
-typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
-
-
static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
uv__peersockfunc func,
char* buffer,
@@ -246,10 +243,13 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
addrlen = sizeof(sa);
memset(&sa, 0, addrlen);
- err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
+ err = uv__getsockpeername((const uv_handle_t*) handle,
+ func,
+ (struct sockaddr*) &sa,
+ (int*) &addrlen);
if (err < 0) {
*size = 0;
- return UV__ERR(errno);
+ return err;
}
#if defined(__linux__)
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index 75501f7a0a..fb6b070fd1 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -135,8 +135,10 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
return UV__ERR(errno);
- if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
+ if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) {
+ perror("(libuv) port_dissociate()");
abort();
+ }
return 0;
}
@@ -174,8 +176,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w = QUEUE_DATA(q, uv__io_t, watcher_queue);
assert(w->pevents != 0);
- if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0))
+ if (port_associate(loop->backend_fd,
+ PORT_SOURCE_FD,
+ w->fd,
+ w->pevents,
+ 0)) {
+ perror("(libuv) port_associate()");
abort();
+ }
w->events = w->pevents;
}
@@ -219,10 +227,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
/* Work around another kernel bug: port_getn() may return events even
* on error.
*/
- if (errno == EINTR || errno == ETIME)
+ if (errno == EINTR || errno == ETIME) {
saved_errno = errno;
- else
+ } else {
+ perror("(libuv) port_getn()");
abort();
+ }
}
/* Update loop->time unconditionally. It's tempting to skip the update when
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index 900839a99d..8cedcd6027 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -82,7 +82,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
handle->flags |= flags;
return 0;
}
-
+
/* Query to see if tcp socket is bound. */
slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
@@ -283,44 +283,28 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
int uv_tcp_getsockname(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
- socklen_t socklen;
if (handle->delayed_error)
return handle->delayed_error;
- if (uv__stream_fd(handle) < 0)
- return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
-
- /* sizeof(socklen_t) != sizeof(int) on some systems. */
- socklen = (socklen_t) *namelen;
-
- if (getsockname(uv__stream_fd(handle), name, &socklen))
- return UV__ERR(errno);
-
- *namelen = (int) socklen;
- return 0;
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getsockname,
+ name,
+ namelen);
}
int uv_tcp_getpeername(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
- socklen_t socklen;
if (handle->delayed_error)
return handle->delayed_error;
- if (uv__stream_fd(handle) < 0)
- return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
-
- /* sizeof(socklen_t) != sizeof(int) on some systems. */
- socklen = (socklen_t) *namelen;
-
- if (getpeername(uv__stream_fd(handle), name, &socklen))
- return UV__ERR(errno);
-
- *namelen = (int) socklen;
- return 0;
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getpeername,
+ name,
+ namelen);
}
diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c
index c17a51fed2..6088c77f71 100644
--- a/deps/uv/src/unix/thread.c
+++ b/deps/uv/src/unix/thread.c
@@ -801,7 +801,9 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
return UV_ETIMEDOUT;
abort();
+#ifndef __SUNPRO_C
return UV_EINVAL; /* Satisfy the compiler. */
+#endif
}
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index ec337ec8b8..15fa5937b3 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -227,9 +227,14 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
assert(req != NULL);
memset(&h, 0, sizeof h);
- h.msg_name = &req->addr;
- h.msg_namelen = (req->addr.ss_family == AF_INET6 ?
- sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
+ if (req->addr.ss_family == AF_UNSPEC) {
+ h.msg_name = NULL;
+ h.msg_namelen = 0;
+ } else {
+ h.msg_name = &req->addr;
+ h.msg_namelen = req->addr.ss_family == AF_INET6 ?
+ sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+ }
h.msg_iov = (struct iovec*) req->bufs;
h.msg_iovlen = req->nbufs;
@@ -383,6 +388,50 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
}
+int uv__udp_connect(uv_udp_t* handle,
+ const struct sockaddr* addr,
+ unsigned int addrlen) {
+ int err;
+
+ err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+ if (err)
+ return err;
+
+ do {
+ errno = 0;
+ err = connect(handle->io_watcher.fd, addr, addrlen);
+ } while (err == -1 && errno == EINTR);
+
+ if (err)
+ return UV__ERR(errno);
+
+ handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+ return 0;
+}
+
+
+int uv__udp_disconnect(uv_udp_t* handle) {
+ int r;
+ struct sockaddr addr;
+
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sa_family = AF_UNSPEC;
+
+ do {
+ errno = 0;
+ r = connect(handle->io_watcher.fd, &addr, sizeof(addr));
+ } while (r == -1 && errno == EINTR);
+
+ if (r == -1 && errno != EAFNOSUPPORT)
+ return UV__ERR(errno);
+
+ handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
+ return 0;
+}
+
+
int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
@@ -395,9 +444,11 @@ int uv__udp_send(uv_udp_send_t* req,
assert(nbufs > 0);
- err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
- if (err)
- return err;
+ if (addr) {
+ err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+ if (err)
+ return err;
+ }
/* It's legal for send_queue_count > 0 even when the write_queue is empty;
* it means there are error-state requests in the write_completed_queue that
@@ -407,7 +458,10 @@ int uv__udp_send(uv_udp_send_t* req,
uv__req_init(handle->loop, req, UV_UDP_SEND);
assert(addrlen <= sizeof(req->addr));
- memcpy(&req->addr, addr, addrlen);
+ if (addr == NULL)
+ req->addr.ss_family = AF_UNSPEC;
+ else
+ memcpy(&req->addr, addr, addrlen);
req->send_cb = send_cb;
req->handle = handle;
req->nbufs = nbufs;
@@ -459,9 +513,13 @@ int uv__udp_try_send(uv_udp_t* handle,
if (handle->send_queue_count != 0)
return UV_EAGAIN;
- err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
- if (err)
- return err;
+ if (addr) {
+ err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+ if (err)
+ return err;
+ } else {
+ assert(handle->flags & UV_HANDLE_UDP_CONNECTED);
+ }
memset(&h, 0, sizeof h);
h.msg_name = (struct sockaddr*) addr;
@@ -608,6 +666,7 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
uv__io_init(&handle->io_watcher, uv__udp_io, fd);
QUEUE_INIT(&handle->write_queue);
QUEUE_INIT(&handle->write_completed_queue);
+
return 0;
}
@@ -636,6 +695,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
return err;
handle->io_watcher.fd = sock;
+ if (uv__udp_is_connected(handle))
+ handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
return 0;
}
@@ -743,13 +805,17 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
IPV6_UNICAST_HOPS,
&ttl,
sizeof(ttl));
-#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
- defined(__MVS__) */
+
+#else /* !(defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
+ defined(__MVS__)) */
return uv__setsockopt_maybe_char(handle,
IP_TTL,
IPV6_UNICAST_HOPS,
ttl);
+
+#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
+ defined(__MVS__) */
}
@@ -851,23 +917,24 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
return 0;
}
-
-int uv_udp_getsockname(const uv_udp_t* handle,
+int uv_udp_getpeername(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen) {
- socklen_t socklen;
- if (handle->io_watcher.fd == -1)
- return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
-
- /* sizeof(socklen_t) != sizeof(int) on some systems. */
- socklen = (socklen_t) *namelen;
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getpeername,
+ name,
+ namelen);
+}
- if (getsockname(handle->io_watcher.fd, name, &socklen))
- return UV__ERR(errno);
+int uv_udp_getsockname(const uv_udp_t* handle,
+ struct sockaddr* name,
+ int* namelen) {
- *namelen = (int) socklen;
- return 0;
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getsockname,
+ name,
+ namelen);
}
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index 952bde080c..94dd59fb07 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -222,6 +222,9 @@ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
memset(addr, 0, sizeof(*addr));
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(port);
+#ifdef SIN6_LEN
+ addr->sin6_len = sizeof(*addr);
+#endif
zone_index = strchr(ip, '%');
if (zone_index != NULL) {
@@ -314,17 +317,20 @@ int uv_tcp_connect(uv_connect_t* req,
}
-int uv_udp_send(uv_udp_send_t* req,
- uv_udp_t* handle,
- const uv_buf_t bufs[],
- unsigned int nbufs,
- const struct sockaddr* addr,
- uv_udp_send_cb send_cb) {
+int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
unsigned int addrlen;
if (handle->type != UV_UDP)
return UV_EINVAL;
+ /* Disconnect the handle */
+ if (addr == NULL) {
+ if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
+ return UV_ENOTCONN;
+
+ return uv__udp_disconnect(handle);
+ }
+
if (addr->sa_family == AF_INET)
addrlen = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6)
@@ -332,6 +338,66 @@ int uv_udp_send(uv_udp_send_t* req,
else
return UV_EINVAL;
+ if (handle->flags & UV_HANDLE_UDP_CONNECTED)
+ return UV_EISCONN;
+
+ return uv__udp_connect(handle, addr, addrlen);
+}
+
+
+int uv__udp_is_connected(uv_udp_t* handle) {
+ struct sockaddr_storage addr;
+ int addrlen;
+ if (handle->type != UV_UDP)
+ return 0;
+
+ addrlen = sizeof(addr);
+ if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
+ return 0;
+
+ return addrlen > 0;
+}
+
+
+int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
+ unsigned int addrlen;
+
+ if (handle->type != UV_UDP)
+ return UV_EINVAL;
+
+ if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
+ return UV_EISCONN;
+
+ if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
+ return UV_EDESTADDRREQ;
+
+ if (addr != NULL) {
+ if (addr->sa_family == AF_INET)
+ addrlen = sizeof(struct sockaddr_in);
+ else if (addr->sa_family == AF_INET6)
+ addrlen = sizeof(struct sockaddr_in6);
+ else
+ return UV_EINVAL;
+ } else {
+ addrlen = 0;
+ }
+
+ return addrlen;
+}
+
+
+int uv_udp_send(uv_udp_send_t* req,
+ uv_udp_t* handle,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
+ const struct sockaddr* addr,
+ uv_udp_send_cb send_cb) {
+ int addrlen;
+
+ addrlen = uv__udp_check_before_send(handle, addr);
+ if (addrlen < 0)
+ return addrlen;
+
return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
}
@@ -340,17 +406,11 @@ int uv_udp_try_send(uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr* addr) {
- unsigned int addrlen;
-
- if (handle->type != UV_UDP)
- return UV_EINVAL;
+ int addrlen;
- if (addr->sa_family == AF_INET)
- addrlen = sizeof(struct sockaddr_in);
- else if (addr->sa_family == AF_INET6)
- addrlen = sizeof(struct sockaddr_in6);
- else
- return UV_EINVAL;
+ addrlen = uv__udp_check_before_send(handle, addr);
+ if (addrlen < 0)
+ return addrlen;
return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
}
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index 15ac4d02c1..e09a57b2c2 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -103,6 +103,7 @@ enum {
/* Only used by uv_udp_t handles. */
UV_HANDLE_UDP_PROCESSING = 0x01000000,
+ UV_HANDLE_UDP_CONNECTED = 0x02000000,
/* Only used by uv_pipe_t handles. */
UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000,
@@ -142,6 +143,14 @@ int uv__udp_bind(uv_udp_t* handle,
unsigned int addrlen,
unsigned int flags);
+int uv__udp_connect(uv_udp_t* handle,
+ const struct sockaddr* addr,
+ unsigned int addrlen);
+
+int uv__udp_disconnect(uv_udp_t* handle);
+
+int uv__udp_is_connected(uv_udp_t* handle);
+
int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
diff --git a/deps/uv/src/uv-data-getter-setters.c b/deps/uv/src/uv-data-getter-setters.c
index b7fcd4a7fd..c3025662fa 100644
--- a/deps/uv/src/uv-data-getter-setters.c
+++ b/deps/uv/src/uv-data-getter-setters.c
@@ -36,7 +36,7 @@ const char* uv_req_type_name(uv_req_type type) {
case UV_REQ_TYPE_MAX:
case UV_UNKNOWN_REQ:
default: /* UV_REQ_TYPE_PRIVATE */
- return NULL;
+ break;
}
return NULL;
}
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index bf80d77e27..e9d0a58153 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -623,3 +623,30 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
return 0;
}
+
+int uv_cpumask_size(void) {
+ return (int)(sizeof(DWORD_PTR) * 8);
+}
+
+int uv__getsockpeername(const uv_handle_t* handle,
+ uv__peersockfunc func,
+ struct sockaddr* name,
+ int* namelen,
+ int delayed_error) {
+
+ int result;
+ uv_os_fd_t fd;
+
+ result = uv_fileno(handle, &fd);
+ if (result != 0)
+ return result;
+
+ if (delayed_error)
+ return uv_translate_sys_error(delayed_error);
+
+ result = func((SOCKET) fd, name, namelen);
+ if (result != 0)
+ return uv_translate_sys_error(WSAGetLastError());
+
+ return 0;
+}
diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c
index 9d76c3f542..61e4df61b3 100644
--- a/deps/uv/src/win/handle.c
+++ b/deps/uv/src/win/handle.c
@@ -139,7 +139,6 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
case UV_FS_POLL:
uv__fs_poll_close((uv_fs_poll_t*) handle);
uv__handle_closing(handle);
- uv_want_endgame(loop, handle);
return;
default:
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index 634b9f776c..70ddaa5332 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -272,6 +272,14 @@ int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
+typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);
+
+int uv__getsockpeername(const uv_handle_t* handle,
+ uv__peersockfunc func,
+ struct sockaddr* name,
+ int* namelen,
+ int delayed_error);
+
/*
* Process stdio handles.
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index 3ce5548c0a..f2cb5271b8 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -809,44 +809,24 @@ static int uv_tcp_try_connect(uv_connect_t* req,
int uv_tcp_getsockname(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
- int result;
-
- if (handle->socket == INVALID_SOCKET) {
- return UV_EINVAL;
- }
-
- if (handle->delayed_error) {
- return uv_translate_sys_error(handle->delayed_error);
- }
-
- result = getsockname(handle->socket, name, namelen);
- if (result != 0) {
- return uv_translate_sys_error(WSAGetLastError());
- }
- return 0;
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getsockname,
+ name,
+ namelen,
+ handle->delayed_error);
}
int uv_tcp_getpeername(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
- int result;
-
- if (handle->socket == INVALID_SOCKET) {
- return UV_EINVAL;
- }
-
- if (handle->delayed_error) {
- return uv_translate_sys_error(handle->delayed_error);
- }
-
- result = getpeername(handle->socket, name, namelen);
- if (result != 0) {
- return uv_translate_sys_error(WSAGetLastError());
- }
- return 0;
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getpeername,
+ name,
+ namelen,
+ handle->delayed_error);
}
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index 37df849f8f..8aeeab3b46 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -36,22 +36,27 @@ const unsigned int uv_active_udp_streams_threshold = 0;
/* A zero-size buffer for use by uv_udp_read */
static char uv_zero_[] = "";
-
-int uv_udp_getsockname(const uv_udp_t* handle,
+int uv_udp_getpeername(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen) {
- int result;
- if (handle->socket == INVALID_SOCKET) {
- return UV_EINVAL;
- }
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getpeername,
+ name,
+ namelen,
+ 0);
+}
- result = getsockname(handle->socket, name, namelen);
- if (result != 0) {
- return uv_translate_sys_error(WSAGetLastError());
- }
- return 0;
+int uv_udp_getsockname(const uv_udp_t* handle,
+ struct sockaddr* name,
+ int* namelen) {
+
+ return uv__getsockpeername((const uv_handle_t*) handle,
+ getsockname,
+ name,
+ namelen,
+ 0);
}
@@ -784,6 +789,18 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
}
+int uv__udp_is_bound(uv_udp_t* handle) {
+ struct sockaddr_storage addr;
+ int addrlen;
+
+ addrlen = sizeof(addr);
+ if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
+ return 0;
+
+ return addrlen > 0;
+}
+
+
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
WSAPROTOCOL_INFOW protocol_info;
int opt_len;
@@ -803,7 +820,16 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
handle,
sock,
protocol_info.iAddressFamily);
- return uv_translate_sys_error(err);
+ if (err)
+ return uv_translate_sys_error(err);
+
+ if (uv__udp_is_bound(handle))
+ handle->flags |= UV_HANDLE_BOUND;
+
+ if (uv__udp_is_connected(handle))
+ handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+ return 0;
}
@@ -880,6 +906,50 @@ int uv__udp_bind(uv_udp_t* handle,
}
+int uv__udp_connect(uv_udp_t* handle,
+ const struct sockaddr* addr,
+ unsigned int addrlen) {
+ const struct sockaddr* bind_addr;
+ int err;
+
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ if (addrlen == sizeof(uv_addr_ip4_any_))
+ bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
+ else if (addrlen == sizeof(uv_addr_ip6_any_))
+ bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
+ else
+ return UV_EINVAL;
+
+ err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+ if (err)
+ return uv_translate_sys_error(err);
+ }
+
+ err = connect(handle->socket, addr, addrlen);
+ if (err)
+ return uv_translate_sys_error(err);
+
+ handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+ return 0;
+}
+
+
+int uv__udp_disconnect(uv_udp_t* handle) {
+ int err;
+ struct sockaddr addr;
+
+ memset(&addr, 0, sizeof(addr));
+
+ err = connect(handle->socket, &addr, sizeof(addr));
+ if (err)
+ return uv_translate_sys_error(err);
+
+ handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
+ return 0;
+}
+
+
/* This function is an egress point, i.e. it returns libuv errors rather than
* system errors.
*/
@@ -900,6 +970,7 @@ int uv__udp_send(uv_udp_send_t* req,
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
else
return UV_EINVAL;
+
err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
@@ -925,9 +996,11 @@ int uv__udp_try_send(uv_udp_t* handle,
assert(nbufs > 0);
- err = uv__convert_to_localhost_if_unspecified(addr, &converted);
- if (err)
- return err;
+ if (addr != NULL) {
+ err = uv__convert_to_localhost_if_unspecified(addr, &converted);
+ if (err)
+ return err;
+ }
/* Already sending a message.*/
if (handle->send_queue_count != 0)
diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c
index 5e7da2a8f2..5820ba9c66 100644
--- a/deps/uv/src/win/winsock.c
+++ b/deps/uv/src/win/winsock.c
@@ -87,12 +87,6 @@ void uv_winsock_init(void) {
WSAPROTOCOL_INFOW protocol_info;
int opt_len;
- /* Initialize winsock */
- errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
- if (errorno != 0) {
- uv_fatal_error(errorno, "WSAStartup");
- }
-
/* Set implicit binding address used by connectEx */
if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) {
abort();
@@ -102,6 +96,15 @@ void uv_winsock_init(void) {
abort();
}
+ /* Skip initialization in safe mode without network support */
+ if (1 == GetSystemMetrics(SM_CLEANBOOT)) return;
+
+ /* Initialize winsock */
+ errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
+ if (errorno != 0) {
+ uv_fatal_error(errorno, "WSAStartup");
+ }
+
/* Detect non-IFS LSPs */
dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c
index eba28ecb9a..55cf412827 100644
--- a/deps/uv/test/run-tests.c
+++ b/deps/uv/test/run-tests.c
@@ -44,7 +44,7 @@ int ipc_send_recv_helper(void);
int ipc_helper_bind_twice(void);
int ipc_helper_send_zero(void);
int stdio_over_pipes_helper(void);
-int spawn_stdin_stdout(void);
+void spawn_stdin_stdout(void);
int spawn_tcp_server_helper(void);
static int maybe_run_test(int argc, char **argv);
@@ -67,7 +67,9 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
+#ifndef __SUNPRO_C
return EXIT_SUCCESS;
+#endif
}
@@ -209,7 +211,8 @@ static int maybe_run_test(int argc, char **argv) {
if (strcmp(argv[1], "spawn_helper9") == 0) {
notify_parent_process();
- return spawn_stdin_stdout();
+ spawn_stdin_stdout();
+ return 1;
}
#ifndef _WIN32
diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h
index 282c02d50c..8462e0ddbd 100644
--- a/deps/uv/test/task.h
+++ b/deps/uv/test/task.h
@@ -174,8 +174,7 @@ extern int snprintf(char*, size_t, const char*, ...);
#if defined(__clang__) || \
defined(__GNUC__) || \
- defined(__INTEL_COMPILER) || \
- defined(__SUNPRO_C)
+ defined(__INTEL_COMPILER)
# define UNUSED __attribute__((unused))
#else
# define UNUSED
diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c
index eadff542bc..7b6511c93c 100644
--- a/deps/uv/test/test-fs-copyfile.c
+++ b/deps/uv/test/test-fs-copyfile.c
@@ -23,7 +23,8 @@
#include "task.h"
#if defined(__unix__) || defined(__POSIX__) || \
- defined(__APPLE__) || defined(_AIX) || defined(__MVS__)
+ defined(__APPLE__) || defined(__sun) || \
+ defined(_AIX) || defined(__MVS__)
#include <unistd.h> /* unlink, etc. */
#else
# include <direct.h>
diff --git a/deps/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c
index 737d50dfd2..e19a68780f 100644
--- a/deps/uv/test/test-fs-poll.c
+++ b/deps/uv/test/test-fs-poll.c
@@ -185,3 +185,77 @@ TEST_IMPL(fs_poll_getpath) {
MAKE_VALGRIND_HAPPY();
return 0;
}
+
+
+TEST_IMPL(fs_poll_close_request) {
+ uv_loop_t loop;
+ uv_fs_poll_t poll_handle;
+
+ remove(FIXTURE);
+
+ ASSERT(0 == uv_loop_init(&loop));
+
+ ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
+ ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
+ uv_close((uv_handle_t*) &poll_handle, close_cb);
+ while (close_cb_called == 0)
+ uv_run(&loop, UV_RUN_ONCE);
+ ASSERT(close_cb_called == 1);
+
+ ASSERT(0 == uv_loop_close(&loop));
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+TEST_IMPL(fs_poll_close_request_multi_start_stop) {
+ uv_loop_t loop;
+ uv_fs_poll_t poll_handle;
+ int i;
+
+ remove(FIXTURE);
+
+ ASSERT(0 == uv_loop_init(&loop));
+
+ ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
+
+ for (i = 0; i < 10; ++i) {
+ ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
+ ASSERT(0 == uv_fs_poll_stop(&poll_handle));
+ }
+ uv_close((uv_handle_t*) &poll_handle, close_cb);
+ while (close_cb_called == 0)
+ uv_run(&loop, UV_RUN_ONCE);
+ ASSERT(close_cb_called == 1);
+
+ ASSERT(0 == uv_loop_close(&loop));
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+TEST_IMPL(fs_poll_close_request_multi_stop_start) {
+ uv_loop_t loop;
+ uv_fs_poll_t poll_handle;
+ int i;
+
+ remove(FIXTURE);
+
+ ASSERT(0 == uv_loop_init(&loop));
+
+ ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
+
+ for (i = 0; i < 10; ++i) {
+ ASSERT(0 == uv_fs_poll_stop(&poll_handle));
+ ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
+ }
+ uv_close((uv_handle_t*) &poll_handle, close_cb);
+ while (close_cb_called == 0)
+ uv_run(&loop, UV_RUN_ONCE);
+ ASSERT(close_cb_called == 1);
+
+ ASSERT(0 == uv_loop_close(&loop));
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c
index 5eed160de2..35f7d0c3f1 100644
--- a/deps/uv/test/test-fs.c
+++ b/deps/uv/test/test-fs.c
@@ -30,7 +30,8 @@
/* FIXME we shouldn't need to branch in this file */
#if defined(__unix__) || defined(__POSIX__) || \
- defined(__APPLE__) || defined(_AIX) || defined(__MVS__)
+ defined(__APPLE__) || defined(__sun) || \
+ defined(_AIX) || defined(__MVS__)
#include <unistd.h> /* unlink, rmdir, etc. */
#else
# include <winioctl.h>
@@ -1248,6 +1249,16 @@ TEST_IMPL(fs_fstat) {
#endif
#endif
+#if defined(__linux__)
+ /* If statx() is supported, the birth time should be equal to the change time
+ * because we just created the file. On older kernels, it's set to zero.
+ */
+ ASSERT(s->st_birthtim.tv_sec == 0 ||
+ s->st_birthtim.tv_sec == t.st_ctim.tv_sec);
+ ASSERT(s->st_birthtim.tv_nsec == 0 ||
+ s->st_birthtim.tv_nsec == t.st_ctim.tv_nsec);
+#endif
+
uv_fs_req_cleanup(&req);
/* Now do the uv_fs_fstat call asynchronously */
diff --git a/deps/uv/test/test-hrtime.c b/deps/uv/test/test-hrtime.c
index fbe9a68bfc..9d461d9623 100644
--- a/deps/uv/test/test-hrtime.c
+++ b/deps/uv/test/test-hrtime.c
@@ -41,13 +41,11 @@ TEST_IMPL(hrtime) {
diff = b - a;
- /* printf("i= %d diff = %llu\n", i, (unsigned long long int) diff); */
-
/* The windows Sleep() function has only a resolution of 10-20 ms. Check
- * that the difference between the two hrtime values is somewhat in the
- * range we expect it to be. */
+ * that the difference between the two hrtime values has a reasonable
+ * lower bound.
+ */
ASSERT(diff > (uint64_t) 25 * NANOSEC / MILLISEC);
- ASSERT(diff < (uint64_t) 80 * NANOSEC / MILLISEC);
--i;
}
return 0;
diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c
index 88d04ba143..24c067e0a4 100644
--- a/deps/uv/test/test-ipc.c
+++ b/deps/uv/test/test-ipc.c
@@ -971,4 +971,4 @@ int ipc_helper_send_zero(void) {
MAKE_VALGRIND_HAPPY();
return 0;
-} \ No newline at end of file
+}
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index d81416fad2..f498c7dc81 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -132,6 +132,7 @@ TEST_DECLARE (tcp_write_ready)
TEST_DECLARE (udp_alloc_cb_fail)
TEST_DECLARE (udp_bind)
TEST_DECLARE (udp_bind_reuseaddr)
+TEST_DECLARE (udp_connect)
TEST_DECLARE (udp_create_early)
TEST_DECLARE (udp_create_early_bad_bind)
TEST_DECLARE (udp_create_early_bad_domain)
@@ -152,6 +153,8 @@ TEST_DECLARE (udp_options6)
TEST_DECLARE (udp_no_autobind)
TEST_DECLARE (udp_open)
TEST_DECLARE (udp_open_twice)
+TEST_DECLARE (udp_open_bound)
+TEST_DECLARE (udp_open_connect)
TEST_DECLARE (udp_try_send)
TEST_DECLARE (pipe_bind_error_addrinuse)
TEST_DECLARE (pipe_bind_error_addrnotavail)
@@ -280,6 +283,9 @@ TEST_DECLARE (spawn_quoted_path)
TEST_DECLARE (spawn_tcp_server)
TEST_DECLARE (fs_poll)
TEST_DECLARE (fs_poll_getpath)
+TEST_DECLARE (fs_poll_close_request)
+TEST_DECLARE (fs_poll_close_request_multi_start_stop)
+TEST_DECLARE (fs_poll_close_request_multi_stop_start)
TEST_DECLARE (kill)
TEST_DECLARE (kill_invalid_signum)
TEST_DECLARE (fs_file_noent)
@@ -619,6 +625,7 @@ TASK_LIST_START
TEST_ENTRY (udp_alloc_cb_fail)
TEST_ENTRY (udp_bind)
TEST_ENTRY (udp_bind_reuseaddr)
+ TEST_ENTRY (udp_connect)
TEST_ENTRY (udp_create_early)
TEST_ENTRY (udp_create_early_bad_bind)
TEST_ENTRY (udp_create_early_bad_domain)
@@ -642,6 +649,9 @@ TASK_LIST_START
TEST_ENTRY (udp_open)
TEST_HELPER (udp_open, udp4_echo_server)
TEST_ENTRY (udp_open_twice)
+ TEST_ENTRY (udp_open_bound)
+ TEST_ENTRY (udp_open_connect)
+ TEST_HELPER (udp_open_connect, udp4_echo_server)
TEST_ENTRY (pipe_bind_error_addrinuse)
TEST_ENTRY (pipe_bind_error_addrnotavail)
@@ -817,6 +827,9 @@ TASK_LIST_START
TEST_ENTRY (spawn_tcp_server)
TEST_ENTRY (fs_poll)
TEST_ENTRY (fs_poll_getpath)
+ TEST_ENTRY (fs_poll_close_request)
+ TEST_ENTRY (fs_poll_close_request_multi_start_stop)
+ TEST_ENTRY (fs_poll_close_request_multi_stop_start)
TEST_ENTRY (kill)
TEST_ENTRY (kill_invalid_signum)
diff --git a/deps/uv/test/test-loop-handles.c b/deps/uv/test/test-loop-handles.c
index 6471cd08b3..131098801a 100644
--- a/deps/uv/test/test-loop-handles.c
+++ b/deps/uv/test/test-loop-handles.c
@@ -320,7 +320,7 @@ TEST_IMPL(loop_handles) {
ASSERT(prepare_1_cb_called == ITERATIONS);
ASSERT(prepare_1_close_cb_called == 1);
- ASSERT(prepare_2_cb_called == floor(ITERATIONS / 2.0));
+ ASSERT(prepare_2_cb_called == ITERATIONS / 2);
ASSERT(prepare_2_close_cb_called == 1);
ASSERT(check_cb_called == ITERATIONS);
diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c
index 0d1b1d7ec9..cc2b5fbe59 100644
--- a/deps/uv/test/test-poll.c
+++ b/deps/uv/test/test-poll.c
@@ -82,9 +82,9 @@ static int closed_connections = 0;
static int valid_writable_wakeups = 0;
static int spurious_writable_wakeups = 0;
-#if !defined(_AIX) && !defined(__MVS__)
+#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
static int disconnects = 0;
-#endif /* !_AIX && !__MVS__ */
+#endif /* !__sun && !_AIX && !__MVS__ */
static int got_eagain(void) {
#ifdef _WIN32
@@ -391,7 +391,7 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
new_events &= ~UV_WRITABLE;
}
}
-#if !defined(_AIX) && !defined(__MVS__)
+#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
if (events & UV_DISCONNECT) {
context->got_disconnect = 1;
++disconnects;
@@ -399,9 +399,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
}
if (context->got_fin && context->sent_fin && context->got_disconnect) {
-#else /* _AIX && __MVS__ */
+#else /* __sun && _AIX && __MVS__ */
if (context->got_fin && context->sent_fin) {
-#endif /* !_AIX && !__MVS__ */
+#endif /* !__sun && !_AIX && !__MVS__ */
/* Sent and received FIN. Close and destroy context. */
close_socket(context->sock);
destroy_connection_context(context);
@@ -569,7 +569,7 @@ static void start_poll_test(void) {
spurious_writable_wakeups > 20);
ASSERT(closed_connections == NUM_CLIENTS * 2);
-#if !defined(_AIX) && !defined(__MVS__)
+#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
ASSERT(disconnects == NUM_CLIENTS * 2);
#endif
MAKE_VALGRIND_HAPPY();
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index 05c76f6145..e5fc308a0e 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/test/test-spawn.c
@@ -1838,7 +1838,7 @@ TEST_IMPL(spawn_quoted_path) {
/* Helper for child process of spawn_inherit_streams */
#ifndef _WIN32
-int spawn_stdin_stdout(void) {
+void spawn_stdin_stdout(void) {
char buf[1024];
char* pbuf;
for (;;) {
@@ -1847,7 +1847,7 @@ int spawn_stdin_stdout(void) {
r = read(0, buf, sizeof buf);
} while (r == -1 && errno == EINTR);
if (r == 0) {
- return 1;
+ return;
}
ASSERT(r > 0);
c = r;
@@ -1861,10 +1861,9 @@ int spawn_stdin_stdout(void) {
c = c - w;
}
}
- return 2;
}
#else
-int spawn_stdin_stdout(void) {
+void spawn_stdin_stdout(void) {
char buf[1024];
char* pbuf;
HANDLE h_stdin = GetStdHandle(STD_INPUT_HANDLE);
@@ -1877,7 +1876,7 @@ int spawn_stdin_stdout(void) {
DWORD to_write;
if (!ReadFile(h_stdin, buf, sizeof buf, &n_read, NULL)) {
ASSERT(GetLastError() == ERROR_BROKEN_PIPE);
- return 1;
+ return;
}
to_write = n_read;
pbuf = buf;
@@ -1887,6 +1886,5 @@ int spawn_stdin_stdout(void) {
pbuf += n_written;
}
}
- return 2;
}
#endif /* !_WIN32 */
diff --git a/deps/uv/test/test-udp-connect.c b/deps/uv/test/test-udp-connect.c
new file mode 100644
index 0000000000..f44634248f
--- /dev/null
+++ b/deps/uv/test/test-udp-connect.c
@@ -0,0 +1,182 @@
+/* Copyright libuv project and 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"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CHECK_HANDLE(handle) \
+ ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client)
+
+static uv_udp_t server;
+static uv_udp_t client;
+static uv_buf_t buf;
+static struct sockaddr_in lo_addr;
+
+static int cl_send_cb_called;
+static int sv_recv_cb_called;
+
+static int close_cb_called;
+
+
+static void alloc_cb(uv_handle_t* handle,
+ size_t suggested_size,
+ uv_buf_t* buf) {
+ static char slab[65536];
+ CHECK_HANDLE(handle);
+ ASSERT(suggested_size <= sizeof(slab));
+ buf->base = slab;
+ buf->len = sizeof(slab);
+}
+
+
+static void close_cb(uv_handle_t* handle) {
+ CHECK_HANDLE(handle);
+ ASSERT(uv_is_closing(handle));
+ close_cb_called++;
+}
+
+
+static void cl_send_cb(uv_udp_send_t* req, int status) {
+ int r;
+
+ ASSERT(req != NULL);
+ ASSERT(status == 0);
+ CHECK_HANDLE(req->handle);
+ if (++cl_send_cb_called == 1) {
+ uv_udp_connect(&client, NULL);
+ r = uv_udp_send(req, &client, &buf, 1, NULL, cl_send_cb);
+ ASSERT(r == UV_EDESTADDRREQ);
+ r = uv_udp_send(req,
+ &client,
+ &buf,
+ 1,
+ (const struct sockaddr*) &lo_addr,
+ cl_send_cb);
+ ASSERT(r == 0);
+ }
+
+}
+
+
+static void sv_recv_cb(uv_udp_t* handle,
+ ssize_t nread,
+ const uv_buf_t* rcvbuf,
+ const struct sockaddr* addr,
+ unsigned flags) {
+ if (nread > 0) {
+ ASSERT(nread == 4);
+ ASSERT(addr != NULL);
+ ASSERT(memcmp("EXIT", rcvbuf->base, nread) == 0);
+ if (++sv_recv_cb_called == 4) {
+ uv_close((uv_handle_t*) &server, close_cb);
+ uv_close((uv_handle_t*) &client, close_cb);
+ }
+ }
+}
+
+
+TEST_IMPL(udp_connect) {
+ uv_udp_send_t req;
+ struct sockaddr_in ext_addr;
+ struct sockaddr_in tmp_addr;
+ int r;
+ int addrlen;
+
+ ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &lo_addr));
+
+ r = uv_udp_init(uv_default_loop(), &server);
+ ASSERT(r == 0);
+
+ r = uv_udp_bind(&server, (const struct sockaddr*) &lo_addr, 0);
+ ASSERT(r == 0);
+
+ r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);
+ ASSERT(r == 0);
+
+ r = uv_udp_init(uv_default_loop(), &client);
+ ASSERT(r == 0);
+
+ buf = uv_buf_init("EXIT", 4);
+
+ ASSERT(0 == uv_ip4_addr("8.8.8.8", TEST_PORT, &ext_addr));
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &lo_addr));
+
+ r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);
+ ASSERT(r == 0);
+ r = uv_udp_connect(&client, (const struct sockaddr*) &ext_addr);
+ ASSERT(r == UV_EISCONN);
+
+ addrlen = sizeof(tmp_addr);
+ r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);
+ ASSERT(r == 0);
+
+ /* To send messages in connected UDP sockets addr must be NULL */
+ r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);
+ ASSERT(r == UV_EISCONN);
+ r = uv_udp_try_send(&client, &buf, 1, NULL);
+ ASSERT(r == 4);
+ r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &ext_addr);
+ ASSERT(r == UV_EISCONN);
+
+ r = uv_udp_connect(&client, NULL);
+ ASSERT(r == 0);
+ r = uv_udp_connect(&client, NULL);
+ ASSERT(r == UV_ENOTCONN);
+
+ addrlen = sizeof(tmp_addr);
+ r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);
+ ASSERT(r == UV_ENOTCONN);
+
+ /* To send messages in disconnected UDP sockets addr must be set */
+ r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);
+ ASSERT(r == 4);
+ r = uv_udp_try_send(&client, &buf, 1, NULL);
+ ASSERT(r == UV_EDESTADDRREQ);
+
+
+ r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);
+ ASSERT(r == 0);
+ r = uv_udp_send(&req,
+ &client,
+ &buf,
+ 1,
+ (const struct sockaddr*) &lo_addr,
+ cl_send_cb);
+ ASSERT(r == UV_EISCONN);
+ r = uv_udp_send(&req, &client, &buf, 1, NULL, cl_send_cb);
+ ASSERT(r == 0);
+
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ ASSERT(close_cb_called == 2);
+ ASSERT(sv_recv_cb_called == 4);
+ ASSERT(cl_send_cb_called == 2);
+
+ ASSERT(client.send_queue_size == 0);
+ ASSERT(server.send_queue_size == 0);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-udp-open.c b/deps/uv/test/test-udp-open.c
index ee04c99f61..0390bae2e5 100644
--- a/deps/uv/test/test-udp-open.c
+++ b/deps/uv/test/test-udp-open.c
@@ -129,6 +129,7 @@ static void send_cb(uv_udp_send_t* req, int status) {
ASSERT(status == 0);
send_cb_called++;
+ uv_close((uv_handle_t*)req->handle, close_cb);
}
@@ -215,3 +216,83 @@ TEST_IMPL(udp_open_twice) {
MAKE_VALGRIND_HAPPY();
return 0;
}
+
+TEST_IMPL(udp_open_bound) {
+ struct sockaddr_in addr;
+ uv_udp_t client;
+ uv_os_sock_t sock;
+ int r;
+
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
+
+ startup();
+ sock = create_udp_socket();
+
+ r = bind(sock, (struct sockaddr*) &addr, sizeof(addr));
+ ASSERT(r == 0);
+
+ r = uv_udp_init(uv_default_loop(), &client);
+ ASSERT(r == 0);
+
+ r = uv_udp_open(&client, sock);
+ ASSERT(r == 0);
+
+ r = uv_udp_recv_start(&client, alloc_cb, recv_cb);
+ ASSERT(r == 0);
+
+ uv_close((uv_handle_t*) &client, NULL);
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+TEST_IMPL(udp_open_connect) {
+ struct sockaddr_in addr;
+ uv_buf_t buf = uv_buf_init("PING", 4);
+ uv_udp_t client;
+ uv_udp_t server;
+ uv_os_sock_t sock;
+ int r;
+
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
+
+ startup();
+ sock = create_udp_socket();
+
+ r = uv_udp_init(uv_default_loop(), &client);
+ ASSERT(r == 0);
+
+ r = connect(sock, (const struct sockaddr*) &addr, sizeof(addr));
+ ASSERT(r == 0);
+
+ r = uv_udp_open(&client, sock);
+ ASSERT(r == 0);
+
+ r = uv_udp_init(uv_default_loop(), &server);
+ ASSERT(r == 0);
+
+ r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
+ ASSERT(r == 0);
+
+ r = uv_udp_recv_start(&server, alloc_cb, recv_cb);
+ ASSERT(r == 0);
+
+ r = uv_udp_send(&send_req,
+ &client,
+ &buf,
+ 1,
+ NULL,
+ send_cb);
+ ASSERT(r == 0);
+
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ ASSERT(send_cb_called == 1);
+ ASSERT(close_cb_called == 2);
+
+ ASSERT(client.send_queue_size == 0);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp
index 8fc6cca140..9c13e25dde 100644
--- a/deps/uv/test/test.gyp
+++ b/deps/uv/test/test.gyp
@@ -137,6 +137,7 @@
'test-tty.c',
'test-udp-alloc-cb-fail.c',
'test-udp-bind.c',
+ 'test-udp-connect.c',
'test-udp-create-socket-early.c',
'test-udp-dgram-too-big.c',
'test-udp-ipv6.c',