summaryrefslogtreecommitdiff
path: root/deps/uv/src
diff options
context:
space:
mode:
authorSaúl Ibarra Corretgé <saghul@gmail.com>2016-05-17 00:25:23 +0200
committerSaúl Ibarra Corretgé <saghul@gmail.com>2016-05-17 02:28:48 +0200
commitb78a7043699093c46d5d71992184f4c40ab5c4b5 (patch)
tree7ee0fc8474ae60c4be545965ae18882ef1964027 /deps/uv/src
parentf293d0b0c85b2d1b9e0d3938dd38cf1cacac6970 (diff)
downloadandroid-node-v8-b78a7043699093c46d5d71992184f4c40ab5c4b5.tar.gz
android-node-v8-b78a7043699093c46d5d71992184f4c40ab5c4b5.tar.bz2
android-node-v8-b78a7043699093c46d5d71992184f4c40ab5c4b5.zip
deps: upgrade libuv to 1.9.1
Fixes: https://github.com/nodejs/node/issues/4002 Fixes: https://github.com/nodejs/node/issues/5384 Fixes: https://github.com/nodejs/node/issues/6563 Refs: https://github.com/nodejs/node/issues/2680#issuecomment-213521708 PR-URL: https://github.com/nodejs/node/pull/6796 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Johan Bergström <bugs@bergstroem.nu> Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/uv/src')
-rw-r--r--deps/uv/src/unix/aix.c82
-rw-r--r--deps/uv/src/unix/async.c4
-rw-r--r--deps/uv/src/unix/core.c10
-rw-r--r--deps/uv/src/unix/freebsd.c8
-rw-r--r--deps/uv/src/unix/fs.c15
-rw-r--r--deps/uv/src/unix/internal.h58
-rw-r--r--deps/uv/src/unix/kqueue.c38
-rw-r--r--deps/uv/src/unix/linux-core.c69
-rw-r--r--deps/uv/src/unix/linux-inotify.c2
-rw-r--r--deps/uv/src/unix/linux-syscalls.h8
-rw-r--r--deps/uv/src/unix/openbsd.c4
-rw-r--r--deps/uv/src/unix/pipe.c4
-rw-r--r--deps/uv/src/unix/poll.c14
-rw-r--r--deps/uv/src/unix/pthread-barrier.c120
-rw-r--r--deps/uv/src/unix/pthread-fixes.c70
-rw-r--r--deps/uv/src/unix/signal.c2
-rw-r--r--deps/uv/src/unix/stream.c70
-rw-r--r--deps/uv/src/unix/sunos.c20
-rw-r--r--deps/uv/src/unix/tcp.c4
-rw-r--r--deps/uv/src/unix/thread.c109
-rw-r--r--deps/uv/src/unix/udp.c20
-rw-r--r--deps/uv/src/uv-common.c29
-rw-r--r--deps/uv/src/win/fs-event.c61
-rw-r--r--deps/uv/src/win/fs.c18
-rw-r--r--deps/uv/src/win/internal.h3
-rw-r--r--deps/uv/src/win/tty.c174
-rw-r--r--deps/uv/src/win/util.c108
27 files changed, 631 insertions, 493 deletions
diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c
index bcaa5ee50b..2276985fc0 100644
--- a/deps/uv/src/unix/aix.c
+++ b/deps/uv/src/unix/aix.c
@@ -118,6 +118,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
uv__io_t* w;
uint64_t base;
uint64_t diff;
+ int have_signals;
int nevents;
int count;
int nfds;
@@ -225,6 +226,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
goto update_timeout;
}
+ have_signals = 0;
nevents = 0;
assert(loop->watchers != NULL);
@@ -255,13 +257,26 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
continue;
}
- w->cb(loop, w, pe->revents);
+ /* Run signal watchers last. This also affects child process watchers
+ * because those are implemented in terms of signal watchers.
+ */
+ if (w == &loop->signal_io_watcher)
+ have_signals = 1;
+ else
+ w->cb(loop, w, pe->revents);
+
nevents++;
}
+ if (have_signals != 0)
+ loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
+
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;
+ if (have_signals != 0)
+ return; /* Event loop should cycle now so don't poll again. */
+
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
/* Poll for more events but don't block this time. */
@@ -782,53 +797,30 @@ int uv_fs_event_start(uv_fs_event_t* handle,
const char* filename,
unsigned int flags) {
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
- int fd, rc, i = 0, res = 0;
+ int fd, rc, str_offset = 0;
char cwd[PATH_MAX];
char absolute_path[PATH_MAX];
- char fname[PATH_MAX];
- char *p;
+ char readlink_cwd[PATH_MAX];
- /* Clean all the buffers*/
- for(i = 0; i < PATH_MAX; i++) {
- cwd[i] = 0;
- absolute_path[i] = 0;
- fname[i] = 0;
- }
- i = 0;
/* Figure out whether filename is absolute or not */
if (filename[0] == '/') {
- /* We have absolute pathname, create the relative pathname*/
- sprintf(absolute_path, filename);
- p = strrchr(filename, '/');
- p++;
+ /* We have absolute pathname */
+ snprintf(absolute_path, sizeof(absolute_path), "%s", filename);
} else {
- if (filename[0] == '.' && filename[1] == '/') {
- /* We have a relative pathname, compose the absolute pathname */
- sprintf(fname, filename);
- snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
- res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1);
- if (res < 0)
- return res;
- p = strrchr(absolute_path, '/');
- p++;
- p++;
- } else {
- /* We have a relative pathname, compose the absolute pathname */
- sprintf(fname, filename);
- snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
- res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1);
- if (res < 0)
- return res;
- p = strrchr(absolute_path, '/');
- p++;
- }
- /* Copy to filename buffer */
- while(filename[i] != NULL) {
- *p = filename[i];
- i++;
- p++;
- }
+ /* We have a relative pathname, compose the absolute pathname */
+ snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid());
+ rc = readlink(cwd, readlink_cwd, sizeof(readlink_cwd) - 1);
+ if (rc < 0)
+ return rc;
+ /* readlink does not null terminate our string */
+ readlink_cwd[rc] = '\0';
+
+ if (filename[0] == '.' && filename[1] == '/')
+ str_offset = 2;
+
+ snprintf(absolute_path, sizeof(absolute_path), "%s%s", readlink_cwd,
+ filename + str_offset);
}
if (uv__is_ahafs_mounted() < 0) /* /aha checks failed */
@@ -845,7 +837,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
handle->path = uv__strdup(filename);
handle->cb = cb;
- uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN);
+ uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
return 0;
#else
@@ -1036,14 +1028,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
}
if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
- SAVE_ERRNO(uv__close(sockfd));
+ uv__close(sockfd);
return -errno;
}
ifc.ifc_req = (struct ifreq*)uv__malloc(size);
ifc.ifc_len = size;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
- SAVE_ERRNO(uv__close(sockfd));
+ uv__close(sockfd);
return -errno;
}
@@ -1062,7 +1054,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
- SAVE_ERRNO(uv__close(sockfd));
+ uv__close(sockfd);
return -errno;
}
diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c
index 184b598126..393cdebd4e 100644
--- a/deps/uv/src/unix/async.c
+++ b/deps/uv/src/unix/async.c
@@ -223,7 +223,7 @@ int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) {
return err;
uv__io_init(&wa->io_watcher, uv__async_io, pipefd[0]);
- uv__io_start(loop, &wa->io_watcher, UV__POLLIN);
+ uv__io_start(loop, &wa->io_watcher, POLLIN);
wa->wfd = pipefd[1];
wa->cb = cb;
@@ -241,7 +241,7 @@ void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) {
wa->wfd = -1;
}
- uv__io_stop(loop, &wa->io_watcher, UV__POLLIN);
+ uv__io_stop(loop, &wa->io_watcher, POLLIN);
uv__close(wa->io_watcher.fd);
wa->io_watcher.fd = -1;
}
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 9aaca84187..cdcd0b504f 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -762,7 +762,7 @@ static int uv__run_pending(uv_loop_t* loop) {
QUEUE_REMOVE(q);
QUEUE_INIT(q);
w = QUEUE_DATA(q, uv__io_t, pending_queue);
- w->cb(loop, w, UV__POLLOUT);
+ w->cb(loop, w, POLLOUT);
}
return 1;
@@ -833,7 +833,7 @@ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
+ assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
assert(w->fd >= 0);
assert(w->fd < INT_MAX);
@@ -866,7 +866,7 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
+ assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
if (w->fd == -1)
@@ -898,7 +898,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
- uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
+ uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP);
QUEUE_REMOVE(&w->pending_queue);
/* Remove stale events for this file descriptor */
@@ -913,7 +913,7 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
int uv__io_active(const uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
+ assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
return 0 != (w->pevents & events);
}
diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c
index b747abdf5b..adc95235ce 100644
--- a/deps/uv/src/unix/freebsd.c
+++ b/deps/uv/src/unix/freebsd.c
@@ -292,7 +292,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(cpuspeed);
if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) {
- SAVE_ERRNO(uv__free(*cpu_infos));
+ uv__free(*cpu_infos);
return -errno;
}
@@ -301,7 +301,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*/
size = sizeof(maxcpus);
if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) {
- SAVE_ERRNO(uv__free(*cpu_infos));
+ uv__free(*cpu_infos);
return -errno;
}
@@ -314,8 +314,8 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) {
- SAVE_ERRNO(uv__free(cp_times));
- SAVE_ERRNO(uv__free(*cpu_infos));
+ uv__free(cp_times);
+ uv__free(*cpu_infos);
return -errno;
}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 8936ad9d83..085970a06d 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -33,6 +33,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h> /* PATH_MAX */
#include <sys/types.h>
#include <sys/socket.h>
@@ -205,6 +206,13 @@ skip:
# else
return futimes(req->file, tv);
# endif
+#elif defined(_AIX71)
+ struct timespec ts[2];
+ ts[0].tv_sec = req->atime;
+ ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000;
+ ts[1].tv_sec = req->mtime;
+ ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000;
+ return futimens(req->file, ts);
#else
errno = ENOSYS;
return -1;
@@ -362,9 +370,10 @@ out:
if (dents != NULL) {
int i;
+ /* Memory was allocated using the system allocator, so use free() here. */
for (i = 0; i < n; i++)
- uv__free(dents[i]);
- uv__free(dents);
+ free(dents[i]);
+ free(dents);
}
errno = saved_errno;
@@ -383,7 +392,7 @@ static ssize_t uv__fs_pathmax_size(const char* path) {
#if defined(PATH_MAX)
return PATH_MAX;
#else
- return 4096;
+#error "PATH_MAX undefined in the current platform"
#endif
}
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 938e76f1d1..670b14bc2a 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -44,15 +44,25 @@
#endif /* __sun */
#if defined(_AIX)
-#define reqevents events
-#define rtnevents revents
-#include <sys/poll.h>
+# define reqevents events
+# define rtnevents revents
+# include <sys/poll.h>
+#else
+# include <poll.h>
#endif /* _AIX */
#if defined(__APPLE__) && !TARGET_OS_IPHONE
# include <CoreServices/CoreServices.h>
#endif
+#if defined(__ANDROID__)
+int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
+# ifdef pthread_sigmask
+# undef pthread_sigmask
+# endif
+# define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset)
+#endif
+
#define ACCESS_ONCE(type, var) \
(*(volatile type*) &(var))
@@ -89,43 +99,11 @@
# define UV_UNUSED(declaration) declaration
#endif
-#if defined(__linux__)
-# define UV__POLLIN UV__EPOLLIN
-# define UV__POLLOUT UV__EPOLLOUT
-# define UV__POLLERR UV__EPOLLERR
-# define UV__POLLHUP UV__EPOLLHUP
-# define UV__POLLRDHUP UV__EPOLLRDHUP
-#endif
-
-#if defined(__sun) || defined(_AIX)
-# define UV__POLLIN POLLIN
-# define UV__POLLOUT POLLOUT
-# define UV__POLLERR POLLERR
-# define UV__POLLHUP POLLHUP
-#endif
-
-#ifndef UV__POLLIN
-# define UV__POLLIN 1
-#endif
-
-#ifndef UV__POLLOUT
-# define UV__POLLOUT 2
-#endif
-
-#ifndef UV__POLLERR
-# define UV__POLLERR 4
-#endif
-
-#ifndef UV__POLLHUP
-# define UV__POLLHUP 8
-#endif
-
-#ifndef UV__POLLRDHUP
-# ifdef POLLRDHUP
-# define UV__POLLRDHUP POLLRDHUP
-# else
-# define UV__POLLRDHUP 0x200
-# endif
+/* Leans on the fact that, on Linux, POLLRDHUP == EPOLLRDHUP. */
+#ifdef POLLRDHUP
+# define UV__POLLRDHUP POLLRDHUP
+#else
+# define UV__POLLRDHUP 0x2000
#endif
#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index 400b4a4b7c..fffd4626f1 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -78,6 +78,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
sigset_t set;
uint64_t base;
uint64_t diff;
+ int have_signals;
int filter;
int fflags;
int count;
@@ -103,7 +104,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
assert(w->fd >= 0);
assert(w->fd < (int) loop->nwatchers);
- if ((w->events & UV__POLLIN) == 0 && (w->pevents & UV__POLLIN) != 0) {
+ if ((w->events & POLLIN) == 0 && (w->pevents & POLLIN) != 0) {
filter = EVFILT_READ;
fflags = 0;
op = EV_ADD;
@@ -124,7 +125,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
}
- if ((w->events & UV__POLLOUT) == 0 && (w->pevents & UV__POLLOUT) != 0) {
+ if ((w->events & POLLOUT) == 0 && (w->pevents & POLLOUT) != 0) {
EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (++nevents == ARRAY_SIZE(events)) {
@@ -192,6 +193,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
goto update_timeout;
}
+ have_signals = 0;
nevents = 0;
assert(loop->watchers != NULL);
@@ -219,8 +221,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
if (ev->filter == EVFILT_VNODE) {
- assert(w->events == UV__POLLIN);
- assert(w->pevents == UV__POLLIN);
+ assert(w->events == POLLIN);
+ assert(w->pevents == POLLIN);
w->cb(loop, w, ev->fflags); /* XXX always uv__fs_event() */
nevents++;
continue;
@@ -229,8 +231,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
revents = 0;
if (ev->filter == EVFILT_READ) {
- if (w->pevents & UV__POLLIN) {
- revents |= UV__POLLIN;
+ if (w->pevents & POLLIN) {
+ revents |= POLLIN;
w->rcount = ev->data;
} else {
/* TODO batch up */
@@ -243,8 +245,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
if (ev->filter == EVFILT_WRITE) {
- if (w->pevents & UV__POLLOUT) {
- revents |= UV__POLLOUT;
+ if (w->pevents & POLLOUT) {
+ revents |= POLLOUT;
w->wcount = ev->data;
} else {
/* TODO batch up */
@@ -257,7 +259,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
if (ev->flags & EV_ERROR)
- revents |= UV__POLLERR;
+ revents |= POLLERR;
if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP))
revents |= UV__POLLRDHUP;
@@ -265,12 +267,26 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (revents == 0)
continue;
- w->cb(loop, w, revents);
+ /* Run signal watchers last. This also affects child process watchers
+ * because those are implemented in terms of signal watchers.
+ */
+ if (w == &loop->signal_io_watcher)
+ have_signals = 1;
+ else
+ w->cb(loop, w, revents);
+
nevents++;
}
+
+ if (have_signals != 0)
+ loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
+
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;
+ if (have_signals != 0)
+ return; /* Event loop should cycle now so don't poll again. */
+
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
/* Poll for more events but don't block this time. */
@@ -409,7 +425,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
fallback:
#endif /* defined(__APPLE__) */
- uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN);
+ uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
return 0;
}
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index fb8ac3f237..b48a111170 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -18,6 +18,11 @@
* IN THE SOFTWARE.
*/
+/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their
+ * EPOLL* counterparts. We use the POLL* variants in this file because that
+ * is what libuv uses elsewhere and it avoids a dependency on <sys/epoll.h>.
+ */
+
#include "uv.h"
#include "internal.h"
@@ -69,7 +74,9 @@
#endif
static int read_models(unsigned int numcpus, uv_cpu_info_t* ci);
-static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci);
+static int read_times(FILE* statfile_fp,
+ unsigned int numcpus,
+ uv_cpu_info_t* ci);
static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
static unsigned long read_cpufreq(unsigned int cpunum);
@@ -102,7 +109,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
void uv__platform_loop_delete(uv_loop_t* loop) {
if (loop->inotify_fd == -1) return;
- uv__io_stop(loop, &loop->inotify_read_watcher, UV__POLLIN);
+ uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN);
uv__close(loop->inotify_fd);
loop->inotify_fd = -1;
}
@@ -144,7 +151,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
struct uv__epoll_event e;
int rc;
- e.events = UV__EPOLLIN;
+ e.events = POLLIN;
e.data = -1;
rc = 0;
@@ -181,6 +188,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
sigset_t sigset;
uint64_t sigmask;
uint64_t base;
+ int have_signals;
int nevents;
int count;
int nfds;
@@ -308,6 +316,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
goto update_timeout;
}
+ have_signals = 0;
nevents = 0;
assert(loop->watchers != NULL);
@@ -341,7 +350,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* the current watcher. Also, filters out events that users has not
* requested us to watch.
*/
- pe->events &= w->pevents | UV__POLLERR | UV__POLLHUP;
+ pe->events &= w->pevents | POLLERR | POLLHUP;
/* Work around an epoll quirk where it sometimes reports just the
* EPOLLERR or EPOLLHUP event. In order to force the event loop to
@@ -358,17 +367,31 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* needs to remember the error/hangup event. We should get that for
* free when we switch over to edge-triggered I/O.
*/
- if (pe->events == UV__EPOLLERR || pe->events == UV__EPOLLHUP)
- pe->events |= w->pevents & (UV__EPOLLIN | UV__EPOLLOUT);
+ if (pe->events == POLLERR || pe->events == POLLHUP)
+ pe->events |= w->pevents & (POLLIN | POLLOUT);
if (pe->events != 0) {
- w->cb(loop, w, pe->events);
+ /* Run signal watchers last. This also affects child process watchers
+ * because those are implemented in terms of signal watchers.
+ */
+ if (w == &loop->signal_io_watcher)
+ have_signals = 1;
+ else
+ w->cb(loop, w, pe->events);
+
nevents++;
}
}
+
+ if (have_signals != 0)
+ loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
+
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;
+ if (have_signals != 0)
+ return; /* Event loop should cycle now so don't poll again. */
+
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
/* Poll for more events but don't block this time. */
@@ -557,7 +580,7 @@ static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
char buf[1024];
if (!fgets(buf, sizeof(buf), statfile_fp))
- abort();
+ return -EIO;
num = 0;
while (fgets(buf, sizeof(buf), statfile_fp)) {
@@ -566,6 +589,9 @@ static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
num++;
}
+ if (num == 0)
+ return -EIO;
+
*numcpus = num;
return 0;
}
@@ -586,26 +612,20 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
err = uv__cpu_num(statfile_fp, &numcpus);
if (err < 0)
- return err;
-
- assert(numcpus != (unsigned int) -1);
- assert(numcpus != 0);
+ goto out;
+ err = -ENOMEM;
ci = uv__calloc(numcpus, sizeof(*ci));
if (ci == NULL)
- return -ENOMEM;
+ goto out;
err = read_models(numcpus, ci);
if (err == 0)
err = read_times(statfile_fp, numcpus, ci);
- if (fclose(statfile_fp))
- if (errno != EINTR && errno != EINPROGRESS)
- abort();
-
if (err) {
uv_free_cpu_info(ci, numcpus);
- return err;
+ goto out;
}
/* read_models() on x86 also reads the CPU speed from /proc/cpuinfo.
@@ -616,8 +636,15 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*cpu_infos = ci;
*count = numcpus;
+ err = 0;
- return 0;
+out:
+
+ if (fclose(statfile_fp))
+ if (errno != EINTR && errno != EINPROGRESS)
+ abort();
+
+ return err;
}
@@ -727,7 +754,9 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
}
-static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci) {
+static int read_times(FILE* statfile_fp,
+ unsigned int numcpus,
+ uv_cpu_info_t* ci) {
unsigned long clock_ticks;
struct uv_cpu_times_s ts;
unsigned long user;
diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c
index 282912115d..4708c051d3 100644
--- a/deps/uv/src/unix/linux-inotify.c
+++ b/deps/uv/src/unix/linux-inotify.c
@@ -102,7 +102,7 @@ static int init_inotify(uv_loop_t* loop) {
loop->inotify_fd = err;
uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd);
- uv__io_start(loop, &loop->inotify_read_watcher, UV__POLLIN);
+ uv__io_start(loop, &loop->inotify_read_watcher, POLLIN);
return 0;
}
diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h
index 4260df111f..4c095e9b53 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -72,14 +72,6 @@
#define UV__EPOLL_CTL_DEL 2
#define UV__EPOLL_CTL_MOD 3
-#define UV__EPOLLIN 1
-#define UV__EPOLLOUT 4
-#define UV__EPOLLERR 8
-#define UV__EPOLLHUP 16
-#define UV__EPOLLRDHUP 0x2000
-#define UV__EPOLLONESHOT 0x40000000
-#define UV__EPOLLET 0x80000000
-
/* inotify flags */
#define UV__IN_ACCESS 0x001
#define UV__IN_MODIFY 0x002
diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c
index 6a3909a666..8c40bde40f 100644
--- a/deps/uv/src/unix/openbsd.c
+++ b/deps/uv/src/unix/openbsd.c
@@ -247,7 +247,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
which[1] = HW_CPUSPEED;
size = sizeof(cpuspeed);
if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
- SAVE_ERRNO(uv__free(*cpu_infos));
+ uv__free(*cpu_infos);
return -errno;
}
@@ -258,7 +258,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
which[2] = i;
size = sizeof(info);
if (sysctl(which, 3, &info, &size, NULL, 0)) {
- SAVE_ERRNO(uv__free(*cpu_infos));
+ uv__free(*cpu_infos);
return -errno;
}
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index d4fdfa9d5a..c8d163dcc7 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -102,7 +102,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
handle->connection_cb = cb;
handle->io_watcher.cb = uv__server_io;
- uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN);
+ uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
return 0;
}
@@ -185,7 +185,7 @@ void uv_pipe_connect(uv_connect_t* req,
}
if (err == 0)
- uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN | UV__POLLOUT);
+ uv__io_start(handle->loop, &handle->io_watcher, POLLIN | POLLOUT);
out:
handle->delayed_error = err;
diff --git a/deps/uv/src/unix/poll.c b/deps/uv/src/unix/poll.c
index e5efb17160..0d5944b0af 100644
--- a/deps/uv/src/unix/poll.c
+++ b/deps/uv/src/unix/poll.c
@@ -33,17 +33,17 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
handle = container_of(w, uv_poll_t, io_watcher);
- if (events & UV__POLLERR) {
- uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
+ if (events & POLLERR) {
+ uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP);
uv__handle_stop(handle);
handle->poll_cb(handle, -EBADF, 0);
return;
}
pevents = 0;
- if (events & UV__POLLIN)
+ if (events & POLLIN)
pevents |= UV_READABLE;
- if (events & UV__POLLOUT)
+ if (events & POLLOUT)
pevents |= UV_WRITABLE;
if (events & UV__POLLRDHUP)
pevents |= UV_DISCONNECT;
@@ -79,7 +79,7 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
static void uv__poll_stop(uv_poll_t* handle) {
uv__io_stop(handle->loop,
&handle->io_watcher,
- UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
+ POLLIN | POLLOUT | UV__POLLRDHUP);
uv__handle_stop(handle);
}
@@ -104,9 +104,9 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
events = 0;
if (pevents & UV_READABLE)
- events |= UV__POLLIN;
+ events |= POLLIN;
if (pevents & UV_WRITABLE)
- events |= UV__POLLOUT;
+ events |= POLLOUT;
if (pevents & UV_DISCONNECT)
events |= UV__POLLRDHUP;
diff --git a/deps/uv/src/unix/pthread-barrier.c b/deps/uv/src/unix/pthread-barrier.c
new file mode 100644
index 0000000000..f57bf25080
--- /dev/null
+++ b/deps/uv/src/unix/pthread-barrier.c
@@ -0,0 +1,120 @@
+/*
+Copyright (c) 2016, Kari Tristan Helgason <kthelgason@gmail.com>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+#include "uv-common.h"
+#include "pthread-barrier.h"
+
+#include <stdlib.h>
+#include <assert.h>
+
+/* TODO: support barrier_attr */
+int pthread_barrier_init(pthread_barrier_t* barrier,
+ const void* barrier_attr,
+ unsigned count) {
+ int rc;
+ _uv_barrier* b;
+
+ if (barrier == NULL || count == 0)
+ return EINVAL;
+
+ if (barrier_attr != NULL)
+ return ENOTSUP;
+
+ b = uv__malloc(sizeof(*b));
+ if (b == NULL)
+ return ENOMEM;
+
+ b->in = 0;
+ b->out = 0;
+ b->threshold = count;
+
+ if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0)
+ goto error2;
+ if ((rc = pthread_cond_init(&b->cond, NULL)) != 0)
+ goto error;
+
+ barrier->b = b;
+ return 0;
+
+error:
+ pthread_mutex_destroy(&b->mutex);
+error2:
+ uv__free(b);
+ return rc;
+}
+
+int pthread_barrier_wait(pthread_barrier_t* barrier) {
+ int rc;
+ _uv_barrier* b;
+
+ if (barrier == NULL || barrier->b == NULL)
+ return EINVAL;
+
+ b = barrier->b;
+ /* Lock the mutex*/
+ if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
+ return rc;
+
+ /* Increment the count. If this is the first thread to reach the threshold,
+ wake up waiters, unlock the mutex, then return
+ PTHREAD_BARRIER_SERIAL_THREAD. */
+ if (++b->in == b->threshold) {
+ b->in = 0;
+ b->out = b->threshold - 1;
+ assert(pthread_cond_signal(&b->cond) == 0);
+
+ pthread_mutex_unlock(&b->mutex);
+ return PTHREAD_BARRIER_SERIAL_THREAD;
+ }
+ /* Otherwise, wait for other threads until in is set to 0,
+ then return 0 to indicate this is not the first thread. */
+ do {
+ if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0)
+ break;
+ } while (b->in != 0);
+
+ /* mark thread exit */
+ b->out--;
+ pthread_cond_signal(&b->cond);
+ pthread_mutex_unlock(&b->mutex);
+ return rc;
+}
+
+int pthread_barrier_destroy(pthread_barrier_t* barrier) {
+ int rc;
+ _uv_barrier* b;
+
+ if (barrier == NULL || barrier->b == NULL)
+ return EINVAL;
+
+ b = barrier->b;
+
+ if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
+ return rc;
+
+ if (b->in > 0 || b->out > 0)
+ rc = EBUSY;
+
+ pthread_mutex_unlock(&b->mutex);
+
+ if (rc)
+ return rc;
+
+ pthread_cond_destroy(&b->cond);
+ pthread_mutex_destroy(&b->mutex);
+ uv__free(barrier->b);
+ barrier->b = NULL;
+ return 0;
+}
diff --git a/deps/uv/src/unix/pthread-fixes.c b/deps/uv/src/unix/pthread-fixes.c
index 3a71eb5aae..fb17995846 100644
--- a/deps/uv/src/unix/pthread-fixes.c
+++ b/deps/uv/src/unix/pthread-fixes.c
@@ -29,76 +29,28 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* Android versions < 4.1 have a broken pthread_sigmask.
- * Note that this block of code must come before any inclusion of
- * pthread-fixes.h so that the real pthread_sigmask can be referenced.
- * */
+/* Android versions < 4.1 have a broken pthread_sigmask. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) {
static int workaround;
+ int err;
if (workaround) {
return sigprocmask(how, set, oset);
- } else if (pthread_sigmask(how, set, oset)) {
- if (errno == EINVAL && sigprocmask(how, set, oset) == 0) {
- workaround = 1;
- return 0;
- } else {
- return -1;
- }
} else {
- return 0;
- }
-}
-
-/*Android doesn't provide pthread_barrier_t for now.*/
-#ifndef PTHREAD_BARRIER_SERIAL_THREAD
-
-#include "pthread-fixes.h"
-
-int pthread_barrier_init(pthread_barrier_t* barrier,
- const void* barrier_attr,
- unsigned count) {
- barrier->count = count;
- pthread_mutex_init(&barrier->mutex, NULL);
- pthread_cond_init(&barrier->cond, NULL);
- return 0;
-}
-
-int pthread_barrier_wait(pthread_barrier_t* barrier) {
- /* Lock the mutex*/
- pthread_mutex_lock(&barrier->mutex);
- /* Decrement the count. If this is the first thread to reach 0, wake up
- waiters, unlock the mutex, then return PTHREAD_BARRIER_SERIAL_THREAD.*/
- if (--barrier->count == 0) {
- /* First thread to reach the barrier */
- pthread_cond_broadcast(&barrier->cond);
- pthread_mutex_unlock(&barrier->mutex);
- return PTHREAD_BARRIER_SERIAL_THREAD;
+ err = pthread_sigmask(how, set, oset);
+ if (err) {
+ if (err == EINVAL && sigprocmask(how, set, oset) == 0) {
+ workaround = 1;
+ return 0;
+ } else {
+ return -1;
+ }
+ }
}
- /* Otherwise, wait for other threads until the count reaches 0, then
- return 0 to indicate this is not the first thread.*/
- do {
- pthread_cond_wait(&barrier->cond, &barrier->mutex);
- } while (barrier->count > 0);
-
- pthread_mutex_unlock(&barrier->mutex);
- return 0;
-}
-
-int pthread_barrier_destroy(pthread_barrier_t *barrier) {
- barrier->count = 0;
- pthread_cond_destroy(&barrier->cond);
- pthread_mutex_destroy(&barrier->mutex);
- return 0;
-}
-
-#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */
-int pthread_yield(void) {
- sched_yield();
return 0;
}
diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c
index edd9085d3f..d82b9b7cf8 100644
--- a/deps/uv/src/unix/signal.c
+++ b/deps/uv/src/unix/signal.c
@@ -222,7 +222,7 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) {
uv__io_init(&loop->signal_io_watcher,
uv__signal_event,
loop->signal_pipefd[0]);
- uv__io_start(loop, &loop->signal_io_watcher, UV__POLLIN);
+ uv__io_start(loop, &loop->signal_io_watcher, POLLIN);
return 0;
}
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 9043664dfc..7dbc556f74 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -159,9 +159,9 @@ static void uv__stream_osx_select(void* arg) {
memset(s->sread, 0, s->sread_sz);
memset(s->swrite, 0, s->swrite_sz);
- if (uv__io_active(&stream->io_watcher, UV__POLLIN))
+ if (uv__io_active(&stream->io_watcher, POLLIN))
FD_SET(fd, s->sread);
- if (uv__io_active(&stream->io_watcher, UV__POLLOUT))
+ if (uv__io_active(&stream->io_watcher, POLLOUT))
FD_SET(fd, s->swrite);
FD_SET(s->int_fd, s->sread);
@@ -202,9 +202,9 @@ static void uv__stream_osx_select(void* arg) {
/* Handle events */
events = 0;
if (FD_ISSET(fd, s->sread))
- events |= UV__POLLIN;
+ events |= POLLIN;
if (FD_ISSET(fd, s->swrite))
- events |= UV__POLLOUT;
+ events |= POLLOUT;
assert(events != 0 || FD_ISSET(s->int_fd, s->sread));
if (events != 0) {
@@ -233,14 +233,14 @@ static void uv__stream_osx_select_cb(uv_async_t* handle) {
ACCESS_ONCE(int, s->events) = 0;
assert(events != 0);
- assert(events == (events & (UV__POLLIN | UV__POLLOUT)));
+ assert(events == (events & (POLLIN | POLLOUT)));
/* Invoke callback on event-loop */
- if ((events & UV__POLLIN) && uv__io_active(&stream->io_watcher, UV__POLLIN))
- uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLIN);
+ if ((events & POLLIN) && uv__io_active(&stream->io_watcher, POLLIN))
+ uv__stream_io(stream->loop, &stream->io_watcher, POLLIN);
- if ((events & UV__POLLOUT) && uv__io_active(&stream->io_watcher, UV__POLLOUT))
- uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLOUT);
+ if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT))
+ uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT);
if (stream->flags & UV_CLOSING)
return;
@@ -437,7 +437,7 @@ void uv__stream_flush_write_queue(uv_stream_t* stream, int error) {
void uv__stream_destroy(uv_stream_t* stream) {
- assert(!uv__io_active(&stream->io_watcher, UV__POLLIN | UV__POLLOUT));
+ assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT));
assert(stream->flags & UV_CLOSED);
if (stream->connect_req) {
@@ -511,11 +511,11 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
int err;
stream = container_of(w, uv_stream_t, io_watcher);
- assert(events == UV__POLLIN);
+ assert(events == POLLIN);
assert(stream->accepted_fd == -1);
assert(!(stream->flags & UV_CLOSING));
- uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
+ uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
/* connection_cb can close the server socket while we're
* in the loop so check it on each iteration.
@@ -552,7 +552,7 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
if (stream->accepted_fd != -1) {
/* The user hasn't yet accepted called uv_accept() */
- uv__io_stop(loop, &stream->io_watcher, UV__POLLIN);
+ uv__io_stop(loop, &stream->io_watcher, POLLIN);
return;
}
@@ -626,7 +626,7 @@ done:
} else {
server->accepted_fd = -1;
if (err == 0)
- uv__io_start(server->loop, &server->io_watcher, UV__POLLIN);
+ uv__io_start(server->loop, &server->io_watcher, POLLIN);
}
return err;
}
@@ -660,7 +660,7 @@ static void uv__drain(uv_stream_t* stream) {
int err;
assert(QUEUE_EMPTY(&stream->write_queue));
- uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
uv__stream_osx_interrupt_select(stream);
/* Shutdown? */
@@ -846,8 +846,8 @@ start:
/* Error */
req->error = -errno;
uv__write_req_finish(req);
- uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
- if (!uv__io_active(&stream->io_watcher, UV__POLLIN))
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
+ if (!uv__io_active(&stream->io_watcher, POLLIN))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
return;
@@ -910,7 +910,7 @@ start:
assert(!(stream->flags & UV_STREAM_BLOCKING));
/* We're not done. */
- uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT);
+ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
/* Notify select() thread about state change */
uv__stream_osx_interrupt_select(stream);
@@ -989,8 +989,8 @@ uv_handle_type uv__handle_type(int fd) {
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_STREAM_READ_EOF;
- uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
- if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
+ if (!uv__io_active(&stream->io_watcher, POLLOUT))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
stream->read_cb(stream, UV_EOF, buf);
@@ -1159,7 +1159,7 @@ static void uv__read(uv_stream_t* stream) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
/* Wait for the next one. */
if (stream->flags & UV_STREAM_READING) {
- uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
+ uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
uv__stream_osx_interrupt_select(stream);
}
stream->read_cb(stream, 0, &buf);
@@ -1168,8 +1168,8 @@ static void uv__read(uv_stream_t* stream) {
stream->read_cb(stream, -errno, &buf);
if (stream->flags & UV_STREAM_READING) {
stream->flags &= ~UV_STREAM_READING;
- uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
- if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
+ if (!uv__io_active(&stream->io_watcher, POLLOUT))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
}
@@ -1230,7 +1230,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
stream->shutdown_req = req;
stream->flags |= UV_STREAM_SHUTTING;
- uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT);
+ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
uv__stream_osx_interrupt_select(stream);
return 0;
@@ -1255,7 +1255,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
assert(uv__stream_fd(stream) >= 0);
/* Ignore POLLHUP here. Even it it's set, there may still be data to read. */
- if (events & (UV__POLLIN | UV__POLLERR | UV__POLLHUP))
+ if (events & (POLLIN | POLLERR | POLLHUP))
uv__read(stream);
if (uv__stream_fd(stream) == -1)
@@ -1267,7 +1267,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
* have to do anything. If the partial read flag is not set, we can't
* report the EOF yet because there is still data to read.
*/
- if ((events & UV__POLLHUP) &&
+ if ((events & POLLHUP) &&
(stream->flags & UV_STREAM_READING) &&
(stream->flags & UV_STREAM_READ_PARTIAL) &&
!(stream->flags & UV_STREAM_READ_EOF)) {
@@ -1278,7 +1278,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
if (uv__stream_fd(stream) == -1)
return; /* read_cb closed stream. */
- if (events & (UV__POLLOUT | UV__POLLERR | UV__POLLHUP)) {
+ if (events & (POLLOUT | POLLERR | POLLHUP)) {
uv__write(stream);
uv__write_callbacks(stream);
@@ -1327,7 +1327,7 @@ static void uv__stream_connect(uv_stream_t* stream) {
uv__req_unregister(stream->loop, req);
if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) {
- uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
}
if (req->cb)
@@ -1422,7 +1422,7 @@ int uv_write2(uv_write_t* req,
* sufficiently flushed in uv__write.
*/
assert(!(stream->flags & UV_STREAM_BLOCKING));
- uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT);
+ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
uv__stream_osx_interrupt_select(stream);
}
@@ -1461,7 +1461,7 @@ int uv_try_write(uv_stream_t* stream,
if (stream->connect_req != NULL || stream->write_queue_size != 0)
return -EAGAIN;
- has_pollout = uv__io_active(&stream->io_watcher, UV__POLLOUT);
+ has_pollout = uv__io_active(&stream->io_watcher, POLLOUT);
r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb);
if (r != 0)
@@ -1485,7 +1485,7 @@ int uv_try_write(uv_stream_t* stream,
/* Do not poll for writable, if we wasn't before calling this */
if (!has_pollout) {
- uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
uv__stream_osx_interrupt_select(stream);
}
@@ -1520,7 +1520,7 @@ int uv_read_start(uv_stream_t* stream,
stream->read_cb = read_cb;
stream->alloc_cb = alloc_cb;
- uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
+ uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
uv__handle_start(stream);
uv__stream_osx_interrupt_select(stream);
@@ -1533,8 +1533,8 @@ int uv_read_stop(uv_stream_t* stream) {
return 0;
stream->flags &= ~UV_STREAM_READING;
- uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
- if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
+ if (!uv__io_active(&stream->io_watcher, POLLOUT))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
@@ -1621,7 +1621,7 @@ void uv__stream_close(uv_stream_t* handle) {
handle->queued_fds = NULL;
}
- assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT));
+ assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT));
}
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index 9a6cc42b5b..e67be8fcf8 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -140,6 +140,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
unsigned int nfds;
unsigned int i;
int saved_errno;
+ int have_signals;
int nevents;
int count;
int err;
@@ -230,6 +231,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
return;
}
+ have_signals = 0;
nevents = 0;
assert(loop->watchers != NULL);
@@ -252,7 +254,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (w == NULL)
continue;
- w->cb(loop, w, pe->portev_events);
+ /* Run signal watchers last. This also affects child process watchers
+ * because those are implemented in terms of signal watchers.
+ */
+ if (w == &loop->signal_io_watcher)
+ have_signals = 1;
+ else
+ w->cb(loop, w, pe->portev_events);
+
nevents++;
if (w != loop->watchers[fd])
@@ -262,9 +271,16 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue))
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
}
+
+ if (have_signals != 0)
+ loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
+
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;
+ if (have_signals != 0)
+ return; /* Event loop should cycle now so don't poll again. */
+
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
/* Poll for more events but don't block this time. */
@@ -456,7 +472,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
if (first_run) {
uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd);
- uv__io_start(handle->loop, &handle->loop->fs_event_watcher, UV__POLLIN);
+ uv__io_start(handle->loop, &handle->loop->fs_event_watcher, POLLIN);
}
return 0;
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index 6d213a4977..793e4c7d60 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -181,7 +181,7 @@ int uv__tcp_connect(uv_connect_t* req,
QUEUE_INIT(&req->queue);
handle->connect_req = req;
- uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT);
+ uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
if (handle->delayed_error)
uv__io_feed(handle->loop, &handle->io_watcher);
@@ -273,7 +273,7 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
/* Start listening for connections. */
tcp->io_watcher.cb = uv__server_io;
- uv__io_start(tcp->loop, &tcp->io_watcher, UV__POLLIN);
+ uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
return 0;
}
diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c
index c35bc926bf..236f591393 100644
--- a/deps/uv/src/unix/thread.c
+++ b/deps/uv/src/unix/thread.c
@@ -28,13 +28,13 @@
#include <sys/time.h>
#include <sys/resource.h> /* getrlimit() */
+#include <unistd.h> /* getpagesize() */
#include <limits.h>
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
-
struct thread_ctx {
void (*entry)(void* arg);
void* arg;
@@ -82,10 +82,13 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
if (pthread_attr_init(attr))
abort();
- if (lim.rlim_cur != RLIM_INFINITY &&
- lim.rlim_cur >= PTHREAD_STACK_MIN) {
- if (pthread_attr_setstacksize(attr, lim.rlim_cur))
- abort();
+ if (lim.rlim_cur != RLIM_INFINITY) {
+ /* pthread_attr_setstacksize() expects page-aligned values. */
+ lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
+
+ if (lim.rlim_cur >= PTHREAD_STACK_MIN)
+ if (pthread_attr_setstacksize(attr, lim.rlim_cur))
+ abort();
}
#else
attr = NULL;
@@ -393,6 +396,35 @@ error2:
#endif /* defined(__APPLE__) && defined(__MACH__) */
void uv_cond_destroy(uv_cond_t* cond) {
+#if defined(__APPLE__) && defined(__MACH__)
+ /* It has been reported that destroying condition variables that have been
+ * signalled but not waited on can sometimes result in application crashes.
+ * See https://codereview.chromium.org/1323293005.
+ */
+ pthread_mutex_t mutex;
+ struct timespec ts;
+ int err;
+
+ if (pthread_mutex_init(&mutex, NULL))
+ abort();
+
+ if (pthread_mutex_lock(&mutex))
+ abort();
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
+
+ err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
+ if (err != 0 && err != ETIMEDOUT)
+ abort();
+
+ if (pthread_mutex_unlock(&mutex))
+ abort();
+
+ if (pthread_mutex_destroy(&mutex))
+ abort();
+#endif /* defined(__APPLE__) && defined(__MACH__) */
+
if (pthread_cond_destroy(cond))
abort();
}
@@ -448,72 +480,6 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
}
-#if defined(__APPLE__) && defined(__MACH__)
-
-int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
- int err;
-
- barrier->n = count;
- barrier->count = 0;
-
- err = uv_mutex_init(&barrier->mutex);
- if (err)
- return -err;
-
- err = uv_sem_init(&barrier->turnstile1, 0);
- if (err)
- goto error2;
-
- err = uv_sem_init(&barrier->turnstile2, 1);
- if (err)
- goto error;
-
- return 0;
-
-error:
- uv_sem_destroy(&barrier->turnstile1);
-error2:
- uv_mutex_destroy(&barrier->mutex);
- return -err;
-
-}
-
-
-void uv_barrier_destroy(uv_barrier_t* barrier) {
- uv_sem_destroy(&barrier->turnstile2);
- uv_sem_destroy(&barrier->turnstile1);
- uv_mutex_destroy(&barrier->mutex);
-}
-
-
-int uv_barrier_wait(uv_barrier_t* barrier) {
- int serial_thread;
-
- uv_mutex_lock(&barrier->mutex);
- if (++barrier->count == barrier->n) {
- uv_sem_wait(&barrier->turnstile2);
- uv_sem_post(&barrier->turnstile1);
- }
- uv_mutex_unlock(&barrier->mutex);
-
- uv_sem_wait(&barrier->turnstile1);
- uv_sem_post(&barrier->turnstile1);
-
- uv_mutex_lock(&barrier->mutex);
- serial_thread = (--barrier->count == 0);
- if (serial_thread) {
- uv_sem_wait(&barrier->turnstile1);
- uv_sem_post(&barrier->turnstile2);
- }
- uv_mutex_unlock(&barrier->mutex);
-
- uv_sem_wait(&barrier->turnstile2);
- uv_sem_post(&barrier->turnstile2);
- return serial_thread;
-}
-
-#else /* !(defined(__APPLE__) && defined(__MACH__)) */
-
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
return -pthread_barrier_init(barrier, NULL, count);
}
@@ -532,7 +498,6 @@ int uv_barrier_wait(uv_barrier_t* barrier) {
return r == PTHREAD_BARRIER_SERIAL_THREAD;
}
-#endif /* defined(__APPLE__) && defined(__MACH__) */
int uv_key_create(uv_key_t* key) {
return -pthread_key_create(key, NULL);
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index 39ade8de33..4527bba1f1 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -61,7 +61,7 @@ void uv__udp_finish_close(uv_udp_t* handle) {
uv_udp_send_t* req;
QUEUE* q;
- assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT));
+ assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT));
assert(handle->io_watcher.fd == -1);
while (!QUEUE_EMPTY(&handle->write_queue)) {
@@ -120,8 +120,8 @@ static void uv__udp_run_completed(uv_udp_t* handle) {
if (QUEUE_EMPTY(&handle->write_queue)) {
/* Pending queue and completion queue empty, stop watcher. */
- uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLOUT);
- if (!uv__io_active(&handle->io_watcher, UV__POLLIN))
+ uv__io_stop(handle->loop, &handle->io_watcher, POLLOUT);
+ if (!uv__io_active(&handle->io_watcher, POLLIN))
uv__handle_stop(handle);
}
@@ -135,10 +135,10 @@ static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) {
handle = container_of(w, uv_udp_t, io_watcher);
assert(handle->type == UV_UDP);
- if (revents & UV__POLLIN)
+ if (revents & POLLIN)
uv__udp_recvmsg(handle);
- if (revents & UV__POLLOUT) {
+ if (revents & POLLOUT) {
uv__udp_sendmsg(handle);
uv__udp_run_completed(handle);
}
@@ -424,7 +424,7 @@ int uv__udp_send(uv_udp_send_t* req,
if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) {
uv__udp_sendmsg(handle);
} else {
- uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT);
+ uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
}
return 0;
@@ -843,7 +843,7 @@ int uv__udp_recv_start(uv_udp_t* handle,
if (alloc_cb == NULL || recv_cb == NULL)
return -EINVAL;
- if (uv__io_active(&handle->io_watcher, UV__POLLIN))
+ if (uv__io_active(&handle->io_watcher, POLLIN))
return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */
err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0);
@@ -853,7 +853,7 @@ int uv__udp_recv_start(uv_udp_t* handle,
handle->alloc_cb = alloc_cb;
handle->recv_cb = recv_cb;
- uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN);
+ uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
uv__handle_start(handle);
return 0;
@@ -861,9 +861,9 @@ int uv__udp_recv_start(uv_udp_t* handle,
int uv__udp_recv_stop(uv_udp_t* handle) {
- uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLIN);
+ uv__io_stop(handle->loop, &handle->io_watcher, POLLIN);
- if (!uv__io_active(&handle->io_watcher, UV__POLLOUT))
+ if (!uv__io_active(&handle->io_watcher, POLLOUT))
uv__handle_stop(handle);
handle->alloc_cb = NULL;
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index 6b8c584fbe..ba26446915 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -22,10 +22,11 @@
#include "uv.h"
#include "uv-common.h"
-#include <stdio.h>
#include <assert.h>
+#include <errno.h>
#include <stdarg.h>
#include <stddef.h> /* NULL */
+#include <stdio.h>
#include <stdlib.h> /* malloc */
#include <string.h> /* memset */
@@ -75,7 +76,14 @@ void* uv__malloc(size_t size) {
}
void uv__free(void* ptr) {
+ int saved_errno;
+
+ /* Libuv expects that free() does not clobber errno. The system allocator
+ * honors that assumption but custom allocators may not be so careful.
+ */
+ saved_errno = errno;
uv__allocator.local_free(ptr);
+ errno = saved_errno;
}
void* uv__calloc(size_t count, size_t size) {
@@ -475,6 +483,16 @@ static unsigned int* uv__get_nbufs(uv_fs_t* req) {
#endif
}
+/* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
+ * systems. So, the memory should be released using free(). On Windows,
+ * uv__malloc() is used, so use uv__free() to free memory.
+*/
+#ifdef _WIN32
+# define uv__fs_scandir_free uv__free
+#else
+# define uv__fs_scandir_free free
+#endif
+
void uv__fs_scandir_cleanup(uv_fs_t* req) {
uv__dirent_t** dents;
@@ -484,7 +502,10 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) {
if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
(*nbufs)--;
for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
- uv__free(dents[*nbufs]);
+ uv__fs_scandir_free(dents[*nbufs]);
+
+ uv__fs_scandir_free(req->ptr);
+ req->ptr = NULL;
}
@@ -498,11 +519,11 @@ int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
/* Free previous entity */
if (*nbufs > 0)
- uv__free(dents[*nbufs - 1]);
+ uv__fs_scandir_free(dents[*nbufs - 1]);
/* End was already reached */
if (*nbufs == (unsigned int) req->result) {
- uv__free(dents);
+ uv__fs_scandir_free(dents);
req->ptr = NULL;
return UV_EOF;
}
diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c
index 77c935a2d8..e79a48d0e9 100644
--- a/deps/uv/src/win/fs-event.c
+++ b/deps/uv/src/win/fs-event.c
@@ -66,11 +66,12 @@ static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,
static void uv_relative_path(const WCHAR* filename,
const WCHAR* dir,
WCHAR** relpath) {
+ size_t relpathlen;
+ size_t filenamelen = wcslen(filename);
size_t dirlen = wcslen(dir);
if (dirlen > 0 && dir[dirlen - 1] == '\\')
dirlen--;
- size_t filenamelen = wcslen(filename);
- size_t relpathlen = filenamelen - dirlen - 1;
+ relpathlen = filenamelen - dirlen - 1;
*relpath = uv__malloc((relpathlen + 1) * sizeof(WCHAR));
if (!*relpath)
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
@@ -348,7 +349,8 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
FILE_NOTIFY_INFORMATION* file_info;
int err, sizew, size;
char* filename = NULL;
- WCHAR* filenamew, *long_filenamew = NULL;
+ WCHAR* filenamew = NULL;
+ WCHAR* long_filenamew = NULL;
DWORD offset = 0;
assert(req->type == UV_FS_EVENT_REQ);
@@ -373,6 +375,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
do {
file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset);
assert(!filename);
+ assert(!filenamew);
assert(!long_filenamew);
/*
@@ -437,14 +440,17 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
uv__free(long_filenamew);
long_filenamew = filenamew;
sizew = -1;
+ } else {
+ /* We couldn't get the long filename, use the one reported. */
+ filenamew = file_info->FileName;
+ sizew = file_info->FileNameLength / sizeof(WCHAR);
}
- }
- /*
- * Removed or renamed events cannot be resolved to the long form.
- * We therefore use the name given by ReadDirectoryChangesW.
- * This may be the long form or the 8.3 short name in some cases.
- */
- if (!long_filenamew) {
+ } else {
+ /*
+ * Removed or renamed events cannot be resolved to the long form.
+ * We therefore use the name given by ReadDirectoryChangesW.
+ * This may be the long form or the 8.3 short name in some cases.
+ */
filenamew = file_info->FileName;
sizew = file_info->FileNameLength / sizeof(WCHAR);
}
@@ -454,38 +460,8 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
sizew = -1;
}
- if (filenamew) {
- /* Convert the filename to utf8. */
- size = WideCharToMultiByte(CP_UTF8,
- 0,
- filenamew,
- sizew,
- NULL,
- 0,
- NULL,
- NULL);
- if (size) {
- filename = (char*)uv__malloc(size + 1);
- if (!filename) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
- }
-
- size = WideCharToMultiByte(CP_UTF8,
- 0,
- filenamew,
- sizew,
- filename,
- size,
- NULL,
- NULL);
- if (size) {
- filename[size] = '\0';
- } else {
- uv__free(filename);
- filename = NULL;
- }
- }
- }
+ /* Convert the filename to utf8. */
+ uv__convert_utf16_to_utf8(filenamew, sizew, &filename);
switch (file_info->Action) {
case FILE_ACTION_ADDED:
@@ -504,6 +480,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
filename = NULL;
uv__free(long_filenamew);
long_filenamew = NULL;
+ filenamew = NULL;
}
offset = file_info->NextEntryOffset;
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 16e3ae7cf1..54dfea7240 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -901,7 +901,15 @@ void fs__scandir(uv_fs_t* req) {
/* Compute the length of the filename in WCHARs. */
wchar_len = info->FileNameLength / sizeof info->FileName[0];
- /* Skip over '.' and '..' entries. */
+ /* Skip over '.' and '..' entries. It has been reported that
+ * the SharePoint driver includes the terminating zero byte in
+ * the filename length. Strip those first.
+ */
+ while (wchar_len > 0 && info->FileName[wchar_len - 1] == L'\0')
+ wchar_len -= 1;
+
+ if (wchar_len == 0)
+ continue;
if (wchar_len == 1 && info->FileName[0] == L'.')
continue;
if (wchar_len == 2 && info->FileName[0] == L'.' &&
@@ -1870,8 +1878,12 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
if (req->flags & UV_FS_FREE_PATHS)
uv__free(req->file.pathw);
- if (req->flags & UV_FS_FREE_PTR)
- uv__free(req->ptr);
+ if (req->flags & UV_FS_FREE_PTR) {
+ if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
+ uv__fs_scandir_cleanup(req);
+ else
+ uv__free(req->ptr);
+ }
req->path = NULL;
req->file.pathw = NULL;
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index c724793bf0..0a7c9404fa 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -83,6 +83,7 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
#define UV_HANDLE_ZERO_READ 0x00080000
#define UV_HANDLE_EMULATE_IOCP 0x00100000
#define UV_HANDLE_BLOCKING_WRITES 0x00200000
+#define UV_HANDLE_CANCELLATION_PENDING 0x00400000
/* Used by uv_tcp_t and uv_udp_t handles */
#define UV_HANDLE_IPV6 0x01000000
@@ -329,7 +330,7 @@ int uv_parent_pid();
int uv_current_pid();
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
int uv__getpwuid_r(uv_passwd_t* pwd);
-int uv__convert_utf16_to_utf8(const WCHAR* utf16, char** utf8);
+int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
/*
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index 1b27f60a6f..9b96377844 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -57,11 +57,23 @@
static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info);
static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info);
+static int uv__cancel_read_console(uv_tty_t* handle);
/* Null uv_buf_t */
static const uv_buf_t uv_null_buf_ = { 0, NULL };
+enum uv__read_console_status_e {
+ NOT_STARTED,
+ IN_PROGRESS,
+ TRAP_REQUESTED,
+ COMPLETED
+};
+
+static volatile LONG uv__read_console_status = NOT_STARTED;
+static volatile LONG uv__restore_screen_state;
+static CONSOLE_SCREEN_BUFFER_INFO uv__saved_screen_state;
+
/*
* The console virtual window.
@@ -173,7 +185,8 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
if (readable) {
/* Initialize TTY input specific fields. */
tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE;
- tty->tty.rd.read_line_handle = NULL;
+ /* TODO: remove me in v2.x. */
+ tty->tty.rd.unused_ = NULL;
tty->tty.rd.read_line_buffer = uv_null_buf_;
tty->tty.rd.read_raw_wait = NULL;
@@ -398,6 +411,8 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
DWORD bytes, read_bytes;
WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3];
DWORD chars, read_chars;
+ LONG status;
+ COORD pos;
assert(data);
@@ -419,7 +434,15 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
/* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */
chars = bytes / 3;
- if (ReadConsoleW(handle->tty.rd.read_line_handle,
+ status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS);
+ if (status == TRAP_REQUESTED) {
+ SET_REQ_SUCCESS(req);
+ req->u.io.overlapped.InternalHigh = 0;
+ POST_COMPLETION_FOR_REQ(loop, req);
+ return 0;
+ }
+
+ if (ReadConsoleW(handle->handle,
(void*) utf16,
chars,
&read_chars,
@@ -438,6 +461,33 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
SET_REQ_ERROR(req, GetLastError());
}
+ InterlockedExchange(&uv__read_console_status, COMPLETED);
+
+ /* If we canceled the read by sending a VK_RETURN event, restore the screen
+ state to undo the visual effect of the VK_RETURN*/
+ if (InterlockedOr(&uv__restore_screen_state, 0)) {
+ HANDLE active_screen_buffer = CreateFileA("conout$",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (active_screen_buffer != INVALID_HANDLE_VALUE) {
+ pos = uv__saved_screen_state.dwCursorPosition;
+
+ /* If the cursor was at the bottom line of the screen buffer, the
+ VK_RETURN would have caused the buffer contents to scroll up by
+ one line. The right position to reset the cursor to is therefore one
+ line higher */
+ if (pos.Y == uv__saved_screen_state.dwSize.Y - 1)
+ pos.Y--;
+
+ SetConsoleCursorPosition(active_screen_buffer, pos);
+ CloseHandle(active_screen_buffer);
+ }
+ }
+
POST_COMPLETION_FOR_REQ(loop, req);
return 0;
}
@@ -463,25 +513,11 @@ static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
}
assert(handle->tty.rd.read_line_buffer.base != NULL);
- /* Duplicate the console handle, so if we want to cancel the read, we can */
- /* just close this handle duplicate. */
- if (handle->tty.rd.read_line_handle == NULL) {
- HANDLE this_process = GetCurrentProcess();
- r = DuplicateHandle(this_process,
- handle->handle,
- this_process,
- &handle->tty.rd.read_line_handle,
- 0,
- 0,
- DUPLICATE_SAME_ACCESS);
- if (!r) {
- handle->tty.rd.read_line_handle = NULL;
- SET_REQ_ERROR(req, GetLastError());
- uv_insert_pending_req(loop, (uv_req_t*)req);
- goto out;
- }
- }
-
+ /* Reset flags No locking is required since there cannot be a line read
+ in progress. We are also relying on the memory barrier provided by
+ QueueUserWorkItem*/
+ uv__restore_screen_state = FALSE;
+ uv__read_console_status = NOT_STARTED;
r = QueueUserWorkItem(uv_tty_line_read_thread,
(void*) req,
WT_EXECUTELONGFUNCTION);
@@ -490,7 +526,6 @@ static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
uv_insert_pending_req(loop, (uv_req_t*)req);
}
- out:
handle->flags |= UV_HANDLE_READ_PENDING;
handle->reqs_pending++;
}
@@ -857,8 +892,7 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
if (!REQ_SUCCESS(req)) {
/* Read was not successful */
- if ((handle->flags & UV_HANDLE_READING) &&
- handle->tty.rd.read_line_handle != NULL) {
+ if (handle->flags & UV_HANDLE_READING) {
/* Real error */
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
@@ -871,10 +905,15 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
}
} else {
- /* Read successful */
- /* TODO: read unicode, convert to utf-8 */
- DWORD bytes = req->u.io.overlapped.InternalHigh;
- handle->read_cb((uv_stream_t*) handle, bytes, &buf);
+ if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) {
+ /* Read successful */
+ /* TODO: read unicode, convert to utf-8 */
+ DWORD bytes = req->u.io.overlapped.InternalHigh;
+ handle->read_cb((uv_stream_t*) handle, bytes, &buf);
+ } else {
+ handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING;
+ handle->read_cb((uv_stream_t*) handle, 0, &buf);
+ }
}
/* Wait for more input events. */
@@ -937,30 +976,82 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
int uv_tty_read_stop(uv_tty_t* handle) {
+ INPUT_RECORD record;
+ DWORD written, err;
+
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(handle->loop, handle);
- /* Cancel raw read */
- if ((handle->flags & UV_HANDLE_READ_PENDING) &&
- (handle->flags & UV_HANDLE_TTY_RAW)) {
+ if (!(handle->flags & UV_HANDLE_READ_PENDING))
+ return 0;
+
+ if (handle->flags & UV_HANDLE_TTY_RAW) {
+ /* Cancel raw read */
/* Write some bullshit event to force the console wait to return. */
- INPUT_RECORD record;
- DWORD written;
memset(&record, 0, sizeof record);
if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {
return GetLastError();
}
+ } else if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) {
+ /* Cancel line-buffered read if not already pending */
+ err = uv__cancel_read_console(handle);
+ if (err)
+ return err;
+
+ handle->flags |= UV_HANDLE_CANCELLATION_PENDING;
+ }
+
+ return 0;
+}
+
+static int uv__cancel_read_console(uv_tty_t* handle) {
+ HANDLE active_screen_buffer = INVALID_HANDLE_VALUE;
+ INPUT_RECORD record;
+ DWORD written;
+ DWORD err = 0;
+ LONG status;
+
+ assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING));
+
+ status = InterlockedExchange(&uv__read_console_status, TRAP_REQUESTED);
+ if (status != IN_PROGRESS) {
+ /* Either we have managed to set a trap for the other thread before
+ ReadConsole is called, or ReadConsole has returned because the user
+ has pressed ENTER. In either case, there is nothing else to do. */
+ return 0;
}
- /* Cancel line-buffered read */
- if (handle->tty.rd.read_line_handle != NULL) {
- /* Closing this handle will cancel the ReadConsole operation */
- CloseHandle(handle->tty.rd.read_line_handle);
- handle->tty.rd.read_line_handle = NULL;
+ /* Save screen state before sending the VK_RETURN event */
+ active_screen_buffer = CreateFileA("conout$",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (active_screen_buffer != INVALID_HANDLE_VALUE &&
+ GetConsoleScreenBufferInfo(active_screen_buffer,
+ &uv__saved_screen_state)) {
+ InterlockedOr(&uv__restore_screen_state, 1);
}
+ /* Write enter key event to force the console wait to return. */
+ record.EventType = KEY_EVENT;
+ record.Event.KeyEvent.bKeyDown = TRUE;
+ record.Event.KeyEvent.wRepeatCount = 1;
+ record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
+ record.Event.KeyEvent.wVirtualScanCode =
+ MapVirtualKeyW(VK_RETURN, MAPVK_VK_TO_VSC);
+ record.Event.KeyEvent.uChar.UnicodeChar = L'\r';
+ record.Event.KeyEvent.dwControlKeyState = 0;
+ if (!WriteConsoleInputW(handle->handle, &record, 1, &written))
+ err = GetLastError();
- return 0;
+ if (active_screen_buffer != INVALID_HANDLE_VALUE)
+ CloseHandle(active_screen_buffer);
+
+ return err;
}
@@ -2045,11 +2136,6 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
if (handle->flags & UV__HANDLE_CLOSING &&
handle->reqs_pending == 0) {
- /* The console handle duplicate used for line reading should be destroyed */
- /* by uv_tty_read_stop. */
- assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
- handle->tty.rd.read_line_handle == NULL);
-
/* The wait handle used for raw reading should be unregistered when the */
/* wait callback runs. */
assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index 1788b1780e..4cebad3908 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -124,7 +124,7 @@ int uv_exepath(char* buffer, size_t* size_ptr) {
utf16_buffer,
-1,
buffer,
- *size_ptr > INT_MAX ? INT_MAX : (int) *size_ptr,
+ (int) *size_ptr,
NULL,
NULL);
if (utf8_len == 0) {
@@ -403,36 +403,13 @@ done:
static int uv__get_process_title() {
WCHAR title_w[MAX_TITLE_LENGTH];
- int length;
if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
return -1;
}
- /* Find out what the size of the buffer is that we need */
- length = WideCharToMultiByte(CP_UTF8, 0, title_w, -1, NULL, 0, NULL, NULL);
- if (!length) {
- return -1;
- }
-
- assert(!process_title);
- process_title = (char*)uv__malloc(length);
- if (!process_title) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
- }
-
- /* Do utf16 -> utf8 conversion here */
- if (!WideCharToMultiByte(CP_UTF8,
- 0,
- title_w,
- -1,
- process_title,
- length,
- NULL,
- NULL)) {
- uv__free(process_title);
+ if (uv__convert_utf16_to_utf8(title_w, -1, &process_title) != 0)
return -1;
- }
return 0;
}
@@ -704,43 +681,9 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
cpu_info->cpu_times.nice = 0;
-
- len = WideCharToMultiByte(CP_UTF8,
- 0,
- cpu_brand,
+ uv__convert_utf16_to_utf8(cpu_brand,
cpu_brand_size / sizeof(WCHAR),
- NULL,
- 0,
- NULL,
- NULL);
- if (len == 0) {
- err = GetLastError();
- goto error;
- }
-
- assert(len > 0);
-
- /* Allocate 1 extra byte for the null terminator. */
- cpu_info->model = uv__malloc(len + 1);
- if (cpu_info->model == NULL) {
- err = ERROR_OUTOFMEMORY;
- goto error;
- }
-
- if (WideCharToMultiByte(CP_UTF8,
- 0,
- cpu_brand,
- cpu_brand_size / sizeof(WCHAR),
- cpu_info->model,
- len,
- NULL,
- NULL) == 0) {
- err = GetLastError();
- goto error;
- }
-
- /* Ensure that cpu_info->model is null terminated. */
- cpu_info->model[len] = '\0';
+ &(cpu_info->model));
}
uv__free(sppi);
@@ -1118,6 +1061,7 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
int uv_getrusage(uv_rusage_t *uv_rusage) {
FILETIME createTime, exitTime, kernelTime, userTime;
SYSTEMTIME kernelSystemTime, userSystemTime;
+ PROCESS_MEMORY_COUNTERS memCounters;
int ret;
ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
@@ -1135,6 +1079,13 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
return uv_translate_sys_error(GetLastError());
}
+ ret = GetProcessMemoryInfo(GetCurrentProcess(),
+ &memCounters,
+ sizeof(memCounters));
+ if (ret == 0) {
+ return uv_translate_sys_error(GetLastError());
+ }
+
memset(uv_rusage, 0, sizeof(*uv_rusage));
uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 +
@@ -1147,6 +1098,9 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
kernelSystemTime.wSecond;
uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000;
+ uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount;
+ uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024;
+
return 0;
}
@@ -1288,20 +1242,36 @@ void uv_os_free_passwd(uv_passwd_t* pwd) {
}
-int uv__convert_utf16_to_utf8(const WCHAR* utf16, char** utf8) {
+/*
+ * Converts a UTF-16 string into a UTF-8 one. The resulting string is
+ * null-terminated.
+ *
+ * If utf16 is null terminated, utf16len can be set to -1, otherwise it must
+ * be specified.
+ */
+int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {
DWORD bufsize;
if (utf16 == NULL)
return UV_EINVAL;
/* Check how much space we need */
- bufsize = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL);
+ bufsize = WideCharToMultiByte(CP_UTF8,
+ 0,
+ utf16,
+ utf16len,
+ NULL,
+ 0,
+ NULL,
+ NULL);
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
- /* Allocate the destination buffer */
- *utf8 = uv__malloc(bufsize);
+ /* Allocate the destination buffer adding an extra byte for the terminating
+ * NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so
+ * we do it ourselves always, just in case. */
+ *utf8 = uv__malloc(bufsize + 1);
if (*utf8 == NULL)
return UV_ENOMEM;
@@ -1310,7 +1280,7 @@ int uv__convert_utf16_to_utf8(const WCHAR* utf16, char** utf8) {
bufsize = WideCharToMultiByte(CP_UTF8,
0,
utf16,
- -1,
+ utf16len,
*utf8,
bufsize,
NULL,
@@ -1318,9 +1288,11 @@ int uv__convert_utf16_to_utf8(const WCHAR* utf16, char** utf8) {
if (bufsize == 0) {
uv__free(*utf8);
+ *utf8 = NULL;
return uv_translate_sys_error(GetLastError());
}
+ (*utf8)[bufsize] = '\0';
return 0;
}
@@ -1366,13 +1338,13 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
}
pwd->homedir = NULL;
- r = uv__convert_utf16_to_utf8(path, &pwd->homedir);
+ r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir);
if (r != 0)
return r;
pwd->username = NULL;
- r = uv__convert_utf16_to_utf8(username, &pwd->username);
+ r = uv__convert_utf16_to_utf8(username, -1, &pwd->username);
if (r != 0) {
uv__free(pwd->homedir);