diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index e7f8f3f59fa7ee..1eaaca8406e957 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -67,3 +67,6 @@ ipch *.xcodeproj *.xcworkspace + +# make dist output +libuv-*.tar.* diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 3a350a4b9ac0b4..0a152ba8dbb0c4 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -14,6 +14,7 @@ Isaac Z. Schlueter Justin Venus Keno Fischer Keno Fischer +Leith Bade Leonard Hecker Maciej Małecki Marc Schlaich diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index ee6595d79b75d7..6929fff222cd91 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -180,3 +180,4 @@ Alexey Melnichuk Johan Bergström Alex Mo Luis Martinez de Bartolome +Michael Penick diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index de6ecc17f2343c..79b1ac716949bd 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,23 @@ +2015.02.25, Version 1.4.1 (Stable) + +Changes since version 1.4.0: + +* win: don't use inline keyword in thread.c (Ben Noordhuis) + +* windows: fix setting dirent types on uv_fs_scandir_next (Saúl Ibarra + Corretgé) + +* unix,windows: make uv_thread_create() return errno (Ben Noordhuis) + +* tty: fix build for SmartOS (Julien Gilli) + +* unix: fix for uv_async data race (Michael Penick) + +* unix, windows: map EHOSTDOWN errno (Ben Noordhuis) + +* stream: use SO_OOBINLINE on OS X (Fedor Indutny) + + 2015.02.10, Version 1.4.0 (Stable), 19fb8a90648f3763240db004b77ab984264409be Changes since version 1.3.0: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index d7557a1b18e6c9..9c511db47a6c8f 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -222,6 +222,7 @@ test_run_tests_SOURCES = test/blackhole-server.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-to-half-open-connection.c \ test/test-tcp-write-after-connect.c \ test/test-tcp-writealot.c \ diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh index d2dc3a5982a2de..9442c202eabe68 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/configure.ac b/deps/uv/configure.ac index 56c6baedc78293..b52330f0fc7ca6 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.4.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.4.1], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/uv/docs/src/threading.rst b/deps/uv/docs/src/threading.rst index aab13f84b627b0..e876dde1256d1a 100644 --- a/deps/uv/docs/src/threading.rst +++ b/deps/uv/docs/src/threading.rst @@ -56,6 +56,9 @@ Threads ^^^^^^^ .. c:function:: int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg) + + .. versionchanged:: 1.4.1 returns a UV_E* error code on failure + .. c:function:: uv_thread_t uv_thread_self(void) .. c:function:: int uv_thread_join(uv_thread_t *tid) .. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) diff --git a/deps/uv/include/uv-errno.h b/deps/uv/include/uv-errno.h index c34132795cd6de..53f30296c1cdc4 100644 --- a/deps/uv/include/uv-errno.h +++ b/deps/uv/include/uv-errno.h @@ -399,4 +399,20 @@ # define UV__EMLINK (-4032) #endif +/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is + * defined. Fortunately, its value is always 64 so it's possible albeit + * icky to hard-code it. + */ +#if defined(EHOSTDOWN) && !defined(_WIN32) +# define UV__EHOSTDOWN (-EHOSTDOWN) +#elif defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) +# define UV__EHOSTDOWN (-64) +#else +# define UV__EHOSTDOWN (-4031) +#endif + #endif /* UV_ERRNO_H_ */ diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index 9dc34a4e09f4a4..c1a69532a11b45 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -32,7 +32,7 @@ #define UV_VERSION_MAJOR 1 #define UV_VERSION_MINOR 4 -#define UV_VERSION_PATCH 0 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h index b744d624cb2fd9..24b22b31a9562b 100644 --- a/deps/uv/include/uv-win.h +++ b/deps/uv/include/uv-win.h @@ -294,6 +294,7 @@ typedef struct uv__dirent_s { char d_name[1]; } uv__dirent_t; +#define HAVE_DIRENT_TYPES #define UV__DT_DIR UV_DIRENT_DIR #define UV__DT_FILE UV_DIRENT_FILE #define UV__DT_LINK UV_DIRENT_LINK diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 191eecacf36c1f..55f75218b58682 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -138,6 +138,7 @@ extern "C" { XX(EOF, "end of file") \ XX(ENXIO, "no such device or address") \ XX(EMLINK, "too many links") \ + XX(EHOSTDOWN, "host is down") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index b794ea6121b161..9ff24aeb3d7d87 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 #include /* snprintf() */ @@ -35,7 +36,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); @@ -58,7 +58,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; @@ -80,9 +84,8 @@ static void uv__async_event(uv_loop_t* loop, QUEUE_FOREACH(q, &loop->async_handles) { h = QUEUE_DATA(q, uv_async_t, queue); - if (h->pending == 0) + if (cmpxchgi(&h->pending, 1, 0) == 0) continue; - h->pending = 0; if (h->async_cb == NULL) continue; @@ -91,37 +94,6 @@ static void uv__async_event(uv_loop_t* loop, } -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; - } -#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 -} - - static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { struct uv__async* wa; char buf[1024]; diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index bfced40794e528..8d00838fb9dc58 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -375,6 +375,10 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { int uv__stream_open(uv_stream_t* stream, int fd, int flags) { +#if defined(__APPLE__) + int enable; +#endif + assert(fd >= 0); stream->flags |= flags; @@ -387,6 +391,14 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { return -errno; } +#if defined(__APPLE__) + enable = 1; + if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) && + errno != ENOTSOCK) { + return -errno; + } +#endif + stream->io_watcher.fd = fd; return 0; diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 7e85bcc51ff614..ea8563fecf95b6 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -68,7 +68,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { if (err) free(ctx); - return err ? -1 : 0; + return -err; } diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index a1ea433f81792b..b1782df95b2010 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -103,6 +103,24 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { return 0; } +static void uv__tty_make_raw(struct termios* tio) { + assert(tio != NULL); + +#ifdef __sun + /* + * This implementation of cfmakeraw for Solaris and derivatives is taken from + * http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html. + */ + tio->c_iflag &= ~(IMAXBEL | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | + IGNCR | ICRNL | IXON); + tio->c_oflag &= ~OPOST; + tio->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + tio->c_cflag &= ~(CSIZE | PARENB); + tio->c_cflag |= CS8; +#else + cfmakeraw(tio); +#endif /* #ifdef __sun */ +} int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { struct termios tmp; @@ -138,7 +156,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { tmp.c_cc[VTIME] = 0; break; case UV_TTY_MODE_IO: - cfmakeraw(&tmp); + uv__tty_make_raw(&tmp); break; } diff --git a/deps/uv/src/unix/uv-dtrace.d b/deps/uv/src/unix/uv-dtrace.d deleted file mode 100644 index 7848450c949f9b..00000000000000 --- a/deps/uv/src/unix/uv-dtrace.d +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright Joyent, Inc. and other Node 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. - */ - -provider uv { - probe tick__start(void* loop, int mode); - probe tick__stop(void* loop, int mode); -}; diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c index 993d66162c40fa..9d273a56e700f5 100644 --- a/deps/uv/src/win/thread.c +++ b/deps/uv/src/win/thread.c @@ -30,53 +30,43 @@ #define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL) #define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL) -#ifdef _MSC_VER /* msvc */ -# define inline __inline -# define NOINLINE __declspec (noinline) -#else /* gcc */ -# define inline inline -# define NOINLINE __attribute__ ((noinline)) -#endif - - -inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock); - -inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock); - - -inline static int uv_cond_fallback_init(uv_cond_t* cond); -inline static void uv_cond_fallback_destroy(uv_cond_t* cond); -inline static void uv_cond_fallback_signal(uv_cond_t* cond); -inline static void uv_cond_fallback_broadcast(uv_cond_t* cond); -inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex); -inline static int uv_cond_fallback_timedwait(uv_cond_t* cond, +static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock); +static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock); +static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock); + +static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock); +static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock); +static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock); + + +static int uv_cond_fallback_init(uv_cond_t* cond); +static void uv_cond_fallback_destroy(uv_cond_t* cond); +static void uv_cond_fallback_signal(uv_cond_t* cond); +static void uv_cond_fallback_broadcast(uv_cond_t* cond); +static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex); +static int uv_cond_fallback_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout); -inline static int uv_cond_condvar_init(uv_cond_t* cond); -inline static void uv_cond_condvar_destroy(uv_cond_t* cond); -inline static void uv_cond_condvar_signal(uv_cond_t* cond); -inline static void uv_cond_condvar_broadcast(uv_cond_t* cond); -inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex); -inline static int uv_cond_condvar_timedwait(uv_cond_t* cond, +static int uv_cond_condvar_init(uv_cond_t* cond); +static void uv_cond_condvar_destroy(uv_cond_t* cond); +static void uv_cond_condvar_signal(uv_cond_t* cond); +static void uv_cond_condvar_broadcast(uv_cond_t* cond); +static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex); +static int uv_cond_condvar_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout); -static NOINLINE void uv__once_inner(uv_once_t* guard, - void (*callback)(void)) { +static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) { DWORD result; HANDLE existing_event, created_event; @@ -185,7 +175,18 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { ResumeThread(thread); } - return err; + switch (err) { + case 0: + return 0; + case EACCES: + return UV_EACCES; + case EAGAIN: + return UV_EAGAIN; + case EINVAL: + return UV_EINVAL; + } + + return UV_EIO; } @@ -346,23 +347,23 @@ int uv_sem_trywait(uv_sem_t* sem) { } -inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) { +static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) { pInitializeSRWLock(&rwlock->srwlock_); return 0; } -inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) { (void) rwlock; } -inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) { pAcquireSRWLockShared(&rwlock->srwlock_); } -inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { +static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { if (pTryAcquireSRWLockShared(&rwlock->srwlock_)) return 0; else @@ -370,17 +371,17 @@ inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) { pReleaseSRWLockShared(&rwlock->srwlock_); } -inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) { pAcquireSRWLockExclusive(&rwlock->srwlock_); } -inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { +static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_)) return 0; else @@ -388,12 +389,12 @@ inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) { pReleaseSRWLockExclusive(&rwlock->srwlock_); } -inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { +static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { int err; err = uv_mutex_init(&rwlock->fallback_.read_mutex_); @@ -412,13 +413,13 @@ inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) { uv_mutex_destroy(&rwlock->fallback_.read_mutex_); uv_mutex_destroy(&rwlock->fallback_.write_mutex_); } -inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) { uv_mutex_lock(&rwlock->fallback_.read_mutex_); if (++rwlock->fallback_.num_readers_ == 1) @@ -428,7 +429,7 @@ inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) { } -inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { +static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { int err; err = uv_mutex_trylock(&rwlock->fallback_.read_mutex_); @@ -449,7 +450,7 @@ inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { uv_mutex_lock(&rwlock->fallback_.read_mutex_); if (--rwlock->fallback_.num_readers_ == 0) @@ -459,17 +460,17 @@ inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) { uv_mutex_lock(&rwlock->fallback_.write_mutex_); } -inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) { +static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) { return uv_mutex_trylock(&rwlock->fallback_.write_mutex_); } -inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { uv_mutex_unlock(&rwlock->fallback_.write_mutex_); } @@ -482,7 +483,7 @@ inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. */ -inline static int uv_cond_fallback_init(uv_cond_t* cond) { +static int uv_cond_fallback_init(uv_cond_t* cond) { int err; /* Initialize the count to 0. */ @@ -520,7 +521,7 @@ inline static int uv_cond_fallback_init(uv_cond_t* cond) { } -inline static int uv_cond_condvar_init(uv_cond_t* cond) { +static int uv_cond_condvar_init(uv_cond_t* cond) { pInitializeConditionVariable(&cond->cond_var); return 0; } @@ -536,7 +537,7 @@ int uv_cond_init(uv_cond_t* cond) { } -inline static void uv_cond_fallback_destroy(uv_cond_t* cond) { +static void uv_cond_fallback_destroy(uv_cond_t* cond) { if (!CloseHandle(cond->fallback.broadcast_event)) abort(); if (!CloseHandle(cond->fallback.signal_event)) @@ -545,7 +546,7 @@ inline static void uv_cond_fallback_destroy(uv_cond_t* cond) { } -inline static void uv_cond_condvar_destroy(uv_cond_t* cond) { +static void uv_cond_condvar_destroy(uv_cond_t* cond) { /* nothing to do */ } @@ -558,7 +559,7 @@ void uv_cond_destroy(uv_cond_t* cond) { } -inline static void uv_cond_fallback_signal(uv_cond_t* cond) { +static void uv_cond_fallback_signal(uv_cond_t* cond) { int have_waiters; /* Avoid race conditions. */ @@ -571,7 +572,7 @@ inline static void uv_cond_fallback_signal(uv_cond_t* cond) { } -inline static void uv_cond_condvar_signal(uv_cond_t* cond) { +static void uv_cond_condvar_signal(uv_cond_t* cond) { pWakeConditionVariable(&cond->cond_var); } @@ -584,7 +585,7 @@ void uv_cond_signal(uv_cond_t* cond) { } -inline static void uv_cond_fallback_broadcast(uv_cond_t* cond) { +static void uv_cond_fallback_broadcast(uv_cond_t* cond) { int have_waiters; /* Avoid race conditions. */ @@ -597,7 +598,7 @@ inline static void uv_cond_fallback_broadcast(uv_cond_t* cond) { } -inline static void uv_cond_condvar_broadcast(uv_cond_t* cond) { +static void uv_cond_condvar_broadcast(uv_cond_t* cond) { pWakeAllConditionVariable(&cond->cond_var); } @@ -610,7 +611,7 @@ void uv_cond_broadcast(uv_cond_t* cond) { } -inline int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, +static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, DWORD dwMilliseconds) { DWORD result; int last_waiter; @@ -660,13 +661,13 @@ inline int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, } -inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) { +static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) { if (uv_cond_wait_helper(cond, mutex, INFINITE)) abort(); } -inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) { +static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) { if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE)) abort(); } @@ -680,13 +681,13 @@ void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { } -inline static int uv_cond_fallback_timedwait(uv_cond_t* cond, +static int uv_cond_fallback_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6)); } -inline static int uv_cond_condvar_timedwait(uv_cond_t* cond, +static int uv_cond_condvar_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) return 0; diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 2c392251f03ce5..cc5dc744501ec4 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -436,7 +436,11 @@ static void scandir_cb(uv_fs_t* req) { while (UV_EOF != uv_fs_scandir_next(req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); +#ifdef HAVE_DIRENT_TYPES + ASSERT(dent.type == UV_DIRENT_FILE); +#else + ASSERT(dent.type == UV_DIRENT_UNKNOWN); +#endif } scandir_cb_count++; ASSERT(req->path); @@ -875,7 +879,11 @@ TEST_IMPL(fs_async_dir) { ASSERT(scandir_req.ptr); while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); +#ifdef HAVE_DIRENT_TYPES + ASSERT(dent.type == UV_DIRENT_FILE); +#else + ASSERT(dent.type == UV_DIRENT_UNKNOWN); +#endif } uv_fs_req_cleanup(&scandir_req); ASSERT(!scandir_req.ptr); @@ -1695,7 +1703,11 @@ TEST_IMPL(fs_symlink_dir) { ASSERT(scandir_req.ptr); while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); +#ifdef HAVE_DIRENT_TYPES + ASSERT(dent.type == UV_DIRENT_FILE); +#else + ASSERT(dent.type == UV_DIRENT_UNKNOWN); +#endif } uv_fs_req_cleanup(&scandir_req); ASSERT(!scandir_req.ptr); @@ -1715,7 +1727,11 @@ TEST_IMPL(fs_symlink_dir) { ASSERT(scandir_req.ptr); while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); +#ifdef HAVE_DIRENT_TYPES + ASSERT(dent.type == UV_DIRENT_FILE); +#else + ASSERT(dent.type == UV_DIRENT_UNKNOWN); +#endif } uv_fs_req_cleanup(&scandir_req); ASSERT(!scandir_req.ptr); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 9eb6a38dcdc3cc..aac15e0d9df0b7 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -80,6 +80,7 @@ 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) @@ -396,6 +397,7 @@ TASK_LIST_START 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) diff --git a/deps/uv/test/test-tcp-oob.c b/deps/uv/test/test-tcp-oob.c new file mode 100644 index 00000000000000..fc011ee495f1f6 --- /dev/null +++ b/deps/uv/test/test-tcp-oob.c @@ -0,0 +1,128 @@ +/* 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 +#include +#include + +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 alloc_cb(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) { + static char storage[1024]; + *buf = uv_buf_init(storage, sizeof(storage)); +} + + +static void idle_cb(uv_idle_t* idle) { + 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* handle, ssize_t nread, const 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; + uv_os_fd_t 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 */ + ASSERT(0 == uv_fileno((uv_handle_t*) &client_handle, &fd)); + + ASSERT(0 == uv_stream_set_blocking((uv_stream_t*) &client_handle, 1)); + + /* 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); + + ASSERT(0 == uv_stream_set_blocking((uv_stream_t*) &client_handle, 0)); +} + + +TEST_IMPL(tcp_oob) { + struct sockaddr_in addr; + uv_loop_t* loop; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + loop = uv_default_loop(); + + ASSERT(0 == uv_tcp_init(loop, &server_handle)); + ASSERT(0 == uv_tcp_init(loop, &client_handle)); + ASSERT(0 == uv_tcp_init(loop, &peer_handle)); + ASSERT(0 == uv_idle_init(loop, &idle)); + ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0)); + ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 1, connection_cb)); + + /* Ensure two separate packets */ + ASSERT(0 == uv_tcp_nodelay(&client_handle, 1)); + + ASSERT(0 == uv_tcp_connect(&connect_req, + &client_handle, + (const struct sockaddr*) &addr, + 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 de4a591392b1a0..1ef8c05adc6496 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -366,6 +366,7 @@ 'test/test-tcp-writealot.c', 'test/test-tcp-try-write.c', 'test/test-tcp-unexpected-read.c', + 'test/test-tcp-oob.c', 'test/test-tcp-read-stop.c', 'test/test-tcp-write-queue-order.c', 'test/test-threadpool.c',