From 3374f57973dcd4c2ae1f665387085b0e444d9f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Tue, 14 Jun 2016 00:00:08 +0200 Subject: [PATCH] deps: update libuv to 0.10.37 Fixes: https://github.com/nodejs/node/issues/7199 Refs: https://github.com/nodejs/node/pull/2723 PR-URL: https://github.com/nodejs/node/pull/7293 Reviewed-By: Rod Vagg --- deps/uv/AUTHORS | 1 + deps/uv/ChangeLog | 27 +- deps/uv/README.md | 11 +- deps/uv/config-unix.mk | 2 +- deps/uv/include/uv-private/ngx-queue.h | 14 + deps/uv/include/uv-private/uv-win.h | 18 +- deps/uv/src/unix/async.c | 8 +- deps/uv/src/unix/darwin.c | 8 +- deps/uv/src/unix/error.c | 1 + deps/uv/src/unix/fsevents.c | 6 +- deps/uv/src/unix/linux-core.c | 2 +- deps/uv/src/unix/linux-inotify.c | 9 +- deps/uv/src/unix/loop-watcher.c | 7 +- deps/uv/src/unix/signal.c | 2 + deps/uv/src/unix/thread.c | 33 ++- deps/uv/src/unix/threadpool.c | 7 +- deps/uv/src/uv-common.c | 9 +- deps/uv/src/version.c | 2 +- deps/uv/src/win/thread.c | 255 ++++++------------ deps/uv/src/win/winapi.c | 28 -- deps/uv/src/win/winapi.h | 28 -- deps/uv/test/test-fs.c | 13 +- deps/uv/test/test-list.h | 2 + deps/uv/test/test-mutexes.c | 59 ++++ .../uv/test/test-tcp-close-while-connecting.c | 6 +- deps/uv/test/test-tcp-connect-timeout.c | 2 + deps/uv/test/test-udp-multicast-join.c | 2 + deps/uv/test/test-udp-multicast-ttl.c | 6 +- deps/uv/vcbuild.bat | 4 +- 29 files changed, 274 insertions(+), 298 deletions(-) diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 1123dd8ec4c977..09b850d4dd8d1e 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -135,3 +135,4 @@ Helge Deller Logan Rosen Kenneth Perry Michael Penick +Stephen von Takach diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index bd03d53b5c3d94..278d0357630e9b 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,29 @@ -2015.02.27, Version 0.10.36 (Stable) +2016.06.14, Version 0.10.37 (Stable) + +Changes since version 0.10.36: + +* build: update the location of gyp (Stephen von Takach) + +* linux: fix epoll_pwait() fallback on arm64 (Ben Noordhuis) + +* test: fix fs_chown when running as root (Ben Noordhuis) + +* tests: skip some tests when network is unreachable (Luca Bruno) + +* unix: do not discard environmental LDFLAGS (Luca Bruno) + +* src: replace ngx_queue_split with ngx_queue_move (Ben Noordhuis) + +* unix: use ngx_queue_move when iterating over lists (Ben Noordhuis) + +* win: fix unsavory rwlock fallback implementation (Bert Belder) + +* unix: map ENFILE errno (Saúl Ibarra Corretgé) + +* doc: add note indicating branch status (Saúl Ibarra Corretgé) + + +2015.02.27, Version 0.10.36 (Stable), cc4d42a89a2a0ae0ff8e14321de086eba3c3b4ca Changes since version 0.10.35: diff --git a/deps/uv/README.md b/deps/uv/README.md index 5fee16cfe013ec..e03d8defdf7005 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -6,6 +6,9 @@ eventually contain all platform differences in this library. http://nodejs.org/ +**This branch only receives security fixes and will be EOL'd by the end of 2016, +please switch to version v1.x** + ## Features * Non-blocking TCP sockets @@ -81,13 +84,7 @@ To have GYP generate build script for another system, make sure that you have Python 2.6 or 2.7 installed, then checkout GYP into the project tree manually: - mkdir -p build - svn co http://gyp.googlecode.com/svn/trunk build/gyp - -Or: - - mkdir -p build - git clone https://git.chromium.org/external/gyp.git build/gyp + git clone https://chromium.googlesource.com/external/gyp.git build/gyp Unix users run diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index db21daa0ba5b1f..82958cf9f03a63 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 -pthread +LDFLAGS += -lm -pthread CPPFLAGS += -D_LARGEFILE_SOURCE CPPFLAGS += -D_FILE_OFFSET_BITS=64 diff --git a/deps/uv/include/uv-private/ngx-queue.h b/deps/uv/include/uv-private/ngx-queue.h index 3c3ed1b0344f9a..3625b7d8d25f3c 100644 --- a/deps/uv/include/uv-private/ngx-queue.h +++ b/deps/uv/include/uv-private/ngx-queue.h @@ -106,6 +106,17 @@ struct ngx_queue_s { while (0) +#define ngx_queue_move(h, n) \ + do { \ + if (ngx_queue_empty(h)) \ + ngx_queue_init(n); \ + else { \ + ngx_queue_t* q = ngx_queue_head(h); \ + ngx_queue_split(h, q, n); \ + } \ + } \ + while (0) + #define ngx_queue_add(h, n) \ do { \ (h)->prev->next = (n)->next; \ @@ -120,6 +131,9 @@ struct ngx_queue_s { ((type *) ((unsigned char *) q - offsetof(type, link))) +/* Important note: mutating the list while ngx_queue_foreach is + * iterating over its elements results in undefined behavior. + */ #define ngx_queue_foreach(q, h) \ for ((q) = ngx_queue_head(h); \ (q) != ngx_queue_sentinel(h) && !ngx_queue_empty(h); \ diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index c9ec38ef4ca302..f5876d3da8fef6 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -235,14 +235,20 @@ typedef union { } uv_cond_t; typedef union { - /* srwlock_ has type SRWLOCK, but not all toolchains define this type in */ - /* windows.h. */ - SRWLOCK srwlock_; struct { - uv_mutex_t read_mutex_; - uv_mutex_t write_mutex_; unsigned int num_readers_; - } fallback_; + CRITICAL_SECTION num_readers_lock_; + HANDLE write_semaphore_; + } state_; + /* TODO: remove me in v2.x. */ + struct { + SRWLOCK unused_; + } unused1_; + /* TODO: remove me in v2.x. */ + struct { + uv_mutex_t unused1_; + uv_mutex_t unused2_; + } unused2_; } uv_rwlock_t; typedef struct { diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index 8adf046a697161..19377191dd9697 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -74,12 +74,18 @@ void uv__async_close(uv_async_t* handle) { static void uv__async_event(uv_loop_t* loop, struct uv__async* w, unsigned int nevents) { + ngx_queue_t queue; ngx_queue_t* q; uv_async_t* h; - ngx_queue_foreach(q, &loop->async_handles) { + ngx_queue_move(&loop->async_handles, &queue); + while (!ngx_queue_empty(&queue)) { + q = ngx_queue_head(&queue); h = ngx_queue_data(q, uv_async_t, queue); + ngx_queue_remove(q); + ngx_queue_insert_tail(&loop->async_handles, q); + if (cmpxchgi(&h->pending, 1, 0) == 0) continue; diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index f37d58df56ddb5..c8c79dc79a8b72 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -133,15 +133,12 @@ static void uv__cf_loop_cb(void* arg) { loop = arg; uv_mutex_lock(&loop->cf_mutex); - ngx_queue_init(&split_head); - if (!ngx_queue_empty(&loop->cf_signals)) { - ngx_queue_t* split_pos = ngx_queue_next(&loop->cf_signals); - ngx_queue_split(&loop->cf_signals, split_pos, &split_head); - } + ngx_queue_move(&loop->cf_signals, &split_head); uv_mutex_unlock(&loop->cf_mutex); while (!ngx_queue_empty(&split_head)) { item = ngx_queue_head(&split_head); + ngx_queue_remove(item); s = ngx_queue_data(item, uv__cf_loop_signal_t, member); @@ -151,7 +148,6 @@ static void uv__cf_loop_cb(void* arg) { else s->cb(s->arg); - ngx_queue_remove(item); free(s); } } diff --git a/deps/uv/src/unix/error.c b/deps/uv/src/unix/error.c index f54ffdbcc831b6..fc65c08a24695f 100644 --- a/deps/uv/src/unix/error.c +++ b/deps/uv/src/unix/error.c @@ -110,6 +110,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ERANGE: return UV_ERANGE; case ENXIO: return UV_ENXIO; case EMLINK: return UV_EMLINK; + case ENFILE: return UV_ENFILE; default: return UV_UNKNOWN; } UNREACHABLE(); diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index d86032420feff4..753705cf53bc2b 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -55,11 +55,7 @@ struct uv__fsevents_event_s { ngx_queue_t split_head; \ uv__fsevents_event_t* event; \ uv_mutex_lock(&(handle)->cf_mutex); \ - ngx_queue_init(&split_head); \ - if (!ngx_queue_empty(&(handle)->cf_events)) { \ - ngx_queue_t* split_pos = ngx_queue_next(&(handle)->cf_events); \ - ngx_queue_split(&(handle)->cf_events, split_pos, &split_head); \ - } \ + ngx_queue_move(&(handle)->cf_events, &split_head); \ uv_mutex_unlock(&(handle)->cf_mutex); \ while (!ngx_queue_empty(&split_head)) { \ curr = ngx_queue_head(&split_head); \ diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 6cd5a7f003f16b..11a67eb85b52e8 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -199,7 +199,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) abort(); - if (sigmask != 0 && no_epoll_pwait == 0) { + if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) { nfds = uv__epoll_pwait(loop->backend_fd, events, ARRAY_SIZE(events), diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c index 108345aa842d3c..c3fe24c34f68a4 100644 --- a/deps/uv/src/unix/linux-inotify.c +++ b/deps/uv/src/unix/linux-inotify.c @@ -119,6 +119,7 @@ static void uv__inotify_read(uv_loop_t* loop, const struct uv__inotify_event* e; struct watcher_list* w; uv_fs_event_t* h; + ngx_queue_t queue; ngx_queue_t* q; const char* path; ssize_t size; @@ -158,8 +159,14 @@ static void uv__inotify_read(uv_loop_t* loop, */ path = e->len ? (const char*) (e + 1) : basename_r(w->path); - ngx_queue_foreach(q, &w->watchers) { + ngx_queue_move(&w->watchers, &queue); + while (!ngx_queue_empty(&queue)) { + q = ngx_queue_head(&queue); h = ngx_queue_data(q, uv_fs_event_t, watchers); + + ngx_queue_remove(q); + ngx_queue_insert_tail(&w->watchers, q); + h->cb(h, path, events, 0); } } diff --git a/deps/uv/src/unix/loop-watcher.c b/deps/uv/src/unix/loop-watcher.c index a07569e4031558..facb147827aa80 100644 --- a/deps/uv/src/unix/loop-watcher.c +++ b/deps/uv/src/unix/loop-watcher.c @@ -48,9 +48,14 @@ \ void uv__run_##name(uv_loop_t* loop) { \ uv_##name##_t* h; \ + ngx_queue_t queue; \ ngx_queue_t* q; \ - ngx_queue_foreach(q, &loop->name##_handles) { \ + ngx_queue_move(&loop->name##_handles, &queue); \ + while (!ngx_queue_empty(&queue)) { \ + q = ngx_queue_head(&queue); \ h = ngx_queue_data(q, uv_##name##_t, queue); \ + ngx_queue_remove(q); \ + ngx_queue_insert_tail(&loop->name##_handles, q); \ h->name##_cb(h, 0); \ } \ } \ diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index aa84ff2f2d7699..5c7d60a2ddf67d 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -231,6 +231,8 @@ void uv__signal_loop_cleanup(uv_loop_t* loop) { /* Stop all the signal watchers that are still attached to this loop. This * ensures that the (shared) signal tree doesn't contain any invalid entries * entries, and that signal handlers are removed when appropriate. + * It's safe to use QUEUE_FOREACH here because the handles and the handle + * queue are not modified by uv__signal_stop(). */ ngx_queue_foreach(q, &loop->handle_queue) { uv_handle_t* handle = ngx_queue_data(q, uv_handle_t, handle_queue); diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 4d59e938e216f6..55b8cb7ed8ddba 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -84,13 +84,12 @@ int uv_mutex_trylock(uv_mutex_t* mutex) { r = pthread_mutex_trylock(mutex); - if (r && r != EBUSY && r != EAGAIN) - abort(); - - if (r) + if (r) { + if (r != EBUSY && r != EAGAIN) + abort(); return -1; - else - return 0; + } + return 0; } @@ -125,13 +124,12 @@ int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { r = pthread_rwlock_tryrdlock(rwlock); - if (r && r != EBUSY && r != EAGAIN) - abort(); - - if (r) + if (r) { + if (r != EBUSY && r != EAGAIN) + abort(); return -1; - else - return 0; + } + return 0; } @@ -152,13 +150,12 @@ int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { r = pthread_rwlock_trywrlock(rwlock); - if (r && r != EBUSY && r != EAGAIN) - abort(); - - if (r) + if (r) { + if (r != EBUSY && r != EAGAIN) + abort(); return -1; - else - return 0; + } + return 0; } diff --git a/deps/uv/src/unix/threadpool.c b/deps/uv/src/unix/threadpool.c index 6e5adc403e8433..7bc847ff913bd1 100644 --- a/deps/uv/src/unix/threadpool.c +++ b/deps/uv/src/unix/threadpool.c @@ -202,13 +202,8 @@ void uv__work_done(uv_async_t* handle, int status) { int err; loop = container_of(handle, uv_loop_t, wq_async); - ngx_queue_init(&wq); - uv_mutex_lock(&loop->wq_mutex); - if (!ngx_queue_empty(&loop->wq)) { - q = ngx_queue_head(&loop->wq); - ngx_queue_split(&loop->wq, q, &wq); - } + ngx_queue_move(&loop->wq, &wq); uv_mutex_unlock(&loop->wq_mutex); while (!ngx_queue_empty(&wq)) { diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 69da523e6af509..bae5a72a1d7201 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -362,11 +362,18 @@ unsigned long uv_thread_self(void) { void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { + ngx_queue_t queue; ngx_queue_t* q; uv_handle_t* h; - ngx_queue_foreach(q, &loop->handle_queue) { + ngx_queue_move(&loop->handle_queue, &queue); + while (!ngx_queue_empty(&queue)) { + q = ngx_queue_head(&queue); h = ngx_queue_data(q, uv_handle_t, handle_queue); + + ngx_queue_remove(q); + ngx_queue_insert_tail(&loop->handle_queue, q); + if (h->flags & UV__HANDLE_INTERNAL) continue; walk_cb(h, arg); } diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c index 55408660640be9..ecf300ec5c9d93 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 36 +#define UV_VERSION_PATCH 37 #define UV_VERSION_IS_RELEASE 1 diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c index e774fd9cf92aff..43ee184f05ce48 100644 --- a/deps/uv/src/win/thread.c +++ b/deps/uv/src/win/thread.c @@ -26,7 +26,6 @@ #include "internal.h" -#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL) #define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL) #ifdef _MSC_VER /* msvc */ @@ -38,25 +37,6 @@ #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); @@ -158,68 +138,112 @@ void uv_mutex_unlock(uv_mutex_t* mutex) { int uv_rwlock_init(uv_rwlock_t* rwlock) { - uv__once_init(); + /* Initialize the semaphore that acts as the write lock. */ + HANDLE handle = CreateSemaphoreW(NULL, 1, 1, NULL); + if (handle == NULL) + return -1; + rwlock->state_.write_semaphore_ = handle; - if (HAVE_SRWLOCK_API()) - return uv__rwlock_srwlock_init(rwlock); - else - return uv__rwlock_fallback_init(rwlock); + /* Initialize the critical section protecting the reader count. */ + InitializeCriticalSection(&rwlock->state_.num_readers_lock_); + + /* Initialize the reader count. */ + rwlock->state_.num_readers_ = 0; + + return 0; } void uv_rwlock_destroy(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_destroy(rwlock); - else - uv__rwlock_fallback_destroy(rwlock); + DeleteCriticalSection(&rwlock->state_.num_readers_lock_); + CloseHandle(rwlock->state_.write_semaphore_); } void uv_rwlock_rdlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_rdlock(rwlock); - else - uv__rwlock_fallback_rdlock(rwlock); + /* Acquire the lock that protects the reader count. */ + EnterCriticalSection(&rwlock->state_.num_readers_lock_); + + /* Increase the reader count, and lock for write if this is the first + * reader. + */ + if (++rwlock->state_.num_readers_ == 1) { + DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE); + if (r != WAIT_OBJECT_0) + uv_fatal_error(GetLastError(), "WaitForSingleObject"); + } + + /* Release the lock that protects the reader count. */ + LeaveCriticalSection(&rwlock->state_.num_readers_lock_); } int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - return uv__rwlock_srwlock_tryrdlock(rwlock); - else - return uv__rwlock_fallback_tryrdlock(rwlock); + int err; + + if (!TryEnterCriticalSection(&rwlock->state_.num_readers_lock_)) + return -1; + + err = 0; + + if (rwlock->state_.num_readers_ == 0) { + /* Currently there are no other readers, which means that the write lock + * needs to be acquired. + */ + DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0); + if (r == WAIT_OBJECT_0) + rwlock->state_.num_readers_++; + else if (r == WAIT_TIMEOUT) + err = -1; + else if (r == WAIT_FAILED) + uv_fatal_error(GetLastError(), "WaitForSingleObject"); + + } else { + /* The write lock has already been acquired because there are other + * active readers. + */ + rwlock->state_.num_readers_++; + } + + LeaveCriticalSection(&rwlock->state_.num_readers_lock_); + return err; } void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_rdunlock(rwlock); - else - uv__rwlock_fallback_rdunlock(rwlock); + EnterCriticalSection(&rwlock->state_.num_readers_lock_); + + if (--rwlock->state_.num_readers_ == 0) { + if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL)) + uv_fatal_error(GetLastError(), "ReleaseSemaphore"); + } + + LeaveCriticalSection(&rwlock->state_.num_readers_lock_); } void uv_rwlock_wrlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_wrlock(rwlock); - else - uv__rwlock_fallback_wrlock(rwlock); + DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE); + if (r != WAIT_OBJECT_0) + uv_fatal_error(GetLastError(), "WaitForSingleObject"); } int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - return uv__rwlock_srwlock_trywrlock(rwlock); + DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0); + if (r == WAIT_OBJECT_0) + return 0; + else if (r == WAIT_TIMEOUT) + return -1; else - return uv__rwlock_fallback_trywrlock(rwlock); + uv_fatal_error(GetLastError(), "WaitForSingleObject"); + return -1; } void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_wrunlock(rwlock); - else - uv__rwlock_fallback_wrunlock(rwlock); + if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL)) + uv_fatal_error(GetLastError(), "ReleaseSemaphore"); } @@ -261,133 +285,6 @@ int uv_sem_trywait(uv_sem_t* sem) { } -inline 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) { - (void) rwlock; -} - - -inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) { - pAcquireSRWLockShared(&rwlock->srwlock_); -} - - -inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { - if (pTryAcquireSRWLockShared(&rwlock->srwlock_)) - return 0; - else - return -1; -} - - -inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) { - pReleaseSRWLockShared(&rwlock->srwlock_); -} - - -inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) { - pAcquireSRWLockExclusive(&rwlock->srwlock_); -} - - -inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { - if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_)) - return 0; - else - return -1; -} - - -inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) { - pReleaseSRWLockExclusive(&rwlock->srwlock_); -} - - -inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { - if (uv_mutex_init(&rwlock->fallback_.read_mutex_)) - return -1; - - if (uv_mutex_init(&rwlock->fallback_.write_mutex_)) { - uv_mutex_destroy(&rwlock->fallback_.read_mutex_); - return -1; - } - - rwlock->fallback_.num_readers_ = 0; - - return 0; -} - - -inline 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) { - uv_mutex_lock(&rwlock->fallback_.read_mutex_); - - if (++rwlock->fallback_.num_readers_ == 1) - uv_mutex_lock(&rwlock->fallback_.write_mutex_); - - uv_mutex_unlock(&rwlock->fallback_.read_mutex_); -} - - -inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { - int ret; - - ret = -1; - - if (uv_mutex_trylock(&rwlock->fallback_.read_mutex_)) - goto out; - - if (rwlock->fallback_.num_readers_ == 0) - ret = uv_mutex_trylock(&rwlock->fallback_.write_mutex_); - else - ret = 0; - - if (ret == 0) - rwlock->fallback_.num_readers_++; - - uv_mutex_unlock(&rwlock->fallback_.read_mutex_); - -out: - return ret; -} - - -inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { - uv_mutex_lock(&rwlock->fallback_.read_mutex_); - - if (--rwlock->fallback_.num_readers_ == 0) - uv_mutex_unlock(&rwlock->fallback_.write_mutex_); - - uv_mutex_unlock(&rwlock->fallback_.read_mutex_); -} - - -inline 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) { - return uv_mutex_trylock(&rwlock->fallback_.write_mutex_); -} - - -inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { - uv_mutex_unlock(&rwlock->fallback_.write_mutex_); -} - - - /* This condition variable implementation is based on the SetEvent solution * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html * We could not use the SignalObjectAndWait solution (section 3.4) because diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index ab68bba7420c50..1f0677360f8b0e 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -38,13 +38,6 @@ sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; sCreateSymbolicLinkW pCreateSymbolicLinkW; sCancelIoEx pCancelIoEx; -sInitializeSRWLock pInitializeSRWLock; -sAcquireSRWLockShared pAcquireSRWLockShared; -sAcquireSRWLockExclusive pAcquireSRWLockExclusive; -sTryAcquireSRWLockShared pTryAcquireSRWLockShared; -sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive; -sReleaseSRWLockShared pReleaseSRWLockShared; -sReleaseSRWLockExclusive pReleaseSRWLockExclusive; sInitializeConditionVariable pInitializeConditionVariable; sSleepConditionVariableCS pSleepConditionVariableCS; sSleepConditionVariableSRW pSleepConditionVariableSRW; @@ -114,27 +107,6 @@ void uv_winapi_init() { pCancelIoEx = (sCancelIoEx) GetProcAddress(kernel32_module, "CancelIoEx"); - pInitializeSRWLock = (sInitializeSRWLock) - GetProcAddress(kernel32_module, "InitializeSRWLock"); - - pAcquireSRWLockShared = (sAcquireSRWLockShared) - GetProcAddress(kernel32_module, "AcquireSRWLockShared"); - - pAcquireSRWLockExclusive = (sAcquireSRWLockExclusive) - GetProcAddress(kernel32_module, "AcquireSRWLockExclusive"); - - pTryAcquireSRWLockShared = (sTryAcquireSRWLockShared) - GetProcAddress(kernel32_module, "TryAcquireSRWLockShared"); - - pTryAcquireSRWLockExclusive = (sTryAcquireSRWLockExclusive) - GetProcAddress(kernel32_module, "TryAcquireSRWLockExclusive"); - - pReleaseSRWLockShared = (sReleaseSRWLockShared) - GetProcAddress(kernel32_module, "ReleaseSRWLockShared"); - - pReleaseSRWLockExclusive = (sReleaseSRWLockExclusive) - GetProcAddress(kernel32_module, "ReleaseSRWLockExclusive"); - pInitializeConditionVariable = (sInitializeConditionVariable) GetProcAddress(kernel32_module, "InitializeConditionVariable"); diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index e023beed5d4713..9e78b6b8b083cd 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4405,27 +4405,6 @@ typedef BOOL (WINAPI* sCancelIoEx) (HANDLE hFile, LPOVERLAPPED lpOverlapped); -typedef VOID (WINAPI* sInitializeSRWLock) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sAcquireSRWLockShared) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sAcquireSRWLockExclusive) - (PSRWLOCK SRWLock); - -typedef BOOL (WINAPI* sTryAcquireSRWLockShared) - (PSRWLOCK SRWLock); - -typedef BOOL (WINAPI* sTryAcquireSRWLockExclusive) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sReleaseSRWLockShared) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sReleaseSRWLockExclusive) - (PSRWLOCK SRWLock); - typedef VOID (WINAPI* sInitializeConditionVariable) (PCONDITION_VARIABLE ConditionVariable); @@ -4460,13 +4439,6 @@ extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; extern sCreateSymbolicLinkW pCreateSymbolicLinkW; extern sCancelIoEx pCancelIoEx; -extern sInitializeSRWLock pInitializeSRWLock; -extern sAcquireSRWLockShared pAcquireSRWLockShared; -extern sAcquireSRWLockExclusive pAcquireSRWLockExclusive; -extern sTryAcquireSRWLockShared pTryAcquireSRWLockShared; -extern sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive; -extern sReleaseSRWLockShared pReleaseSRWLockShared; -extern sReleaseSRWLockExclusive pReleaseSRWLockExclusive; extern sInitializeConditionVariable pInitializeConditionVariable; extern sSleepConditionVariableCS pSleepConditionVariableCS; extern sSleepConditionVariableSRW pSleepConditionVariableSRW; diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index ca2ff2bd428e0a..587895f8d0ca74 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -196,9 +196,16 @@ static void chown_root_cb(uv_fs_t* req) { /* On windows, chown is a no-op and always succeeds. */ ASSERT(req->result == 0); #else - /* On unix, chown'ing the root directory is not allowed. */ - ASSERT(req->result == -1); - ASSERT(req->errorno == UV_EPERM); + /* On unix, chown'ing the root directory is not allowed - + * unless you're root, of course. + */ + if (geteuid() == 0) { + ASSERT(req->result == 0); + } + else { + ASSERT(req->result == -1); + ASSERT(req->errorno == UV_EPERM); + } #endif chown_cb_count++; uv_fs_req_cleanup(req); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 0bfb9e41e0d49e..51c9fe32f8a291 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -211,6 +211,7 @@ TEST_DECLARE (threadpool_cancel_fs) TEST_DECLARE (threadpool_cancel_single) TEST_DECLARE (thread_mutex) TEST_DECLARE (thread_rwlock) +TEST_DECLARE (thread_rwlock_trylock) TEST_DECLARE (thread_create) TEST_DECLARE (strlcpy) TEST_DECLARE (strlcat) @@ -522,6 +523,7 @@ TASK_LIST_START TEST_ENTRY (threadpool_cancel_single) TEST_ENTRY (thread_mutex) TEST_ENTRY (thread_rwlock) + TEST_ENTRY (thread_rwlock_trylock) TEST_ENTRY (thread_create) TEST_ENTRY (strlcpy) TEST_ENTRY (strlcat) diff --git a/deps/uv/test/test-mutexes.c b/deps/uv/test/test-mutexes.c index 896f46bbed0942..5f8bc46f115971 100644 --- a/deps/uv/test/test-mutexes.c +++ b/deps/uv/test/test-mutexes.c @@ -61,3 +61,62 @@ TEST_IMPL(thread_rwlock) { return 0; } + + +TEST_IMPL(thread_rwlock_trylock) { + uv_rwlock_t rwlock; + int r; + + r = uv_rwlock_init(&rwlock); + ASSERT(r == 0); + + /* No locks held. */ + + r = uv_rwlock_trywrlock(&rwlock); + ASSERT(r == 0); + + /* Write lock held. */ + + r = uv_rwlock_tryrdlock(&rwlock); + ASSERT(r == -1); + r = uv_rwlock_trywrlock(&rwlock); + ASSERT(r == -1); + + uv_rwlock_wrunlock(&rwlock); + + /* No locks held. */ + + r = uv_rwlock_tryrdlock(&rwlock); + ASSERT(r == 0); + + /* One read lock held. */ + + r = uv_rwlock_tryrdlock(&rwlock); + ASSERT(r == 0); + + /* Two read locks held. */ + + r = uv_rwlock_trywrlock(&rwlock); + ASSERT(r == -1); + + uv_rwlock_rdunlock(&rwlock); + + /* One read lock held. */ + + uv_rwlock_rdunlock(&rwlock); + + /* No read locks held. */ + + r = uv_rwlock_trywrlock(&rwlock); + ASSERT(r == 0); + + /* Write lock held. */ + + uv_rwlock_wrunlock(&rwlock); + + /* No locks held. */ + + uv_rwlock_destroy(&rwlock); + + return 0; +} diff --git a/deps/uv/test/test-tcp-close-while-connecting.c b/deps/uv/test/test-tcp-close-while-connecting.c index d19dcbfee0b7c6..4a4196cf149373 100644 --- a/deps/uv/test/test-tcp-close-while-connecting.c +++ b/deps/uv/test/test-tcp-close-while-connecting.c @@ -60,12 +60,16 @@ TEST_IMPL(tcp_close_while_connecting) { uv_connect_t connect_req; struct sockaddr_in addr; uv_loop_t* loop; + int r; addr = uv_ip4_addr("1.2.3.4", TEST_PORT); loop = uv_default_loop(); ASSERT(0 == uv_tcp_init(loop, &tcp_handle)); - ASSERT(0 == uv_tcp_connect(&connect_req, &tcp_handle, addr, connect_cb)); + r = uv_tcp_connect(&connect_req, &tcp_handle, addr, connect_cb); + if (r == -1 && uv_last_error(uv_default_loop()).code == UV_ENETUNREACH) + RETURN_SKIP("Network unreachable."); + ASSERT(r == 0); ASSERT(0 == uv_timer_init(loop, &timer1_handle)); ASSERT(0 == uv_timer_start(&timer1_handle, timer1_cb, 50, 0)); ASSERT(0 == uv_timer_init(loop, &timer2_handle)); diff --git a/deps/uv/test/test-tcp-connect-timeout.c b/deps/uv/test/test-tcp-connect-timeout.c index 0569b6b0f22283..33992024a461ba 100644 --- a/deps/uv/test/test-tcp-connect-timeout.c +++ b/deps/uv/test/test-tcp-connect-timeout.c @@ -76,6 +76,8 @@ TEST_IMPL(tcp_connect_timeout) { ASSERT(r == 0); r = uv_tcp_connect(&connect_req, &conn, addr, connect_cb); + if (r == -1 && uv_last_error(uv_default_loop()).code == UV_ENETUNREACH) + RETURN_SKIP("Network unreachable."); ASSERT(r == 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); diff --git a/deps/uv/test/test-udp-multicast-join.c b/deps/uv/test/test-udp-multicast-join.c index 83ec46b8d1e2db..3134d3eeec6935 100644 --- a/deps/uv/test/test-udp-multicast-join.c +++ b/deps/uv/test/test-udp-multicast-join.c @@ -113,6 +113,8 @@ TEST_IMPL(udp_multicast_join) { /* join the multicast channel */ r = uv_udp_set_membership(&client, "239.255.0.1", NULL, UV_JOIN_GROUP); + if (r == -1 && uv_last_error(uv_default_loop()).code == UV_ENODEV) + RETURN_SKIP("No multicast support."); ASSERT(r == 0); r = uv_udp_recv_start(&client, alloc_cb, cl_recv_cb); diff --git a/deps/uv/test/test-udp-multicast-ttl.c b/deps/uv/test/test-udp-multicast-ttl.c index 6d36983673b135..c9d24597c81bfa 100644 --- a/deps/uv/test/test-udp-multicast-ttl.c +++ b/deps/uv/test/test-udp-multicast-ttl.c @@ -44,7 +44,11 @@ static void close_cb(uv_handle_t* handle) { static void sv_send_cb(uv_udp_send_t* req, int status) { ASSERT(req != NULL); - ASSERT(status == 0); + if (status == -1) { + ASSERT(uv_last_error(uv_default_loop()).code == UV_ENETUNREACH); + } else { + ASSERT(status == 0); + } CHECK_HANDLE(req->handle); sv_send_cb_called++; diff --git a/deps/uv/vcbuild.bat b/deps/uv/vcbuild.bat index 42b0b94792215b..357ca5c14691da 100644 --- a/deps/uv/vcbuild.bat +++ b/deps/uv/vcbuild.bat @@ -90,8 +90,8 @@ if defined noprojgen goto msbuild @rem Generate the VS project. if exist build\gyp goto have_gyp -echo git clone https://git.chromium.org/external/gyp.git build/gyp -git clone https://git.chromium.org/external/gyp.git build/gyp +echo git clone https://chromium.googlesource.com/external/gyp build/gyp +git clone https://chromium.googlesource.com/external/gyp build/gyp if errorlevel 1 goto gyp_install_failed goto have_gyp