mirror of https://github.com/nodejs/node.git
deps: update libuv to 1.4.1
PR-URL: https://github.com/iojs/io.js/pull/940 Reviewed-By: Fedor Indutny <fedor@indutny.com> Reviewed-By: Rod Vagg <rod@vagg.org>
This commit is contained in:
parent
06ee782f24
commit
739fda16a9
|
@ -67,3 +67,6 @@ ipch
|
|||
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
||||
|
||||
# make dist output
|
||||
libuv-*.tar.*
|
||||
|
|
|
@ -14,6 +14,7 @@ Isaac Z. Schlueter <i@izs.me>
|
|||
Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
|
||||
Leith Bade <leith@leithalweapon.geek.nz> <leith@mapbox.com>
|
||||
Leonard Hecker <leonard.hecker91@gmail.com> <leonard@hecker.io>
|
||||
Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
|
||||
|
|
|
@ -180,3 +180,4 @@ Alexey Melnichuk <mimir@newmail.ru>
|
|||
Johan Bergström <bugs@bergstroem.nu>
|
||||
Alex Mo <almosnow@gmail.com>
|
||||
Luis Martinez de Bartolome <lasote@gmail.com>
|
||||
Michael Penick <michael.penick@datastax.com>
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include "atomic-ops.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h> /* 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];
|
||||
|
|
|
@ -375,6 +375,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;
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -103,6 +103,24 @@ skip:
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -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
|
||||
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);
|
||||
|
||||
|
||||
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_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 @@ out:
|
|||
}
|
||||
|
||||
|
||||
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 @@ error2:
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <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 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
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue