summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSaúl Ibarra Corretgé <saghul@gmail.com>2015-02-24 11:05:39 +0100
committerJulien Gilli <julien.gilli@joyent.com>2015-03-06 11:37:40 -0800
commitdcff5d565c000904cabf48c627534a779a40527a (patch)
tree9f7fddde118c2da099b23cc0272e09036fbe1e5f
parent8bcd0a4c4a8e3d748bea53d036985609ea634b8d (diff)
downloadnode-dcff5d565c000904cabf48c627534a779a40527a.tar.gz
deps: update libuv to 0.10.36
PR: #9274 PR-URL: https://github.com/joyent/node/pull/9274 Reviewed-By: Julien Gilli <julien.gilli@joyent.com>
-rw-r--r--deps/uv/AUTHORS3
-rw-r--r--deps/uv/ChangeLog70
-rw-r--r--deps/uv/build.mk2
-rwxr-xr-xdeps/uv/checksparse.sh1
-rw-r--r--deps/uv/config-unix.mk4
-rw-r--r--deps/uv/include/uv-private/uv-win.h5
-rw-r--r--deps/uv/src/unix/async.c43
-rw-r--r--deps/uv/src/unix/atomic-ops.h60
-rw-r--r--deps/uv/src/unix/internal.h15
-rw-r--r--deps/uv/src/unix/linux-core.c40
-rw-r--r--deps/uv/src/unix/linux-syscalls.c6
-rw-r--r--deps/uv/src/unix/linux-syscalls.h2
-rw-r--r--deps/uv/src/unix/process.c15
-rw-r--r--deps/uv/src/unix/stream.c13
-rw-r--r--deps/uv/src/version.c2
-rw-r--r--deps/uv/src/win/dl.c35
-rw-r--r--deps/uv/src/win/fs.c4
-rw-r--r--deps/uv/src/win/internal.h4
-rw-r--r--deps/uv/src/win/poll.c40
-rw-r--r--deps/uv/src/win/winsock.c12
-rw-r--r--deps/uv/test/test-dlerror.c19
-rw-r--r--deps/uv/test/test-list.h10
-rw-r--r--deps/uv/test/test-loop-configure.c40
-rw-r--r--deps/uv/test/test-poll-close-doesnt-corrupt-stack.c114
-rw-r--r--deps/uv/test/test-tcp-oob.c137
-rw-r--r--deps/uv/uv.gyp4
26 files changed, 595 insertions, 105 deletions
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index 48a74db32..1123dd8ec 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -132,3 +132,6 @@ Javier Hernández <jhernandez@emergya.com>
Tonis Tiigi <tonistiigi@gmail.com>
Michael Hudson-Doyle <michael.hudson@linaro.org>
Helge Deller <deller@gmx.de>
+Logan Rosen <loganrosen@gmail.com>
+Kenneth Perry <thothonegan@gmail.com>
+Michael Penick <michael.penick@datastax.com>
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index 4ba348d57..bd03d53b5 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,4 +1,72 @@
-2014.12.10, Version 0.10.30 (Stable)
+2015.02.27, Version 0.10.36 (Stable)
+
+Changes since version 0.10.35:
+
+* stream: ignore EINVAL for SO_OOBINLINE on OS X (Fedor Indutny)
+
+
+2015.02.25, Version 0.10.35 (Stable), 4dc978825d870643bbaa4660f71d22975efba29e
+
+Changes since version 0.10.34:
+
+* stream: use SO_OOBINLINE on OS X (Fedor Indutny)
+
+
+2015.02.21, Version 0.10.34 (Stable), 37aa4aa9b9712c778d7b249563e868cabfdb8332
+
+Changes since version 0.10.33:
+
+* unix: add atomic-ops.h (Ben Noordhuis)
+
+* unix: fix for uv_async data race (Michael Penick)
+
+* unix: call setgoups before calling setuid/setgid (Saúl Ibarra Corretgé)
+
+
+2015.01.29, Version 0.10.33 (Stable), 7a2253d33ad8215a26c1b34f1952aee7242dd687
+
+Changes since version 0.10.32:
+
+* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis)
+
+* test: back-port uv_loop_configure() test (Ben Noordhuis)
+
+
+2015.01.06, Version 0.10.32 (Stable), 378de30c59aef5fdb6d130fa5cfcb0a68fce571c
+
+Changes since version 0.10.31:
+
+* linux: fix epoll_pwait() sigmask size calculation (Ben Noordhuis)
+
+
+2014.12.25, Version 0.10.31 (Stable), 4dbd27e2219069a6daa769fb37f98673b77b4261
+
+Changes since version 0.10.30:
+
+* test: test that closing a poll handle doesn't corrupt the stack (Bert Belder)
+
+* win: fix compilation of tests (Marc Schlaich)
+
+* Revert "win: keep a reference to AFD_POLL_INFO in cancel poll" (Bert Belder)
+
+* win: avoid stack corruption when closing a poll handle (Bert Belder)
+
+* gitignore: ignore Visual Studio files (Marc Schlaich)
+
+* win: set fallback message if FormatMessage fails (Marc Schlaich)
+
+* win: fall back to default language in uv_dlerror (Marc Schlaich)
+
+* test: improve compatibility for dlerror test (Marc Schlaich)
+
+* test: check dlerror is "no error" in no error case (Marc Schlaich)
+
+* build: link against -pthread (Logan Rosen)
+
+* win: scandir use 'ls' for formatting long strings (Kenneth Perry)
+
+
+2014.12.10, Version 0.10.30 (Stable), 5a63f5e9546dca482eeebc3054139b21f509f21f
Changes since version 0.10.29:
diff --git a/deps/uv/build.mk b/deps/uv/build.mk
index a2fdac7d4..efa42e1bc 100644
--- a/deps/uv/build.mk
+++ b/deps/uv/build.mk
@@ -91,6 +91,7 @@ TESTS= \
test/test-ipc-send-recv.o \
test/test-loop-handles.o \
test/test-loop-stop.o \
+ test/test-loop-configure.o \
test/test-multiple-listen.o \
test/test-mutexes.o \
test/test-osx-select.o \
@@ -126,6 +127,7 @@ TESTS= \
test/test-tcp-connect-timeout.o \
test/test-tcp-flags.o \
test/test-tcp-open.o \
+ test/test-tcp-oob.o \
test/test-tcp-read-stop.o \
test/test-tcp-shutdown-after-write.o \
test/test-tcp-unexpected-read.o \
diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh
index 01fac07a3..d2b1d5e05 100755
--- a/deps/uv/checksparse.sh
+++ b/deps/uv/checksparse.sh
@@ -145,6 +145,7 @@ test/test-tcp-open.c
test/test-tcp-read-stop.c
test/test-tcp-shutdown-after-write.c
test/test-tcp-unexpected-read.c
+test/test-tcp-oob.c
test/test-tcp-write-error.c
test/test-tcp-write-to-half-open-connection.c
test/test-tcp-writealot.c
diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk
index 37c4a72f6..db21daa0b 100644
--- a/deps/uv/config-unix.mk
+++ b/deps/uv/config-unix.mk
@@ -22,7 +22,7 @@ E=
CSTDFLAG=--std=c89 -pedantic -Wall -Wextra -Wno-unused-parameter
CFLAGS += -g
CPPFLAGS += -I$(SRCDIR)/src
-LDFLAGS=-lm
+LDFLAGS=-lm -pthread
CPPFLAGS += -D_LARGEFILE_SOURCE
CPPFLAGS += -D_FILE_OFFSET_BITS=64
@@ -186,7 +186,7 @@ src/.buildstamp src/unix/.buildstamp test/.buildstamp:
mkdir -p $(@D)
touch $@
-src/unix/%.o src/unix/%.pic.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h src/unix/.buildstamp $(DTRACE_HEADER)
+src/unix/%.o src/unix/%.pic.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/atomic-ops.h src/unix/internal.h src/unix/.buildstamp $(DTRACE_HEADER)
$(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
src/%.o src/%.pic.o: src/%.c include/uv.h include/uv-private/uv-unix.h src/.buildstamp
diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h
index e5f2f3b4c..c9ec38ef4 100644
--- a/deps/uv/include/uv-private/uv-win.h
+++ b/deps/uv/include/uv-private/uv-win.h
@@ -474,10 +474,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
/* Used in fast mode */ \
SOCKET peer_socket; \
AFD_POLL_INFO afd_poll_info_1; \
- union { \
- AFD_POLL_INFO* afd_poll_info_ptr; \
- AFD_POLL_INFO afd_poll_info; \
- } afd_poll_info_2; \
+ AFD_POLL_INFO afd_poll_info_2; \
/* Used in fast and slow mode. */ \
uv_req_t poll_req_1; \
uv_req_t poll_req_2; \
diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c
index 43f54ed4b..8adf046a6 100644
--- a/deps/uv/src/unix/async.c
+++ b/deps/uv/src/unix/async.c
@@ -24,6 +24,7 @@
#include "uv.h"
#include "internal.h"
+#include "atomic-ops.h"
#include <errno.h>
#include <assert.h>
@@ -34,7 +35,6 @@
static void uv__async_event(uv_loop_t* loop,
struct uv__async* w,
unsigned int nevents);
-static int uv__async_make_pending(int* pending);
static int uv__async_eventfd(void);
@@ -54,7 +54,11 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
int uv_async_send(uv_async_t* handle) {
- if (uv__async_make_pending(&handle->pending) == 0)
+ /* Do a cheap read first. */
+ if (ACCESS_ONCE(int, handle->pending) != 0)
+ return 0;
+
+ if (cmpxchgi(&handle->pending, 0, 1) == 0)
uv__async_send(&handle->loop->async_watcher);
return 0;
@@ -75,41 +79,12 @@ static void uv__async_event(uv_loop_t* loop,
ngx_queue_foreach(q, &loop->async_handles) {
h = ngx_queue_data(q, uv_async_t, queue);
- if (!h->pending) continue;
- h->pending = 0;
- h->async_cb(h, 0);
- }
-}
+ if (cmpxchgi(&h->pending, 1, 0) == 0)
+ continue;
-static int uv__async_make_pending(int* pending) {
- /* Do a cheap read first. */
- if (ACCESS_ONCE(int, *pending) != 0)
- return 1;
-
- /* Micro-optimization: use atomic memory operations to detect if we've been
- * preempted by another thread and don't have to make an expensive syscall.
- * This speeds up the heavily contended case by about 1-2% and has little
- * if any impact on the non-contended case.
- *
- * Use XCHG instead of the CMPXCHG that __sync_val_compare_and_swap() emits
- * on x86, it's about 4x faster. It probably makes zero difference in the
- * grand scheme of things but I'm OCD enough not to let this one pass.
- */
-#if defined(__i386__) || defined(__x86_64__)
- {
- unsigned int val = 1;
- __asm__ __volatile__ ("xchgl %0, %1"
- : "+r" (val)
- : "m" (*pending));
- return val != 0;
+ h->async_cb(h, 0);
}
-#elif defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 0)
- return __sync_val_compare_and_swap(pending, 0, 1) != 0;
-#else
- ACCESS_ONCE(int, *pending) = 1;
- return 0;
-#endif
}
diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h
new file mode 100644
index 000000000..7e4e64bed
--- /dev/null
+++ b/deps/uv/src/unix/atomic-ops.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef UV_ATOMIC_OPS_H_
+#define UV_ATOMIC_OPS_H_
+
+#include "internal.h" /* UV_UNUSED */
+
+UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
+UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval));
+UV_UNUSED(static void cpu_relax(void));
+
+/* Prefer hand-rolled assembly over the gcc builtins because the latter also
+ * issue full memory barriers.
+ */
+UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
+#if defined(__i386__) || defined(__x86_64__)
+ int out;
+ __asm__ __volatile__ ("lock; cmpxchg %2, %1;"
+ : "=a" (out), "+m" (*(volatile int*) ptr)
+ : "r" (newval), "0" (oldval)
+ : "memory");
+ return out;
+#else
+ return __sync_val_compare_and_swap(ptr, oldval, newval);
+#endif
+}
+
+UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
+#if defined(__i386__) || defined(__x86_64__)
+ long out;
+ __asm__ __volatile__ ("lock; cmpxchg %2, %1;"
+ : "=a" (out), "+m" (*(volatile long*) ptr)
+ : "r" (newval), "0" (oldval)
+ : "memory");
+ return out;
+#else
+ return __sync_val_compare_and_swap(ptr, oldval, newval);
+#endif
+}
+
+UV_UNUSED(static void cpu_relax(void)) {
+#if defined(__i386__) || defined(__x86_64__)
+ __asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */
+#endif
+}
+
+#endif /* UV_ATOMIC_OPS_H_ */
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 003e1a509..af360539e 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -66,6 +66,21 @@
} \
while (0)
+/* The __clang__ and __INTEL_COMPILER checks are superfluous because they
+ * define __GNUC__. They are here to convey to you, dear reader, that these
+ * macros are enabled when compiling with clang or icc.
+ */
+#if defined(__clang__) || \
+ defined(__GNUC__) || \
+ defined(__INTEL_COMPILER) || \
+ defined(__SUNPRO_C)
+# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
+# define UV_UNUSED(declaration) __attribute__((unused)) declaration
+#else
+# define UV_DESTRUCTOR(declaration) declaration
+# define UV_UNUSED(declaration) declaration
+#endif
+
#if defined(__linux__)
# define UV__POLLIN UV__EPOLLIN
# define UV__POLLOUT UV__EPOLLOUT
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index 47938f2b2..6cd5a7f00 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -33,7 +33,6 @@
#include <sys/prctl.h>
#include <sys/sysinfo.h>
#include <unistd.h>
-#include <signal.h>
#include <fcntl.h>
#include <time.h>
@@ -126,13 +125,15 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
void uv__io_poll(uv_loop_t* loop, int timeout) {
+ 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;
ngx_queue_t* q;
uv__io_t* w;
- sigset_t* pset;
- sigset_t set;
+ sigset_t sigset;
+ uint64_t sigmask;
uint64_t base;
uint64_t diff;
int nevents;
@@ -141,7 +142,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
int fd;
int op;
int i;
- static int no_epoll_wait;
if (loop->nfds == 0) {
assert(ngx_queue_empty(&loop->watcher_queue));
@@ -183,11 +183,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w->events = w->pevents;
}
- pset = NULL;
+ sigmask = 0;
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
- pset = &set;
- sigemptyset(pset);
- sigaddset(pset, SIGPROF);
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGPROF);
+ sigmask |= 1 << (SIGPROF - 1);
}
assert(timeout >= -1);
@@ -195,23 +195,31 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
count = 48; /* Benchmarks suggest this gives the best throughput. */
for (;;) {
- if (no_epoll_wait || pset != NULL) {
+ if (sigmask != 0 && no_epoll_pwait != 0)
+ if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
+ abort();
+
+ if (sigmask != 0 && no_epoll_pwait == 0) {
nfds = uv__epoll_pwait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout,
- pset);
+ 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) {
+ if (nfds == -1 && errno == ENOSYS)
no_epoll_wait = 1;
- continue;
- }
}
+ if (sigmask != 0 && no_epoll_pwait != 0)
+ if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
+ abort();
+
/* 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
* operating system didn't reschedule our process while in the syscall.
@@ -224,6 +232,12 @@ 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();
diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c
index c9945438f..267915d87 100644
--- a/deps/uv/src/unix/linux-syscalls.c
+++ b/deps/uv/src/unix/linux-syscalls.c
@@ -291,15 +291,15 @@ int uv__epoll_pwait(int epfd,
struct uv__epoll_event* events,
int nevents,
int timeout,
- const sigset_t* sigmask) {
+ uint64_t sigmask) {
#if defined(__NR_epoll_pwait)
return syscall(__NR_epoll_pwait,
epfd,
events,
nevents,
timeout,
- sigmask,
- _NSIG / 8);
+ &sigmask,
+ sizeof(sigmask));
#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 62eb5c5a3..7be73bb6e 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -130,7 +130,7 @@ int uv__epoll_pwait(int epfd,
struct uv__epoll_event* events,
int nevents,
int timeout,
- const sigset_t* sigmask);
+ uint64_t sigmask);
int uv__eventfd2(unsigned int count, int flags);
int uv__inotify_init(void);
int uv__inotify_init1(int flags);
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
index 19686a291..d1f9440c5 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -40,6 +40,10 @@
extern char **environ;
#endif
+#ifdef __linux__
+# include <grp.h>
+#endif
+
static ngx_queue_t* uv__process_queue(uv_loop_t* loop, int pid) {
assert(pid > 0);
@@ -331,6 +335,17 @@ static void uv__process_child_init(uv_process_options_t options,
_exit(127);
}
+ if (options.flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
+ /* When dropping privileges from root, the `setgroups` call will
+ * remove any extraneous groups. If we don't call this, then
+ * even though our uid has dropped, we may still have groups
+ * that enable us to do super-user things. This will fail if we
+ * aren't root, so don't bother checking the return value, this
+ * is just done as an optimistic privilege dropping function.
+ */
+ SAVE_ERRNO(setgroups(0, NULL));
+ }
+
if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
uv__write_int(error_fd, errno);
_exit(127);
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 81933e646..a8802c85a 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -403,6 +403,10 @@ failed_malloc:
int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
+#if defined(__APPLE__)
+ int enable;
+#endif
+
assert(fd >= 0);
stream->flags |= flags;
@@ -415,6 +419,15 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
return uv__set_sys_error(stream->loop, errno);
}
+#if defined(__APPLE__)
+ enable = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
+ errno != ENOTSOCK &&
+ errno != EINVAL) {
+ return uv__set_sys_error(stream->loop, errno);
+ }
+#endif
+
stream->io_watcher.fd = fd;
return 0;
diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c
index 1b5a1e4cd..554086606 100644
--- a/deps/uv/src/version.c
+++ b/deps/uv/src/version.c
@@ -34,7 +34,7 @@
#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 10
-#define UV_VERSION_PATCH 30
+#define UV_VERSION_PATCH 36
#define UV_VERSION_IS_RELEASE 1
diff --git a/deps/uv/src/win/dl.c b/deps/uv/src/win/dl.c
index d5b8f7c7d..f7fca81ca 100644
--- a/deps/uv/src/win/dl.c
+++ b/deps/uv/src/win/dl.c
@@ -69,17 +69,44 @@ const char* uv_dlerror(uv_lib_t* lib) {
}
+static void uv__format_fallback_error(uv_lib_t* lib, int errorno){
+ DWORD_PTR args[1] = { (DWORD_PTR) errorno };
+ LPSTR fallback_error = "error: %1!d!";
+
+ FormatMessageA(FORMAT_MESSAGE_FROM_STRING |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ fallback_error, 0, 0,
+ (LPSTR) &lib->errmsg,
+ 0, (va_list*) args);
+}
+
+
+
static int uv__dlerror(uv_lib_t* lib, int errorno) {
+ DWORD res;
+
if (lib->errmsg) {
LocalFree((void*)lib->errmsg);
lib->errmsg = NULL;
}
if (errorno) {
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
- (LPSTR)&lib->errmsg, 0, NULL);
+ res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ (LPSTR) &lib->errmsg, 0, NULL);
+ if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) {
+ res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
+ 0, (LPSTR) &lib->errmsg, 0, NULL);
+ }
+
+ if (!res) {
+ uv__format_fallback_error(lib, errorno);
+ }
}
return errorno ? -1 : 0;
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 7f3704e8a..c5a4b2b70 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -732,9 +732,9 @@ void fs__readdir(uv_fs_t* req) {
if (len == 0) {
fmt = L"./*";
} else if (pathw[len - 1] == L'/' || pathw[len - 1] == L'\\') {
- fmt = L"%s*";
+ fmt = L"%ls*";
} else {
- fmt = L"%s\\*";
+ fmt = L"%ls\\*";
}
/* Figure out whether path is a file or a directory. */
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index 9920f704a..f32d24a77 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -332,8 +332,8 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
int* addr_len, WSAOVERLAPPED *overlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
-int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
- OVERLAPPED* overlapped);
+int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
+ AFD_POLL_INFO* info_out, OVERLAPPED* overlapped);
/* Whether there are any non-IFS LSPs stacked on TCP */
extern int uv_tcp_non_ifs_lsp_ipv4;
diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c
index 5c5c7d80f..372427927 100644
--- a/deps/uv/src/win/poll.c
+++ b/deps/uv/src/win/poll.c
@@ -46,6 +46,8 @@ typedef struct uv_single_fd_set_s {
static OVERLAPPED overlapped_dummy_;
static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT;
+static AFD_POLL_INFO afd_poll_info_dummy_;
+
static void uv__init_overlapped_dummy(void) {
HANDLE event;
@@ -65,6 +67,11 @@ static OVERLAPPED* uv__get_overlapped_dummy() {
}
+static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() {
+ return &afd_poll_info_dummy_;
+}
+
+
static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
uv_req_t* req;
AFD_POLL_INFO* afd_poll_info;
@@ -79,7 +86,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
handle->mask_events_2 = handle->events;
} else if (handle->submitted_events_2 == 0) {
req = &handle->poll_req_2;
- afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[0];
+ afd_poll_info = &handle->afd_poll_info_2;
handle->submitted_events_2 = handle->events;
handle->mask_events_1 = handle->events;
handle->mask_events_2 = 0;
@@ -108,6 +115,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
result = uv_msafd_poll((SOCKET) handle->peer_socket,
afd_poll_info,
+ afd_poll_info,
&req->overlapped);
if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) {
/* Queue this req, reporting an error. */
@@ -118,19 +126,19 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
- AFD_POLL_INFO* afd_poll_info;
+ AFD_POLL_INFO afd_poll_info;
DWORD result;
- afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[1];
- afd_poll_info->Exclusive = TRUE;
- afd_poll_info->NumberOfHandles = 1;
- afd_poll_info->Timeout.QuadPart = INT64_MAX;
- afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket;
- afd_poll_info->Handles[0].Status = 0;
- afd_poll_info->Handles[0].Events = AFD_POLL_ALL;
+ afd_poll_info.Exclusive = TRUE;
+ afd_poll_info.NumberOfHandles = 1;
+ afd_poll_info.Timeout.QuadPart = INT64_MAX;
+ afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
+ afd_poll_info.Handles[0].Status = 0;
+ afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
result = uv_msafd_poll(handle->socket,
- afd_poll_info,
+ &afd_poll_info,
+ uv__get_afd_poll_info_dummy(),
uv__get_overlapped_dummy());
if (result == SOCKET_ERROR) {
@@ -155,7 +163,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
handle->submitted_events_1 = 0;
mask_events = handle->mask_events_1;
} else if (req == &handle->poll_req_2) {
- afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[0];
+ afd_poll_info = &handle->afd_poll_info_2;
handle->submitted_events_2 = 0;
mask_events = handle->mask_events_2;
} else {
@@ -552,12 +560,6 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
handle->poll_req_2.type = UV_POLL_REQ;
handle->poll_req_2.data = handle;
- handle->afd_poll_info_2.afd_poll_info_ptr = malloc(sizeof(*handle->afd_poll_info_2.afd_poll_info_ptr) * 2);
- if (handle->afd_poll_info_2.afd_poll_info_ptr == NULL) {
- uv__set_artificial_error(loop, UV_ENOMEM);
- return -1;
- }
-
return 0;
}
@@ -611,9 +613,5 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
assert(handle->submitted_events_1 == 0);
assert(handle->submitted_events_2 == 0);
- if (handle->afd_poll_info_2.afd_poll_info_ptr) {
- free(handle->afd_poll_info_2.afd_poll_info_ptr);
- handle->afd_poll_info_2.afd_poll_info_ptr = NULL;
- }
uv__handle_close(handle);
}
diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c
index cf6d03189..b91a23733 100644
--- a/deps/uv/src/win/winsock.c
+++ b/deps/uv/src/win/winsock.c
@@ -467,8 +467,8 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
}
-int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
- OVERLAPPED* overlapped) {
+int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
+ AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) {
IO_STATUS_BLOCK iosb;
IO_STATUS_BLOCK* iosb_ptr;
HANDLE event = NULL;
@@ -506,10 +506,10 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
apc_context,
iosb_ptr,
IOCTL_AFD_POLL,
- info,
- sizeof *info,
- info,
- sizeof *info);
+ info_in,
+ sizeof *info_in,
+ info_out,
+ sizeof *info_out);
if (overlapped == NULL) {
/* If this is a blocking operation, wait for the event to become */
diff --git a/deps/uv/test/test-dlerror.c b/deps/uv/test/test-dlerror.c
index 877ebf371..091200edb 100644
--- a/deps/uv/test/test-dlerror.c
+++ b/deps/uv/test/test-dlerror.c
@@ -26,31 +26,28 @@
TEST_IMPL(dlerror) {
const char* path = "test/fixtures/load_error.node";
+ const char* dlerror_no_error = "no error";
const char* msg;
uv_lib_t lib;
int r;
-#ifdef __linux__
- const char* dlerror_desc = "file too short";
-#elif defined (__sun__)
- const char* dlerror_desc = "unknown file type";
-#elif defined (_WIN32)
- const char* dlerror_desc = "%1 is not a valid Win32 application";
-#else
- const char* dlerror_desc = "";
-#endif
+ lib.errmsg = NULL;
+ lib.handle = NULL;
+ msg = uv_dlerror(&lib);
+ ASSERT(msg != NULL);
+ ASSERT(strstr(msg, dlerror_no_error) != NULL);
r = uv_dlopen(path, &lib);
ASSERT(r == -1);
msg = uv_dlerror(&lib);
ASSERT(msg != NULL);
- ASSERT(strstr(msg, dlerror_desc) != NULL);
+ ASSERT(strstr(msg, dlerror_no_error) == NULL);
/* Should return the same error twice in a row. */
msg = uv_dlerror(&lib);
ASSERT(msg != NULL);
- ASSERT(strstr(msg, dlerror_desc) != NULL);
+ ASSERT(strstr(msg, dlerror_no_error) == NULL);
uv_dlclose(&lib);
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index 474442588..0bfb9e41e 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -24,6 +24,7 @@ TEST_DECLARE (callback_order)
TEST_DECLARE (run_once)
TEST_DECLARE (run_nowait)
TEST_DECLARE (loop_stop)
+TEST_DECLARE (loop_configure)
TEST_DECLARE (barrier_1)
TEST_DECLARE (barrier_2)
TEST_DECLARE (barrier_3)
@@ -64,7 +65,10 @@ TEST_DECLARE (tcp_connect_error_fault)
TEST_DECLARE (tcp_connect_timeout)
TEST_DECLARE (tcp_close_while_connecting)
TEST_DECLARE (tcp_close)
+#ifndef _WIN32
TEST_DECLARE (tcp_close_accept)
+TEST_DECLARE (tcp_oob)
+#endif
TEST_DECLARE (tcp_flags)
TEST_DECLARE (tcp_write_to_half_open_connection)
TEST_DECLARE (tcp_unexpected_read)
@@ -215,6 +219,7 @@ TEST_DECLARE (poll_duplex)
TEST_DECLARE (poll_unidirectional)
TEST_DECLARE (poll_close)
#ifdef _WIN32
+TEST_DECLARE (poll_close_doesnt_corrupt_stack)
TEST_DECLARE (poll_closesocket)
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
TEST_DECLARE (argument_escaping)
@@ -249,6 +254,7 @@ TASK_LIST_START
TEST_ENTRY (run_once)
TEST_ENTRY (run_nowait)
TEST_ENTRY (loop_stop)
+ TEST_ENTRY (loop_configure)
TEST_ENTRY (barrier_1)
TEST_ENTRY (barrier_2)
TEST_ENTRY (barrier_3)
@@ -308,7 +314,10 @@ TASK_LIST_START
TEST_ENTRY (tcp_connect_timeout)
TEST_ENTRY (tcp_close_while_connecting)
TEST_ENTRY (tcp_close)
+#ifndef _WIN32
TEST_ENTRY (tcp_close_accept)
+ TEST_ENTRY (tcp_oob)
+#endif
TEST_ENTRY (tcp_flags)
TEST_ENTRY (tcp_write_to_half_open_connection)
TEST_ENTRY (tcp_unexpected_read)
@@ -451,6 +460,7 @@ TASK_LIST_START
TEST_ENTRY (kill)
#ifdef _WIN32
+ TEST_ENTRY (poll_close_doesnt_corrupt_stack)
TEST_ENTRY (poll_closesocket)
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
TEST_ENTRY (argument_escaping)
diff --git a/deps/uv/test/test-loop-configure.c b/deps/uv/test/test-loop-configure.c
new file mode 100644
index 000000000..9fefc5920
--- /dev/null
+++ b/deps/uv/test/test-loop-configure.c
@@ -0,0 +1,40 @@
+/* Copyright (c) 2014, Ben Noordhuis <info@bnoordhuis.nl>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+static void timer_cb(uv_timer_t* handle, int status) {
+ uv_close((uv_handle_t*) handle, NULL);
+}
+
+
+TEST_IMPL(loop_configure) {
+ uv_timer_t timer_handle;
+ uv_loop_t* loop;
+
+ loop = uv_default_loop();
+#ifdef _WIN32
+ ASSERT(UV_ENOSYS == uv_loop_configure(loop, UV_LOOP_BLOCK_SIGNAL, 0));
+#else
+ ASSERT(0 == uv_loop_configure(loop, UV_LOOP_BLOCK_SIGNAL, SIGPROF));
+#endif
+ ASSERT(0 == uv_timer_init(loop, &timer_handle));
+ ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 10, 0));
+ ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c b/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c
new file mode 100644
index 000000000..eb10507ac
--- /dev/null
+++ b/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c
@@ -0,0 +1,114 @@
+/* Copyright Bert Belder, and other libuv 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.
+ */
+
+#ifdef _WIN32
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "uv.h"
+#include "task.h"
+
+#ifdef _MSC_VER /* msvc */
+# define NO_INLINE __declspec(noinline)
+#else /* gcc */
+# define NO_INLINE __attribute__ ((noinline))
+#endif
+
+
+uv_os_sock_t sock;
+uv_poll_t handle;
+
+static int close_cb_called = 0;
+
+
+static void close_cb(uv_handle_t* h) {
+ close_cb_called++;
+}
+
+
+static void poll_cb(uv_poll_t* h, int status, int events) {
+ ASSERT(0 && "should never get here");
+}
+
+
+static void NO_INLINE close_socket_and_verify_stack() {
+ const uint32_t MARKER = 0xDEADBEEF;
+ const int VERIFY_AFTER = 10; /* ms */
+ int r;
+
+ volatile uint32_t data[65536];
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(data); i++)
+ data[i] = MARKER;
+
+ r = closesocket(sock);
+ ASSERT(r == 0);
+
+ uv_sleep(VERIFY_AFTER);
+
+ for (i = 0; i < ARRAY_SIZE(data); i++)
+ ASSERT(data[i] == MARKER);
+}
+
+
+TEST_IMPL(poll_close_doesnt_corrupt_stack) {
+ struct WSAData wsa_data;
+ int r;
+ unsigned long on;
+ struct sockaddr_in addr;
+
+ r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
+ ASSERT(r == 0);
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ ASSERT(sock != INVALID_SOCKET);
+ on = 1;
+ r = ioctlsocket(sock, FIONBIO, &on);
+ ASSERT(r == 0);
+
+ addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
+ ASSERT(r == 0);
+
+ r = connect(sock, (const struct sockaddr*) &addr, sizeof addr);
+ ASSERT(r != 0);
+ ASSERT(WSAGetLastError() == WSAEWOULDBLOCK);
+
+ r = uv_poll_init_socket(uv_default_loop(), &handle, sock);
+ ASSERT(r == 0);
+ r = uv_poll_start(&handle, UV_READABLE | UV_WRITABLE, poll_cb);
+ ASSERT(r == 0);
+
+ uv_close((uv_handle_t*) &handle, close_cb);
+
+ close_socket_and_verify_stack();
+
+ r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+
+ ASSERT(close_cb_called == 1);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+#endif /* _WIN32 */
diff --git a/deps/uv/test/test-tcp-oob.c b/deps/uv/test/test-tcp-oob.c
new file mode 100644
index 000000000..35a242041
--- /dev/null
+++ b/deps/uv/test/test-tcp-oob.c
@@ -0,0 +1,137 @@
+/* Copyright Fedor Indutny. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#if !defined(_WIN32)
+
+#include "uv.h"
+#include "task.h"
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+static uv_tcp_t server_handle;
+static uv_tcp_t client_handle;
+static uv_tcp_t peer_handle;
+static uv_idle_t idle;
+static uv_connect_t connect_req;
+static int ticks;
+static const int kMaxTicks = 10;
+
+
+static void set_nonblocking(int fd, int set) {
+ int r;
+ int flags = fcntl(fd, F_GETFL, 0);
+ ASSERT(flags >= 0);
+ if (set)
+ flags |= O_NONBLOCK;
+ else
+ flags &= ~O_NONBLOCK;
+ r = fcntl(fd, F_SETFL, flags);
+ ASSERT(r >= 0);
+}
+
+
+static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
+ static char storage[1024];
+ return uv_buf_init(storage, sizeof(storage));
+}
+
+
+static void idle_cb(uv_idle_t* idle, int status) {
+ ASSERT(status == 0);
+ if (++ticks < kMaxTicks)
+ return;
+
+ uv_close((uv_handle_t*) &server_handle, NULL);
+ uv_close((uv_handle_t*) &client_handle, NULL);
+ uv_close((uv_handle_t*) &peer_handle, NULL);
+ uv_close((uv_handle_t*) idle, NULL);
+}
+
+
+static void read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
+ ASSERT(nread > 0);
+ ASSERT(0 == uv_idle_start(&idle, idle_cb));
+}
+
+
+static void connect_cb(uv_connect_t* req, int status) {
+ ASSERT(req->handle == (uv_stream_t*) &client_handle);
+ ASSERT(0 == status);
+}
+
+
+static void connection_cb(uv_stream_t* handle, int status) {
+ int r;
+ int fd;
+
+ ASSERT(0 == status);
+ ASSERT(0 == uv_accept(handle, (uv_stream_t*) &peer_handle));
+ ASSERT(0 == uv_read_start((uv_stream_t*) &peer_handle, alloc_cb, read_cb));
+
+ /* Send some OOB data */
+ fd = client_handle.io_watcher.fd;
+ set_nonblocking(fd, 0);
+
+ /* The problem triggers only on a second message, it seem that xnu is not
+ * triggering `kevent()` for the first one
+ */
+ do {
+ r = send(fd, "hello", 5, MSG_OOB);
+ } while (r < 0 && errno == EINTR);
+ ASSERT(5 == r);
+
+ do {
+ r = send(fd, "hello", 5, MSG_OOB);
+ } while (r < 0 && errno == EINTR);
+ ASSERT(5 == r);
+
+ set_nonblocking(fd, 1);
+}
+
+
+TEST_IMPL(tcp_oob) {
+ uv_loop_t* loop;
+ loop = uv_default_loop();
+
+ ASSERT(0 == uv_tcp_init(loop, &server_handle));
+ ASSERT(0 == uv_tcp_init(loop, &client_handle));
+ ASSERT(0 == uv_tcp_init(loop, &peer_handle));
+ ASSERT(0 == uv_idle_init(loop, &idle));
+ ASSERT(0 == uv_tcp_bind(&server_handle, uv_ip4_addr("127.0.0.1", TEST_PORT)));
+ ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 1, connection_cb));
+
+ /* Ensure two separate packets */
+ ASSERT(0 == uv_tcp_nodelay(&client_handle, 1));
+
+ ASSERT(0 == uv_tcp_connect(&connect_req,
+ &client_handle,
+ uv_ip4_addr("127.0.0.1", TEST_PORT),
+ connect_cb));
+ ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+
+ ASSERT(ticks == kMaxTicks);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+#endif
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index 5af99bd59..d5d0f9407 100644
--- a/deps/uv/uv.gyp
+++ b/deps/uv/uv.gyp
@@ -133,6 +133,7 @@
'include/uv-private/uv-darwin.h',
'include/uv-private/uv-bsd.h',
'src/unix/async.c',
+ 'src/unix/atomic-ops.h',
'src/unix/core.c',
'src/unix/dl.c',
'src/unix/error.c',
@@ -311,6 +312,7 @@
'test/test-list.h',
'test/test-loop-handles.c',
'test/test-loop-stop.c',
+ 'test/test-loop-configure.c',
'test/test-walk-handles.c',
'test/test-watcher-cross-stop.c',
'test/test-multiple-listen.c',
@@ -323,6 +325,7 @@
'test/test-platform-output.c',
'test/test-poll.c',
'test/test-poll-close.c',
+ 'test/test-poll-close-doesnt-corrupt-stack.c',
'test/test-poll-closesocket.c',
'test/test-process-title.c',
'test/test-ref.c',
@@ -352,6 +355,7 @@
'test/test-tcp-write-to-half-open-connection.c',
'test/test-tcp-writealot.c',
'test/test-tcp-unexpected-read.c',
+ 'test/test-tcp-oob.c',
'test/test-tcp-read-stop.c',
'test/test-threadpool.c',
'test/test-threadpool-cancel.c',