deps: upgrade to libuv 1.25.0

PR-URL: https://github.com/nodejs/node/pull/25571
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
cjihrig 2019-01-18 13:37:29 -05:00
parent 27871c35b6
commit f698386c7e
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
38 changed files with 786 additions and 367 deletions

1
deps/uv/.mailmap vendored
View File

@ -45,3 +45,4 @@ Yazhong Liu <yorkiefixer@gmail.com>
Yuki Okumura <mjt@cltn.org>
jBarz <jBarz@users.noreply.github.com> <jbarboza@ca.ibm.com>
jBarz <jBarz@users.noreply.github.com> <jbarz@users.noreply.github.com>
ptlomholt <pt@lomholt.com>

4
deps/uv/AUTHORS vendored
View File

@ -362,3 +362,7 @@ Ashe Connor <ashe@kivikakk.ee>
Rick <lcw0622@163.com>
Ivan Krylov <krylov.r00t@gmail.com>
Michael Meier <michael.meier@leica-geosystems.com>
ptlomholt <pt@lomholt.com>
Victor Costan <pwnall@chromium.org>
sid <sidyhe@hotmail.com>
Kevin Adler <kadler@us.ibm.com>

View File

@ -167,6 +167,7 @@ set(uv_test_sources
test/test-udp-send-immediate.c
test/test-udp-send-unreachable.c
test/test-udp-try-send.c
test/test-uname.c
test/test-walk-handles.c
test/test-watcher-cross-stop.c)
@ -211,7 +212,7 @@ if(WIN32)
else()
list(APPEND uv_defines _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE)
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
# Android has pthread as part of its c library, not as a separate
# Android has pthread as part of its c library, not as a separate
# libpthread.so.
list(APPEND uv_libraries pthread)
endif()

51
deps/uv/ChangeLog vendored
View File

@ -1,3 +1,54 @@
2019.01.19, Version 1.25.0 (Stable), 4a10a9d425863330af199e4b74bd688e62d945f1
Changes since version 1.24.1:
* Revert "win,fs: retry if uv_fs_rename fails" (Ben Noordhuis)
* aix: manually trigger fs event monitoring (Gireesh Punathil)
* unix: rename WRITE_RETRY_ON_ERROR macro (Ben Noordhuis)
* darwin: DRY platform-specific error check (Ben Noordhuis)
* unix: refactor uv__write() (Ben Noordhuis)
* unix: don't send handle twice on partial write (Ben Noordhuis)
* tty,win: fix Alt+key under WSL (Bartosz Sosnowski)
* build: support running tests in out-of-tree builds (Jameson Nash)
* fsevents: really watch files with fsevents on macos 10.7+ (Jameson Nash)
* thread,mingw64: need intrin.h header for SSE2 MemoryBarrier (Jameson Nash)
* win: fix sizeof-pointer-div warning (cjihrig)
* unix,win: add uv_os_uname() (cjihrig)
* win, tty: fix CreateFileW() return value check (Bartosz Sosnowski)
* unix: enable IPv6 tests on OpenBSD (ptlomholt)
* test: fix test-ipc spawn_helper exit_cb (Santiago Gimeno)
* test: fix test-ipc tests (Santiago Gimeno)
* unix: better handling of unsupported F_FULLFSYNC (Victor Costan)
* win,test: de-flake fs_event_watch_dir_short_path (Refael Ackermann)
* win: fix msvc warning (sid)
* openbsd: switch to libuv's barrier implementation (ptlomholt)
* unix,stream: fix zero byte writes (Santiago Gimeno)
* ibmi: return EISDIR on read from directory fd (Kevin Adler)
* build: wrap long lines in Makefile.am (cjihrig)
2018.12.17, Version 1.24.1 (Stable), 274f2bd3b70847cadd9a3965577a87e666ab9ac3
Changes since version 1.24.0:

9
deps/uv/Makefile.am vendored
View File

@ -20,7 +20,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/include \
include_HEADERS=include/uv.h
uvincludedir = $(includedir)/uv
uvinclude_HEADERS=include/uv/errno.h include/uv/threadpool.h include/uv/version.h
uvinclude_HEADERS = include/uv/errno.h \
include/uv/threadpool.h \
include/uv/version.h
CLEANFILES =
@ -293,6 +295,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-udp-send-immediate.c \
test/test-udp-send-unreachable.c \
test/test-udp-try-send.c \
test/test-uname.c \
test/test-walk-handles.c \
test/test-watcher-cross-stop.c
test_run_tests_LDADD = libuv.la
@ -306,7 +309,9 @@ test_run_tests_SOURCES += test/runner-unix.c \
endif
if AIX
test_run_tests_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT
test_run_tests_CFLAGS += -D_ALL_SOURCE \
-D_XOPEN_SOURCE=500 \
-D_LINUX_SOURCE_COMPAT
endif
if LINUX

View File

@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
AC_INIT([libuv], [1.24.1], [https://github.com/libuv/libuv/issues])
AC_INIT([libuv], [1.25.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
@ -73,4 +73,6 @@ AS_CASE([$host_os], [kfreebsd*], [
])
AC_CHECK_HEADERS([sys/ahafs_evProds.h])
AC_CONFIG_FILES([Makefile libuv.pc])
AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file])
AC_CONFIG_LINKS([test/fixtures/load_error.node:test/fixtures/load_error.node])
AC_OUTPUT

View File

@ -233,15 +233,6 @@ API
Equivalent to :man:`rename(2)`.
.. note::
On Windows if this function fails with ``UV_EBUSY``, ``UV_EPERM`` or
``UV_EACCES``, it will retry to rename the file up to four times with
250ms wait between attempts before giving up. If both `path` and
`new_path` are existing directories this function will work only if
target directory is empty.
.. versionchanged:: 1.24.0 Added retrying and directory move support on Windows.
.. c:function:: int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
Equivalent to :man:`fsync(2)`.

View File

@ -145,6 +145,19 @@ Data types
char* homedir;
} uv_passwd_t;
.. c:type:: uv_utsname_t
Data type for operating system name and version information.
::
typedef struct uv_utsname_s {
char sysname[256];
char release[256];
char version[256];
char machine[256];
} uv_utsname_t;
API
---
@ -549,3 +562,12 @@ API
for others it will be silently reduced to `PRIORITY_HIGH`.
.. versionadded:: 1.23.0
.. c:function:: int uv_os_uname(uv_utsname_t* buffer)
Retrieves system information in `buffer`. The populated data includes the
operating system name, release, version, and machine. On non-Windows
systems, `uv_os_uname()` is a thin wrapper around :man:`uname(3)`. Returns
zero on success, and a non-zero error value otherwise.
.. versionadded:: 1.25.0

17
deps/uv/include/uv.h vendored
View File

@ -234,6 +234,7 @@ typedef struct uv_cpu_info_s uv_cpu_info_t;
typedef struct uv_interface_address_s uv_interface_address_t;
typedef struct uv_dirent_s uv_dirent_t;
typedef struct uv_passwd_s uv_passwd_t;
typedef struct uv_utsname_s uv_utsname_t;
typedef enum {
UV_LOOP_BLOCK_SIGNAL
@ -968,13 +969,13 @@ enum uv_process_flags {
*/
UV_PROCESS_WINDOWS_HIDE = (1 << 4),
/*
* Hide the subprocess console window that would normally be created. This
* Hide the subprocess console window that would normally be created. This
* option is only meaningful on Windows systems. On Unix it is silently
* ignored.
*/
UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5),
/*
* Hide the subprocess GUI window that would normally be created. This
* Hide the subprocess GUI window that would normally be created. This
* option is only meaningful on Windows systems. On Unix it is silently
* ignored.
*/
@ -1054,6 +1055,16 @@ struct uv_passwd_s {
char* homedir;
};
struct uv_utsname_s {
char sysname[256];
char release[256];
char version[256];
char machine[256];
/* This struct does not contain the nodename and domainname fields present in
the utsname type. domainname is a GNU extension. Both fields are referred
to as meaningless in the docs. */
};
typedef enum {
UV_DIRENT_UNKNOWN,
UV_DIRENT_FILE,
@ -1135,6 +1146,8 @@ UV_EXTERN int uv_os_unsetenv(const char* name);
UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
typedef enum {
UV_FS_UNKNOWN = -1,

View File

@ -136,7 +136,9 @@ typedef pthread_cond_t uv_cond_t;
typedef pthread_key_t uv_key_t;
/* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */
#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
#if defined(_AIX) || \
defined(__OpenBSD__) || \
!defined(PTHREAD_BARRIER_SERIAL_THREAD)
/* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */
struct _uv_barrier {
uv_mutex_t mutex;

View File

@ -31,8 +31,8 @@
*/
#define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 24
#define UV_VERSION_PATCH 1
#define UV_VERSION_MINOR 25
#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""

View File

@ -555,7 +555,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) {
sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1");
rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
if (rc < 0)
if (rc < 0 && errno != EBUSY)
return UV__ERR(errno);
return 0;
@ -728,10 +728,16 @@ int uv_fs_event_start(uv_fs_event_t* handle,
char cwd[PATH_MAX];
char absolute_path[PATH_MAX];
char readlink_cwd[PATH_MAX];
struct timeval zt;
fd_set pollfd;
/* Figure out whether filename is absolute or not */
if (filename[0] == '/') {
if (filename[0] == '\0') {
/* Missing a pathname */
return UV_ENOENT;
}
else if (filename[0] == '/') {
/* We have absolute pathname */
/* TODO(bnoordhuis) Check uv__strscpy() return value. */
uv__strscpy(absolute_path, filename, sizeof(absolute_path));
@ -768,6 +774,15 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
/* AHAFS wants someone to poll for it to start mointoring.
* so kick-start it so that we don't miss an event in the
* eventuality of an event that occurs in the current loop. */
do {
memset(&zt, 0, sizeof(zt));
FD_ZERO(&pollfd);
FD_SET(fd, &pollfd);
rc = select(fd + 1, &pollfd, NULL, NULL, &zt);
} while (rc == -1 && errno == EINTR);
return 0;
#else
return UV_ENOSYS;

View File

@ -52,13 +52,10 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
*/
if (ent->ifa_addr->sa_family == AF_LINK)
return 1;
#elif defined(__NetBSD__)
#elif defined(__NetBSD__) || defined(__OpenBSD__)
if (ent->ifa_addr->sa_family != PF_INET &&
ent->ifa_addr->sa_family != PF_INET6)
return 1;
#elif defined(__OpenBSD__)
if (ent->ifa_addr->sa_family != PF_INET)
return 1;
#endif
return 0;
}

View File

@ -40,6 +40,7 @@
#include <sys/uio.h> /* writev */
#include <sys/resource.h> /* getrusage */
#include <pwd.h>
#include <sys/utsname.h>
#ifdef __sun
# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
@ -1357,3 +1358,59 @@ int uv_os_setpriority(uv_pid_t pid, int priority) {
return 0;
}
int uv_os_uname(uv_utsname_t* buffer) {
struct utsname buf;
int r;
if (buffer == NULL)
return UV_EINVAL;
if (uname(&buf) == -1) {
r = UV__ERR(errno);
goto error;
}
r = uv__strscpy(buffer->sysname, buf.sysname, sizeof(buffer->sysname));
if (r == UV_E2BIG)
goto error;
#ifdef _AIX
r = snprintf(buffer->release,
sizeof(buffer->release),
"%s.%s",
buf.version,
buf.release);
if (r >= sizeof(buffer->release)) {
r = UV_E2BIG;
goto error;
}
#else
r = uv__strscpy(buffer->release, buf.release, sizeof(buffer->release));
if (r == UV_E2BIG)
goto error;
#endif
r = uv__strscpy(buffer->version, buf.version, sizeof(buffer->version));
if (r == UV_E2BIG)
goto error;
#if defined(_AIX) || defined(__PASE__)
r = uv__strscpy(buffer->machine, "ppc64", sizeof(buffer->machine));
#else
r = uv__strscpy(buffer->machine, buf.machine, sizeof(buffer->machine));
#endif
if (r == UV_E2BIG)
goto error;
return 0;
error:
buffer->sysname[0] = '\0';
buffer->release[0] = '\0';
buffer->version[0] = '\0';
buffer->machine[0] = '\0';
return r;
}

14
deps/uv/src/unix/fs.c vendored
View File

@ -155,7 +155,7 @@ static ssize_t uv__fs_fsync(uv_fs_t* req) {
int r;
r = fcntl(req->file, F_FULLFSYNC);
if (r != 0 && errno == ENOTTY)
if (r != 0)
r = fsync(req->file);
return r;
#else
@ -317,6 +317,18 @@ done:
req->bufs = NULL;
req->nbufs = 0;
#ifdef __PASE__
/* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
if (result == -1 && errno == EOPNOTSUPP) {
struct stat buf;
ssize_t rc;
rc = fstat(req->file, &buf);
if (rc == 0 && S_ISDIR(buf.st_mode)) {
errno = EISDIR;
}
}
#endif
return result;
}

View File

@ -255,42 +255,55 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
path = paths[i];
len = strlen(path);
if (handle->realpath_len == 0)
continue; /* This should be unreachable */
/* Filter out paths that are outside handle's request */
if (strncmp(path, handle->realpath, handle->realpath_len) != 0)
if (len < handle->realpath_len)
continue;
if (handle->realpath_len > 1 || *handle->realpath != '/') {
if (handle->realpath_len != len &&
path[handle->realpath_len] != '/')
/* Make sure that realpath actually named a directory,
* or that we matched the whole string */
continue;
if (memcmp(path, handle->realpath, handle->realpath_len) != 0)
continue;
if (!(handle->realpath_len == 1 && handle->realpath[0] == '/')) {
/* Remove common prefix, unless the watched folder is "/" */
path += handle->realpath_len;
len -= handle->realpath_len;
/* Skip forward slash */
if (*path != '\0') {
/* Ignore events with path equal to directory itself */
if (len <= 1 && (flags & kFSEventStreamEventFlagItemIsDir))
continue;
if (len == 0) {
/* Since we're using fsevents to watch the file itself,
* realpath == path, and we now need to get the basename of the file back
* (for commonality with other codepaths and platforms). */
while (len < handle->realpath_len && path[-1] != '/') {
path--;
len++;
}
/* Created and Removed seem to be always set, but don't make sense */
flags &= ~kFSEventsRenamed;
} else {
/* Skip forward slash */
path++;
len--;
}
}
#ifdef MAC_OS_X_VERSION_10_7
/* Ignore events with path equal to directory itself */
if (len == 0)
continue;
#else
if (len == 0 && (flags & kFSEventStreamEventFlagItemIsDir))
continue;
#endif /* MAC_OS_X_VERSION_10_7 */
/* Do not emit events from subdirectories (without option set) */
if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != 0) {
if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != '\0') {
pos = strchr(path + 1, '/');
if (pos != NULL)
continue;
}
#ifndef MAC_OS_X_VERSION_10_7
path = "";
len = 0;
#endif /* MAC_OS_X_VERSION_10_7 */
event = uv__malloc(sizeof(*event) + len);
if (event == NULL)
break;
@ -299,22 +312,11 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
memcpy(event->path, path, len + 1);
event->events = UV_RENAME;
#ifdef MAC_OS_X_VERSION_10_7
if (0 != (flags & kFSEventsModified) &&
0 == (flags & kFSEventsRenamed)) {
event->events = UV_CHANGE;
if (0 == (flags & kFSEventsRenamed)) {
if (0 != (flags & kFSEventsModified) ||
0 == (flags & kFSEventStreamEventFlagItemIsDir))
event->events = UV_CHANGE;
}
#else
if (0 != (flags & kFSEventsModified) &&
0 != (flags & kFSEventStreamEventFlagItemIsDir) &&
0 == (flags & kFSEventStreamEventFlagItemRenamed)) {
event->events = UV_CHANGE;
}
if (0 == (flags & kFSEventStreamEventFlagItemIsDir) &&
0 == (flags & kFSEventStreamEventFlagItemRenamed)) {
event->events = UV_CHANGE;
}
#endif /* MAC_OS_X_VERSION_10_7 */
QUEUE_INSERT_TAIL(&head, &event->member);
}

View File

@ -284,24 +284,6 @@ int uv__fsevents_init(uv_fs_event_t* handle);
int uv__fsevents_close(uv_fs_event_t* handle);
void uv__fsevents_loop_delete(uv_loop_t* loop);
/* OSX < 10.7 has no file events, polyfill them */
#ifndef MAC_OS_X_VERSION_10_7
static const int kFSEventStreamCreateFlagFileEvents = 0x00000010;
static const int kFSEventStreamEventFlagItemCreated = 0x00000100;
static const int kFSEventStreamEventFlagItemRemoved = 0x00000200;
static const int kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400;
static const int kFSEventStreamEventFlagItemRenamed = 0x00000800;
static const int kFSEventStreamEventFlagItemModified = 0x00001000;
static const int kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000;
static const int kFSEventStreamEventFlagItemChangeOwner = 0x00004000;
static const int kFSEventStreamEventFlagItemXattrMod = 0x00008000;
static const int kFSEventStreamEventFlagItemIsFile = 0x00010000;
static const int kFSEventStreamEventFlagItemIsDir = 0x00020000;
static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000;
#endif /* __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 */
#endif /* defined(__APPLE__) */
UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {

View File

@ -452,49 +452,48 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
const char* path,
unsigned int flags) {
#if defined(__APPLE__)
struct stat statbuf;
#endif /* defined(__APPLE__) */
int fd;
if (uv__is_active(handle))
return UV_EINVAL;
/* TODO open asynchronously - but how do we report back errors? */
fd = open(path, O_RDONLY);
if (fd == -1)
return UV__ERR(errno);
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
handle->path = uv__strdup(path);
handle->cb = cb;
#if defined(__APPLE__)
if (uv__has_forked_with_cfrunloop)
goto fallback;
/* Nullify field to perform checks later */
handle->cf_cb = NULL;
handle->realpath = NULL;
handle->realpath_len = 0;
handle->cf_flags = flags;
if (fstat(fd, &statbuf))
goto fallback;
/* FSEvents works only with directories */
if (!(statbuf.st_mode & S_IFDIR))
goto fallback;
/* The fallback fd is no longer needed */
uv__close(fd);
handle->event_watcher.fd = -1;
return uv__fsevents_init(handle);
fallback:
if (!uv__has_forked_with_cfrunloop) {
int r;
/* The fallback fd is not used */
handle->event_watcher.fd = -1;
handle->path = uv__strdup(path);
if (handle->path == NULL)
return UV_ENOMEM;
handle->cb = cb;
r = uv__fsevents_init(handle);
if (r == 0) {
uv__handle_start(handle);
} else {
uv__free(handle->path);
handle->path = NULL;
}
return r;
}
#endif /* defined(__APPLE__) */
/* TODO open asynchronously - but how do we report back errors? */
fd = open(path, O_RDONLY);
if (fd == -1)
return UV__ERR(errno);
handle->path = uv__strdup(path);
if (handle->path == NULL)
return UV_ENOMEM;
handle->cb = cb;
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
return 0;
@ -502,29 +501,29 @@ fallback:
int uv_fs_event_stop(uv_fs_event_t* handle) {
int r;
r = 0;
if (!uv__is_active(handle))
return 0;
uv__handle_stop(handle);
#if defined(__APPLE__)
if (uv__has_forked_with_cfrunloop || uv__fsevents_close(handle))
#endif /* defined(__APPLE__) */
{
if (!uv__has_forked_with_cfrunloop)
r = uv__fsevents_close(handle);
#endif
if (handle->event_watcher.fd != -1) {
uv__io_close(handle->loop, &handle->event_watcher);
uv__close(handle->event_watcher.fd);
handle->event_watcher.fd = -1;
}
uv__free(handle->path);
handle->path = NULL;
if (handle->event_watcher.fd != -1) {
/* When FSEvents is used, we don't use the event_watcher's fd under certain
* confitions. (see uv_fs_event_start) */
uv__close(handle->event_watcher.fd);
handle->event_watcher.fd = -1;
}
return 0;
return r;
}

View File

@ -58,11 +58,19 @@ struct uv__stream_select_s {
fd_set* swrite;
size_t swrite_sz;
};
# define WRITE_RETRY_ON_ERROR(send_handle) \
/* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
* EPROTOTYPE can be returned while trying to write to a socket that is
* shutting down. If we retry the write, we should get the expected EPIPE
* instead.
*/
# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR || errno == EPROTOTYPE)
# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
(errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
(errno == EMSGSIZE && send_handle))
(errno == EMSGSIZE && send_handle != NULL))
#else
# define WRITE_RETRY_ON_ERROR(send_handle) \
# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR)
# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
(errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
#endif /* defined(__APPLE__) */
@ -700,6 +708,14 @@ static void uv__drain(uv_stream_t* stream) {
}
static ssize_t uv__writev(int fd, struct iovec* vec, size_t n) {
if (n == 1)
return write(fd, vec->iov_base, vec->iov_len);
else
return writev(fd, vec, n);
}
static size_t uv__write_req_size(uv_write_t* req) {
size_t size;
@ -712,6 +728,37 @@ static size_t uv__write_req_size(uv_write_t* req) {
}
/* Returns 1 if all write request data has been written, or 0 if there is still
* more data to write.
*
* Note: the return value only says something about the *current* request.
* There may still be other write requests sitting in the queue.
*/
static int uv__write_req_update(uv_stream_t* stream,
uv_write_t* req,
size_t n) {
uv_buf_t* buf;
size_t len;
assert(n <= stream->write_queue_size);
stream->write_queue_size -= n;
buf = req->bufs + req->write_index;
do {
len = n < buf->len ? n : buf->len;
buf->base += len;
buf->len -= len;
buf += (buf->len == 0); /* Advance to next buffer if this one is empty. */
n -= len;
} while (n > 0);
req->write_index = buf - req->bufs;
return req->write_index == req->nbufs;
}
static void uv__write_req_finish(uv_write_t* req) {
uv_stream_t* stream = req->handle;
@ -832,102 +879,32 @@ start:
*pi = fd_to_send;
}
do {
do
n = sendmsg(uv__stream_fd(stream), &msg, 0);
}
#if defined(__APPLE__)
/*
* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
* EPROTOTYPE can be returned while trying to write to a socket that is
* shutting down. If we retry the write, we should get the expected EPIPE
* instead.
*/
while (n == -1 && (errno == EINTR || errno == EPROTOTYPE));
#else
while (n == -1 && errno == EINTR);
#endif
while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
/* Ensure the handle isn't sent again in case this is a partial write. */
if (n >= 0)
req->send_handle = NULL;
} else {
do {
if (iovcnt == 1) {
n = write(uv__stream_fd(stream), iov[0].iov_base, iov[0].iov_len);
} else {
n = writev(uv__stream_fd(stream), iov, iovcnt);
}
}
#if defined(__APPLE__)
/*
* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
* EPROTOTYPE can be returned while trying to write to a socket that is
* shutting down. If we retry the write, we should get the expected EPIPE
* instead.
*/
while (n == -1 && (errno == EINTR || errno == EPROTOTYPE));
#else
while (n == -1 && errno == EINTR);
#endif
do
n = uv__writev(uv__stream_fd(stream), iov, iovcnt);
while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
}
if (n < 0) {
if (!WRITE_RETRY_ON_ERROR(req->send_handle)) {
err = UV__ERR(errno);
goto error;
} else if (stream->flags & UV_HANDLE_BLOCKING_WRITES) {
/* If this is a blocking stream, try again. */
goto start;
}
} else {
/* Successful write */
while (n >= 0) {
uv_buf_t* buf = &(req->bufs[req->write_index]);
size_t len = buf->len;
assert(req->write_index < req->nbufs);
if ((size_t)n < len) {
buf->base += n;
buf->len -= n;
stream->write_queue_size -= n;
n = 0;
/* There is more to write. */
if (stream->flags & UV_HANDLE_BLOCKING_WRITES) {
/*
* If we're blocking then we should not be enabling the write
* watcher - instead we need to try again.
*/
goto start;
} else {
/* Break loop and ensure the watcher is pending. */
break;
}
} else {
/* Finished writing the buf at index req->write_index. */
req->write_index++;
assert((size_t)n >= len);
n -= len;
assert(stream->write_queue_size >= len);
stream->write_queue_size -= len;
if (req->write_index == req->nbufs) {
/* Then we're done! */
assert(n == 0);
uv__write_req_finish(req);
/* TODO: start trying to write the next request. */
return;
}
}
}
if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) {
err = UV__ERR(errno);
goto error;
}
/* Either we've counted n down to zero or we've got EAGAIN. */
assert(n == 0 || n == -1);
if (n >= 0 && uv__write_req_update(stream, req, n)) {
uv__write_req_finish(req);
return; /* TODO(bnoordhuis) Start trying to write the next request. */
}
/* Only non-blocking streams should use the write_watcher. */
assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES));
/* If this is a blocking stream, try again. */
if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
goto start;
/* We're not done. */
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);

View File

@ -48,8 +48,10 @@
STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
#endif
/* Note: guard clauses should match uv_barrier_t's in include/uv/uv-unix.h. */
#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
#if defined(_AIX) || \
defined(__OpenBSD__) || \
!defined(PTHREAD_BARRIER_SERIAL_THREAD)
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
struct _uv_barrier* b;
int rc;

View File

@ -760,14 +760,16 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
* IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case,
* and use the general uv__setsockopt_maybe_char call otherwise.
*/
#if defined(__sun) || defined(_AIX) || defined(__MVS__)
#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
defined(__MVS__)
if (handle->flags & UV_HANDLE_IPV6)
return uv__setsockopt(handle,
IP_MULTICAST_TTL,
IPV6_MULTICAST_HOPS,
&ttl,
sizeof(ttl));
#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */
#endif /* defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
defined(__MVS__) */
return uv__setsockopt_maybe_char(handle,
IP_MULTICAST_TTL,
@ -783,14 +785,16 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
* IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case,
* and use the general uv__setsockopt_maybe_char call otherwise.
*/
#if defined(__sun) || defined(_AIX) || defined(__MVS__)
#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
defined(__MVS__)
if (handle->flags & UV_HANDLE_IPV6)
return uv__setsockopt(handle,
IP_MULTICAST_LOOP,
IPV6_MULTICAST_LOOP,
&on,
sizeof(on));
#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */
#endif /* defined(__sun) || defined(_AIX) ||defined(__OpenBSD__) ||
defined(__MVS__) */
return uv__setsockopt_maybe_char(handle,
IP_MULTICAST_LOOP,

View File

@ -230,8 +230,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
*/
/* Convert to short path. */
short_path = short_path_buffer;
if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) {
if (GetShortPathNameW(pathw,
short_path_buffer,
ARRAY_SIZE(short_path_buffer))) {
short_path = short_path_buffer;
} else {
short_path = NULL;
}

72
deps/uv/src/win/fs.c vendored
View File

@ -42,8 +42,6 @@
#define UV_FS_FREE_PTR 0x0008
#define UV_FS_CLEANEDUP 0x0010
#define UV__RENAME_RETRIES 4
#define UV__RENAME_WAIT 250
#define INIT(subtype) \
do { \
@ -1360,78 +1358,12 @@ static void fs__fstat(uv_fs_t* req) {
static void fs__rename(uv_fs_t* req) {
int tries;
int sys_errno;
int result;
int try_rmdir;
WCHAR* src, *dst;
DWORD src_attrib, dst_attrib;
src = req->file.pathw;
dst = req->fs.info.new_pathw;
try_rmdir = 0;
/* Do some checks to fail early. */
src_attrib = GetFileAttributesW(src);
if (src_attrib == INVALID_FILE_ATTRIBUTES) {
if (!MoveFileExW(req->file.pathw, req->fs.info.new_pathw, MOVEFILE_REPLACE_EXISTING)) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
dst_attrib = GetFileAttributesW(dst);
if (dst_attrib != INVALID_FILE_ATTRIBUTES) {
if (dst_attrib & FILE_ATTRIBUTE_READONLY) {
req->result = UV_EPERM;
return;
}
/* Renaming folder to a folder name that already exist will fail on
* Windows. We will try to delete target folder first.
*/
if (src_attrib & FILE_ATTRIBUTE_DIRECTORY &&
dst_attrib & FILE_ATTRIBUTE_DIRECTORY)
try_rmdir = 1;
}
/* Sometimes an antivirus or indexing software can lock the target or the
* source file/directory. This is annoying for users, in such cases we will
* retry couple of times with some delay before failing.
*/
for (tries = 0; tries < UV__RENAME_RETRIES; ++tries) {
if (tries > 0)
Sleep(UV__RENAME_WAIT);
if (try_rmdir) {
result = _wrmdir(dst) == 0 ? 0 : uv_translate_sys_error(_doserrno);
switch (result)
{
case 0:
case UV_ENOENT:
/* Folder removed or did not exist at all. */
try_rmdir = 0;
break;
case UV_ENOTEMPTY:
/* Non-empty target folder, fail instantly. */
SET_REQ_RESULT(req, -1);
return;
default:
/* All other errors - try to move file anyway and handle the error
* there, retrying folder deletion next time around.
*/
break;
}
}
if (MoveFileExW(src, dst, MOVEFILE_REPLACE_EXISTING) != 0) {
SET_REQ_RESULT(req, 0);
return;
}
sys_errno = GetLastError();
result = uv_translate_sys_error(sys_errno);
if (result != UV_EBUSY && result != UV_EPERM && result != UV_EACCES)
break;
}
req->sys_errno_ = sys_errno;
req->result = result;
SET_REQ_RESULT(req, 0);
}

View File

@ -1310,7 +1310,6 @@ static int uv__pipe_write_data(uv_loop_t* loop,
uv_pipe_t* handle,
const uv_buf_t bufs[],
size_t nbufs,
uv_stream_t* send_handle,
uv_write_cb cb,
int copy_always) {
int err;
@ -1321,7 +1320,7 @@ static int uv__pipe_write_data(uv_loop_t* loop,
UV_REQ_INIT(req, UV_WRITE);
req->handle = (uv_stream_t*) handle;
req->send_handle = send_handle;
req->send_handle = NULL;
req->cb = cb;
/* Private fields. */
req->coalesced = 0;
@ -1558,8 +1557,7 @@ int uv__pipe_write_ipc(uv_loop_t* loop,
/* Write buffers. We set the `always_copy` flag, so it is not a problem that
* some of the written data lives on the stack. */
err = uv__pipe_write_data(
loop, req, handle, bufs, buf_count, send_handle, cb, 1);
err = uv__pipe_write_data(loop, req, handle, bufs, buf_count, cb, 1);
/* If we had to heap-allocate the bufs array, free it now. */
if (bufs != stack_bufs) {
@ -1583,8 +1581,7 @@ int uv__pipe_write(uv_loop_t* loop,
} else {
/* Non-IPC pipe write: put data on the wire directly. */
assert(send_handle == NULL);
return uv__pipe_write_data(
loop, req, handle, bufs, nbufs, NULL, cb, 0);
return uv__pipe_write_data(loop, req, handle, bufs, nbufs, cb, 0);
}
}

View File

@ -23,6 +23,12 @@
#include <limits.h>
#include <stdlib.h>
#if defined(__MINGW64_VERSION_MAJOR)
/* MemoryBarrier expands to __mm_mfence in some cases (x86+sse2), which may
* require this header in some versions of mingw64. */
#include <intrin.h>
#endif
#include "uv.h"
#include "internal.h"

View File

@ -164,7 +164,7 @@ void uv_console_init(void) {
OPEN_EXISTING,
0,
0);
if (uv__tty_console_handle != NULL) {
if (uv__tty_console_handle != INVALID_HANDLE_VALUE) {
QueueUserWorkItem(uv__tty_console_resize_message_loop_thread,
NULL,
WT_EXECUTELONGFUNCTION);
@ -360,6 +360,8 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
}
} else {
was_reading = 0;
alloc_cb = NULL;
read_cb = NULL;
}
uv_sem_wait(&uv_tty_output_lock);
@ -733,8 +735,9 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
/* Ignore keyup events, unless the left alt key was held and a valid
* unicode character was emitted. */
if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) ||
KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) {
if (!KEV.bKeyDown &&
KEV.wVirtualKeyCode != VK_MENU &&
KEV.uChar.UnicodeChar != 0) {
continue;
}

117
deps/uv/src/win/util.c vendored
View File

@ -1627,3 +1627,120 @@ int uv_os_setpriority(uv_pid_t pid, int priority) {
CloseHandle(handle);
return r;
}
int uv_os_uname(uv_utsname_t* buffer) {
/* Implementation loosely based on
https://github.com/gagern/gnulib/blob/master/lib/uname.c */
OSVERSIONINFOW os_info;
SYSTEM_INFO system_info;
int processor_level;
int r;
if (buffer == NULL)
return UV_EINVAL;
uv__once_init();
os_info.dwOSVersionInfoSize = sizeof(os_info);
os_info.szCSDVersion[0] = L'\0';
/* Try calling RtlGetVersion(), and fall back to the deprecated GetVersionEx()
if RtlGetVersion() is not available. */
if (pRtlGetVersion) {
pRtlGetVersion(&os_info);
} else {
/* Silence GetVersionEx() deprecation warning. */
#pragma warning(suppress : 4996)
if (GetVersionExW(&os_info) == 0) {
r = uv_translate_sys_error(GetLastError());
goto error;
}
}
/* Populate the version field. */
if (WideCharToMultiByte(CP_UTF8,
0,
os_info.szCSDVersion,
-1,
buffer->version,
sizeof(buffer->version),
NULL,
NULL) == 0) {
r = uv_translate_sys_error(GetLastError());
goto error;
}
/* Populate the sysname field. */
#ifdef __MINGW32__
r = snprintf(buffer->sysname,
sizeof(buffer->sysname),
"MINGW32_NT-%u.%u",
(unsigned int) os_info.dwMajorVersion,
(unsigned int) os_info.dwMinorVersion);
assert(r < sizeof(buffer->sysname));
#else
uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname));
#endif
/* Populate the release field. */
r = snprintf(buffer->release,
sizeof(buffer->release),
"%d.%d.%d",
(unsigned int) os_info.dwMajorVersion,
(unsigned int) os_info.dwMinorVersion,
(unsigned int) os_info.dwBuildNumber);
assert(r < sizeof(buffer->release));
/* Populate the machine field. */
GetSystemInfo(&system_info);
switch (system_info.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64:
uv__strscpy(buffer->machine, "x86_64", sizeof(buffer->machine));
break;
case PROCESSOR_ARCHITECTURE_IA64:
uv__strscpy(buffer->machine, "ia64", sizeof(buffer->machine));
break;
case PROCESSOR_ARCHITECTURE_INTEL:
uv__strscpy(buffer->machine, "i386", sizeof(buffer->machine));
if (system_info.wProcessorLevel > 3) {
processor_level = system_info.wProcessorLevel < 6 ?
system_info.wProcessorLevel : 6;
buffer->machine[1] = '0' + processor_level;
}
break;
case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
uv__strscpy(buffer->machine, "i686", sizeof(buffer->machine));
break;
case PROCESSOR_ARCHITECTURE_MIPS:
uv__strscpy(buffer->machine, "mips", sizeof(buffer->machine));
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
case PROCESSOR_ARCHITECTURE_ALPHA64:
uv__strscpy(buffer->machine, "alpha", sizeof(buffer->machine));
break;
case PROCESSOR_ARCHITECTURE_PPC:
uv__strscpy(buffer->machine, "powerpc", sizeof(buffer->machine));
break;
case PROCESSOR_ARCHITECTURE_SHX:
uv__strscpy(buffer->machine, "sh", sizeof(buffer->machine));
break;
case PROCESSOR_ARCHITECTURE_ARM:
uv__strscpy(buffer->machine, "arm", sizeof(buffer->machine));
break;
default:
uv__strscpy(buffer->machine, "unknown", sizeof(buffer->machine));
break;
}
return 0;
error:
buffer->sysname[0] = '\0';
buffer->release[0] = '\0';
buffer->version[0] = '\0';
buffer->machine[0] = '\0';
return r;
}

View File

@ -26,6 +26,7 @@
/* Ntdll function pointers */
sRtlGetVersion pRtlGetVersion;
sRtlNtStatusToDosError pRtlNtStatusToDosError;
sNtDeviceIoControlFile pNtDeviceIoControlFile;
sNtQueryInformationFile pNtQueryInformationFile;
@ -55,6 +56,9 @@ void uv_winapi_init(void) {
uv_fatal_error(GetLastError(), "GetModuleHandleA");
}
pRtlGetVersion = (sRtlGetVersion) GetProcAddress(ntdll_module,
"RtlGetVersion");
pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(
ntdll_module,
"RtlNtStatusToDosError");

View File

@ -4519,6 +4519,9 @@ typedef VOID (NTAPI *PIO_APC_ROUTINE)
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved);
typedef NTSTATUS (NTAPI *sRtlGetVersion)
(PRTL_OSVERSIONINFOW lpVersionInformation);
typedef ULONG (NTAPI *sRtlNtStatusToDosError)
(NTSTATUS Status);
@ -4707,6 +4710,7 @@ typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook)
/* Ntdll function pointers */
extern sRtlGetVersion pRtlGetVersion;
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
extern sNtQueryInformationFile pNtQueryInformationFile;

View File

@ -42,6 +42,7 @@ int ipc_helper_tcp_connection(void);
int ipc_helper_closed_handle(void);
int ipc_send_recv_helper(void);
int ipc_helper_bind_twice(void);
int ipc_helper_send_zero(void);
int stdio_over_pipes_helper(void);
int spawn_stdin_stdout(void);
int spawn_tcp_server_helper(void);
@ -104,6 +105,10 @@ static int maybe_run_test(int argc, char **argv) {
return ipc_helper_bind_twice();
}
if (strcmp(argv[1], "ipc_helper_send_zero") == 0) {
return ipc_helper_send_zero();
}
if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
return stdio_over_pipes_helper();
}

View File

@ -480,6 +480,8 @@ TEST_IMPL(fs_event_watch_dir_recursive) {
#ifdef _WIN32
TEST_IMPL(fs_event_watch_dir_short_path) {
uv_loop_t* loop;
uv_fs_t req;
int has_shortnames;
int r;
/* Setup */
@ -489,26 +491,37 @@ TEST_IMPL(fs_event_watch_dir_short_path) {
create_dir("watch_dir");
create_file("watch_dir/file1");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_cb_dir, "watch_~1", 0);
ASSERT(r == 0);
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
r = uv_timer_start(&timer, timer_cb_file, 100, 0);
ASSERT(r == 0);
/* Newer version of Windows ship with
HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation
not equal to 0. So we verify the files we created are addressable by a 8.3
short name */
has_shortnames = uv_fs_stat(NULL, &req, "watch_~1", NULL) != UV_ENOENT;
if (has_shortnames) {
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_cb_dir, "watch_~1", 0);
ASSERT(r == 0);
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
r = uv_timer_start(&timer, timer_cb_file, 100, 0);
ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(fs_event_cb_called == 1);
ASSERT(timer_cb_called == 1);
ASSERT(close_cb_called == 1);
ASSERT(fs_event_cb_called == 1);
ASSERT(timer_cb_called == 1);
ASSERT(close_cb_called == 1);
}
/* Cleanup */
remove("watch_dir/file1");
remove("watch_dir/");
MAKE_VALGRIND_HAPPY();
if (!has_shortnames)
RETURN_SKIP("Was not able to address files with 8.3 short name.");
return 0;
}
#endif
@ -576,6 +589,14 @@ TEST_IMPL(fs_event_watch_file_exact_path) {
create_dir("watch_dir");
create_file("watch_dir/file.js");
create_file("watch_dir/file.jsx");
#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12)
/* Empirically, FSEvents seems to (reliably) report the preceeding
* create_file events prior to macOS 10.11.6 in the subsequent fs_watch
* creation, but that behavior hasn't been observed to occur on newer
* versions. Give a long delay here to let the system settle before running
* the test. */
uv_sleep(1100);
#endif
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -648,7 +669,7 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
r = uv_timer_start(&timer, timer_cb_touch, 100, 0);
r = uv_timer_start(&timer, timer_cb_touch, 1100, 0);
ASSERT(r == 0);
ASSERT(timer_cb_touch_called == 0);
@ -936,32 +957,48 @@ TEST_IMPL(fs_event_getpath) {
RETURN_SKIP(NO_FS_EVENTS);
#endif
uv_loop_t* loop = uv_default_loop();
unsigned i;
int r;
char buf[1024];
size_t len;
const char* const watch_dir[] = {
"watch_dir",
"watch_dir/",
"watch_dir///",
"watch_dir/subfolder/..",
"watch_dir//subfolder//..//",
};
create_dir("watch_dir");
create_dir("watch_dir/subfolder");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
len = sizeof buf;
r = uv_fs_event_getpath(&fs_event, buf, &len);
ASSERT(r == UV_EINVAL);
r = uv_fs_event_start(&fs_event, fail_cb, "watch_dir", 0);
ASSERT(r == 0);
len = sizeof buf;
r = uv_fs_event_getpath(&fs_event, buf, &len);
ASSERT(r == 0);
ASSERT(buf[len - 1] != 0);
ASSERT(buf[len] == '\0');
ASSERT(memcmp(buf, "watch_dir", len) == 0);
r = uv_fs_event_stop(&fs_event);
ASSERT(r == 0);
uv_close((uv_handle_t*) &fs_event, close_cb);
uv_run(loop, UV_RUN_DEFAULT);
for (i = 0; i < ARRAY_SIZE(watch_dir); i++) {
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
len = sizeof buf;
r = uv_fs_event_getpath(&fs_event, buf, &len);
ASSERT(r == UV_EINVAL);
r = uv_fs_event_start(&fs_event, fail_cb, watch_dir[i], 0);
ASSERT(r == 0);
len = 0;
r = uv_fs_event_getpath(&fs_event, buf, &len);
ASSERT(r == UV_ENOBUFS);
ASSERT(len < sizeof buf); /* sanity check */
ASSERT(len == strlen(watch_dir[i]) + 1);
r = uv_fs_event_getpath(&fs_event, buf, &len);
ASSERT(r == 0);
ASSERT(len == strlen(watch_dir[i]));
ASSERT(strcmp(buf, watch_dir[i]) == 0);
r = uv_fs_event_stop(&fs_event);
ASSERT(r == 0);
uv_close((uv_handle_t*) &fs_event, close_cb);
ASSERT(close_cb_called == 1);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(close_cb_called == 1);
close_cb_called = 0;
}
remove("watch_dir/");
MAKE_VALGRIND_HAPPY();
@ -1082,6 +1119,9 @@ TEST_IMPL(fs_event_watch_invalid_path) {
r = uv_fs_event_start(&fs_event, fs_event_cb_file, "<:;", 0);
ASSERT(r != 0);
ASSERT(uv_is_active((uv_handle_t*) &fs_event) == 0);
r = uv_fs_event_start(&fs_event, fs_event_cb_file, "", 0);
ASSERT(r != 0);
ASSERT(uv_is_active((uv_handle_t*) &fs_event) == 0);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -55,7 +55,7 @@ static void write_cb(uv_write_t* req, int status) {
}
static void shutdown_cb(uv_shutdown_t* req, int status) {
ASSERT(status == 0);
ASSERT(status == 0 || status == UV_ENOTCONN);
uv_close((uv_handle_t*) req->handle, NULL);
}

View File

@ -149,7 +149,6 @@ static void connect_cb(uv_connect_t* req, int status) {
&ctx.send.stream,
NULL);
ASSERT(r == 0);
ASSERT(ctx.write_req.send_handle == &ctx.send.stream);
/* Perform two writes to the same pipe to make sure that on Windows we are
* not running into issue 505:
@ -161,7 +160,6 @@ static void connect_cb(uv_connect_t* req, int status) {
&ctx.send2.stream,
NULL);
ASSERT(r == 0);
ASSERT(ctx.write_req2.send_handle == &ctx.send2.stream);
r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb);
ASSERT(r == 0);
@ -346,7 +344,6 @@ static void read_cb(uv_stream_t* handle,
&recv->stream,
write2_cb);
ASSERT(r == 0);
ASSERT(write_req->send_handle == &recv->stream);
} while (uv_pipe_pending_count(pipe) > 0);
}

View File

@ -39,12 +39,15 @@ static int local_conn_accepted;
static int remote_conn_accepted;
static int tcp_server_listening;
static uv_write_t write_req;
static uv_write_t write_req2;
static uv_write_t conn_notify_req;
static int close_cb_called;
static int connection_accepted;
static int tcp_conn_read_cb_called;
static int tcp_conn_write_cb_called;
static int closed_handle_data_read;
static int closed_handle_write;
static int send_zero_write;
typedef struct {
uv_connect_t conn_req;
@ -54,7 +57,15 @@ typedef struct {
#define CONN_COUNT 100
#define BACKLOG 128
#define LARGE_SIZE 1000000
#define LARGE_SIZE 100000
static uv_buf_t large_buf;
static char buffer[LARGE_SIZE];
static uv_write_t write_reqs[300];
static int write_reqs_completed;
static unsigned int write_until_data_queued(void);
static void send_handle_and_close(void);
static void close_server_conn_cb(uv_handle_t* handle) {
@ -92,6 +103,7 @@ static void exit_cb(uv_process_t* process,
printf("exit_cb\n");
exit_cb_called++;
ASSERT(exit_status == 0);
ASSERT(term_signal == 0);
uv_close((uv_handle_t*)process, NULL);
}
@ -420,6 +432,14 @@ static void on_read_closed_handle(uv_stream_t* handle,
#endif
static void on_read_send_zero(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf) {
ASSERT(nread == 0 || nread == UV_EOF);
free(buf->base);
}
static int run_ipc_test(const char* helper, uv_read_cb read_cb) {
uv_process_t process;
int r;
@ -544,6 +564,13 @@ TEST_IMPL(ipc_listen_after_bind_twice) {
}
#endif
TEST_IMPL(ipc_send_zero) {
int r;
r = run_ipc_test("ipc_helper_send_zero", on_read_send_zero);
ASSERT(r == 0);
return 0;
}
/* Everything here runs in a child process. */
@ -573,14 +600,25 @@ static void tcp_connection_write_cb(uv_write_t* req, int status) {
static void closed_handle_large_write_cb(uv_write_t* req, int status) {
ASSERT(status == 0);
ASSERT(closed_handle_data_read = LARGE_SIZE);
if (++write_reqs_completed == ARRAY_SIZE(write_reqs)) {
write_reqs_completed = 0;
if (write_until_data_queued() > 0)
send_handle_and_close();
}
}
static void closed_handle_write_cb(uv_write_t* req, int status) {
ASSERT(status == UV_EBADF);
closed_handle_write = 1;
}
static void send_zero_write_cb(uv_write_t* req, int status) {
ASSERT(status == 0);
send_zero_write++;
}
static void on_tcp_child_process_read(uv_stream_t* tcp,
ssize_t nread,
const uv_buf_t* buf) {
@ -688,7 +726,6 @@ int ipc_helper(int listen_after_write) {
* over which a handle will be transmitted.
*/
struct sockaddr_in addr;
uv_write_t write_req;
int r;
uv_buf_t buf;
@ -788,14 +825,53 @@ int ipc_helper_tcp_connection(void) {
return 0;
}
static unsigned int write_until_data_queued() {
unsigned int i;
int r;
i = 0;
do {
r = uv_write(&write_reqs[i],
(uv_stream_t*)&channel,
&large_buf,
1,
closed_handle_large_write_cb);
ASSERT(r == 0);
i++;
} while (((uv_stream_t*)&channel)->write_queue_size == 0 &&
i < ARRAY_SIZE(write_reqs));
return ((uv_stream_t*)&channel)->write_queue_size;
}
static void send_handle_and_close() {
int r;
struct sockaddr_in addr;
r = uv_tcp_init(uv_default_loop(), &tcp_server);
ASSERT(r == 0);
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
ASSERT(r == 0);
r = uv_write2(&write_req,
(uv_stream_t*)&channel,
&large_buf,
1,
(uv_stream_t*)&tcp_server,
closed_handle_write_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)&tcp_server, NULL);
}
int ipc_helper_closed_handle(void) {
int r;
struct sockaddr_in addr;
uv_write_t write_req;
uv_write_t write_req2;
uv_buf_t buf;
char buffer[LARGE_SIZE];
memset(buffer, '.', LARGE_SIZE);
large_buf = uv_buf_init(buffer, LARGE_SIZE);
r = uv_pipe_init(uv_default_loop(), &channel, 1);
ASSERT(r == 0);
@ -806,37 +882,14 @@ int ipc_helper_closed_handle(void) {
ASSERT(1 == uv_is_writable((uv_stream_t*) &channel));
ASSERT(0 == uv_is_closing((uv_handle_t*) &channel));
memset(buffer, '.', LARGE_SIZE);
buf = uv_buf_init(buffer, LARGE_SIZE);
r = uv_tcp_init(uv_default_loop(), &tcp_server);
ASSERT(r == 0);
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
ASSERT(r == 0);
r = uv_write(&write_req,
(uv_stream_t*)&channel,
&buf,
1,
closed_handle_large_write_cb);
ASSERT(r == 0);
r = uv_write2(&write_req2,
(uv_stream_t*)&channel,
&buf,
1,
(uv_stream_t*)&tcp_server,
closed_handle_write_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*)&tcp_server, NULL);
if (write_until_data_queued() > 0)
send_handle_and_close();
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(closed_handle_write == 1);
MAKE_VALGRIND_HAPPY();
return 0;
}
@ -848,8 +901,6 @@ int ipc_helper_bind_twice(void) {
* over which two handles will be transmitted.
*/
struct sockaddr_in addr;
uv_write_t write_req;
uv_write_t write_req2;
int r;
uv_buf_t buf;
@ -889,3 +940,35 @@ int ipc_helper_bind_twice(void) {
MAKE_VALGRIND_HAPPY();
return 0;
}
int ipc_helper_send_zero(void) {
int r;
uv_buf_t zero_buf;
zero_buf = uv_buf_init(0, 0);
r = uv_pipe_init(uv_default_loop(), &channel, 0);
ASSERT(r == 0);
uv_pipe_open(&channel, 0);
ASSERT(1 == uv_is_readable((uv_stream_t*) &channel));
ASSERT(1 == uv_is_writable((uv_stream_t*) &channel));
ASSERT(0 == uv_is_closing((uv_handle_t*) &channel));
r = uv_write(&write_req,
(uv_stream_t*)&channel,
&zero_buf,
1,
send_zero_write_cb);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(send_zero_write == 1);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -69,6 +69,7 @@ TEST_DECLARE (ipc_send_recv_pipe_inprocess)
TEST_DECLARE (ipc_send_recv_tcp)
TEST_DECLARE (ipc_send_recv_tcp_inprocess)
TEST_DECLARE (ipc_tcp_connection)
TEST_DECLARE (ipc_send_zero)
#ifndef _WIN32
TEST_DECLARE (ipc_closed_handle)
#endif
@ -436,9 +437,13 @@ TEST_DECLARE (fork_socketpair)
TEST_DECLARE (fork_socketpair_started)
TEST_DECLARE (fork_signal_to_child)
TEST_DECLARE (fork_signal_to_child_closed)
#ifndef __APPLE__ /* This is forbidden in a fork child: The process has forked
and you cannot use this CoreFoundation functionality
safely. You MUST exec(). */
TEST_DECLARE (fork_fs_events_child)
TEST_DECLARE (fork_fs_events_child_dir)
TEST_DECLARE (fork_fs_events_file_parent_child)
#endif
#ifndef __MVS__
TEST_DECLARE (fork_threadpool_queue_work_simple)
#endif
@ -446,6 +451,7 @@ TEST_DECLARE (fork_threadpool_queue_work_simple)
TEST_DECLARE (idna_toascii)
TEST_DECLARE (utf8_decode1)
TEST_DECLARE (uname)
TASK_LIST_START
TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000)
@ -510,6 +516,7 @@ TASK_LIST_START
TEST_ENTRY (ipc_send_recv_tcp)
TEST_ENTRY (ipc_send_recv_tcp_inprocess)
TEST_ENTRY (ipc_tcp_connection)
TEST_ENTRY (ipc_send_zero)
#ifndef _WIN32
TEST_ENTRY (ipc_closed_handle)
#endif
@ -945,15 +952,18 @@ TASK_LIST_START
TEST_ENTRY (fork_socketpair_started)
TEST_ENTRY (fork_signal_to_child)
TEST_ENTRY (fork_signal_to_child_closed)
#ifndef __APPLE__
TEST_ENTRY (fork_fs_events_child)
TEST_ENTRY (fork_fs_events_child_dir)
TEST_ENTRY (fork_fs_events_file_parent_child)
#endif
#ifndef __MVS__
TEST_ENTRY (fork_threadpool_queue_work_simple)
#endif
#endif
TEST_ENTRY (utf8_decode1)
TEST_ENTRY (uname)
/* Doesn't work on z/OS because that platform uses EBCDIC, not ASCII. */
#ifndef __MVS__

View File

@ -35,6 +35,7 @@ TEST_IMPL(platform_output) {
uv_cpu_info_t* cpus;
uv_interface_address_t* interfaces;
uv_passwd_t pwd;
uv_utsname_t uname;
int count;
int i;
int err;
@ -153,5 +154,13 @@ TEST_IMPL(platform_output) {
ASSERT(ppid > 0);
printf("uv_os_getppid: %d\n", (int) ppid);
err = uv_os_uname(&uname);
ASSERT(err == 0);
printf("uv_os_uname:\n");
printf(" sysname: %s\n", uname.sysname);
printf(" release: %s\n", uname.release);
printf(" version: %s\n", uname.version);
printf(" machine: %s\n", uname.machine);
return 0;
}

69
deps/uv/test/test-uname.c vendored Normal file
View File

@ -0,0 +1,69 @@
/* Copyright libuv project contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <string.h>
#ifndef _WIN32
# include <sys/utsname.h>
#endif
TEST_IMPL(uname) {
#ifndef _WIN32
struct utsname buf;
#endif
#ifdef _AIX
char temp[256];
#endif
uv_utsname_t buffer;
int r;
/* Verify that NULL is handled properly. */
r = uv_os_uname(NULL);
ASSERT(r == UV_EINVAL);
/* Verify the happy path. */
r = uv_os_uname(&buffer);
ASSERT(r == 0);
#ifndef _WIN32
ASSERT(uname(&buf) != -1);
ASSERT(strcmp(buffer.sysname, buf.sysname) == 0);
ASSERT(strcmp(buffer.version, buf.version) == 0);
# ifdef _AIX
snprintf(temp, sizeof(temp), "%s.%s", buf.version, buf.release);
ASSERT(strcmp(buffer.release, temp) == 0);
# else
ASSERT(strcmp(buffer.release, buf.release) == 0);
# endif /* _AIX */
# if defined(_AIX) || defined(__PASE__)
ASSERT(strcmp(buffer.machine, "ppc64") == 0);
# else
ASSERT(strcmp(buffer.machine, buf.machine) == 0);
# endif /* defined(_AIX) || defined(__PASE__) */
#endif /* _WIN32 */
return 0;
}

View File

@ -154,6 +154,7 @@
'test-udp-multicast-interface.c',
'test-udp-multicast-interface6.c',
'test-udp-try-send.c',
'test-uname.c',
],
'conditions': [
[ 'OS=="win"', {