summaryrefslogtreecommitdiff
path: root/deps/uv/src
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2015-01-05 20:44:25 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2015-01-05 22:25:20 +0100
commiteaed2a11ecf8d4f8a309f42d6bbc72306c01b755 (patch)
tree59abc7b7d4c1396c5bd60a47f13e694076b5b299 /deps/uv/src
parent94e147500c5bf457c9101bda8c8020d8ff896708 (diff)
downloadandroid-node-v8-eaed2a11ecf8d4f8a309f42d6bbc72306c01b755.tar.gz
android-node-v8-eaed2a11ecf8d4f8a309f42d6bbc72306c01b755.tar.bz2
android-node-v8-eaed2a11ecf8d4f8a309f42d6bbc72306c01b755.zip
deps: update libuv to 1.2.0
PR-URL: https://github.com/iojs/io.js/pull/237 Reviewed-By: Bert Belder <bertbelder@gmail.com> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
Diffstat (limited to 'deps/uv/src')
-rw-r--r--deps/uv/src/unix/aix.c2
-rw-r--r--deps/uv/src/unix/core.c22
-rw-r--r--deps/uv/src/unix/darwin.c37
-rw-r--r--deps/uv/src/unix/freebsd.c2
-rw-r--r--deps/uv/src/unix/fs.c38
-rw-r--r--deps/uv/src/unix/internal.h3
-rw-r--r--deps/uv/src/unix/linux-core.c24
-rw-r--r--deps/uv/src/unix/linux-syscalls.c6
-rw-r--r--deps/uv/src/unix/linux-syscalls.h2
-rw-r--r--deps/uv/src/unix/netbsd.c2
-rw-r--r--deps/uv/src/unix/openbsd.c16
-rw-r--r--deps/uv/src/unix/pipe.c17
-rw-r--r--deps/uv/src/unix/sunos.c8
-rw-r--r--deps/uv/src/unix/tty.c47
-rw-r--r--deps/uv/src/unix/udp.c39
-rw-r--r--deps/uv/src/uv-common.h3
-rw-r--r--deps/uv/src/win/core.c7
-rw-r--r--deps/uv/src/win/dl.c35
-rw-r--r--deps/uv/src/win/fs.c288
-rw-r--r--deps/uv/src/win/internal.h4
-rw-r--r--deps/uv/src/win/poll.c44
-rw-r--r--deps/uv/src/win/req-inl.h9
-rw-r--r--deps/uv/src/win/thread.c24
-rw-r--r--deps/uv/src/win/tty.c17
-rw-r--r--deps/uv/src/win/winapi.c7
-rw-r--r--deps/uv/src/win/winapi.h84
-rw-r--r--deps/uv/src/win/winsock.c12
27 files changed, 516 insertions, 283 deletions
diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c
index 349c2b558e..0c5d1f4b50 100644
--- a/deps/uv/src/unix/aix.c
+++ b/deps/uv/src/unix/aix.c
@@ -294,7 +294,7 @@ int uv_exepath(char* buffer, size_t* size) {
int fd;
char **argv;
- if ((buffer == NULL) || (size == NULL))
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index c08040e537..6f284ffa7a 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -74,7 +74,7 @@
#include <sys/ioctl.h>
#endif
-static void uv__run_pending(uv_loop_t* loop);
+static int uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec));
@@ -304,6 +304,7 @@ int uv_loop_alive(const uv_loop_t* loop) {
int uv_run(uv_loop_t* loop, uv_run_mode mode) {
int timeout;
int r;
+ int ran_pending;
r = uv__loop_alive(loop);
if (!r)
@@ -312,12 +313,12 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
while (r != 0 && loop->stop_flag == 0) {
uv__update_time(loop);
uv__run_timers(loop);
- uv__run_pending(loop);
+ ran_pending = uv__run_pending(loop);
uv__run_idle(loop);
uv__run_prepare(loop);
timeout = 0;
- if ((mode & UV_RUN_NOWAIT) == 0)
+ if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
uv__io_poll(loop, timeout);
@@ -338,8 +339,7 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
}
r = uv__loop_alive(loop);
-
- if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
+ if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
break;
}
@@ -635,6 +635,11 @@ int uv_cwd(char* buffer, size_t* size) {
return -errno;
*size = strlen(buffer);
+ if (*size > 1 && buffer[*size - 1] == '/') {
+ buffer[*size-1] = '\0';
+ (*size)--;
+ }
+
return 0;
}
@@ -689,10 +694,13 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
}
-static void uv__run_pending(uv_loop_t* loop) {
+static int uv__run_pending(uv_loop_t* loop) {
QUEUE* q;
uv__io_t* w;
+ if (QUEUE_EMPTY(&loop->pending_queue))
+ return 0;
+
while (!QUEUE_EMPTY(&loop->pending_queue)) {
q = QUEUE_HEAD(&loop->pending_queue);
QUEUE_REMOVE(q);
@@ -701,6 +709,8 @@ static void uv__run_pending(uv_loop_t* loop) {
w = QUEUE_DATA(q, uv__io_t, pending_queue);
w->cb(loop, w, UV__POLLOUT);
}
+
+ return 1;
}
diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c
index c9a45edee4..651545f85e 100644
--- a/deps/uv/src/unix/darwin.c
+++ b/deps/uv/src/unix/darwin.c
@@ -65,28 +65,33 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
int uv_exepath(char* buffer, size_t* size) {
- uint32_t usize;
- int result;
- char* path;
- char* fullpath;
+ /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */
+ char abspath[PATH_MAX * 2 + 1];
+ char exepath[PATH_MAX + 1];
+ uint32_t exepath_size;
+ size_t abspath_size;
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
- usize = *size;
- result = _NSGetExecutablePath(buffer, &usize);
- if (result) return result;
+ exepath_size = sizeof(exepath);
+ if (_NSGetExecutablePath(exepath, &exepath_size))
+ return -EIO;
- path = malloc(2 * PATH_MAX);
- fullpath = realpath(buffer, path);
- if (fullpath == NULL) {
- SAVE_ERRNO(free(path));
+ if (realpath(exepath, abspath) != abspath)
return -errno;
- }
- strncpy(buffer, fullpath, *size);
- free(fullpath);
- *size = strlen(buffer);
+ abspath_size = strlen(abspath);
+ if (abspath_size == 0)
+ return -EIO;
+
+ *size -= 1;
+ if (*size > abspath_size)
+ *size = abspath_size;
+
+ memcpy(buffer, abspath, *size);
+ buffer[*size] = '\0';
+
return 0;
}
diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c
index d59e3773a5..55492adc48 100644
--- a/deps/uv/src/unix/freebsd.c
+++ b/deps/uv/src/unix/freebsd.c
@@ -78,7 +78,7 @@ int uv_exepath(char* buffer, size_t* size) {
int mib[4];
size_t cb;
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
#ifdef __DragonFly__
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 65fd01230b..e7eee2f9ab 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -35,8 +35,10 @@
#include <string.h>
#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/uio.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
@@ -48,30 +50,12 @@
defined(__OpenBSD__) || \
defined(__NetBSD__)
# define HAVE_PREADV 1
-#elif defined(__linux__)
-# include <linux/version.h>
-# if defined(__GLIBC_PREREQ)
-# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) && \
- __GLIBC_PREREQ(2,10)
-# define HAVE_PREADV 1
-# else
-# define HAVE_PREADV 0
-# endif
-# else
-# define HAVE_PREADV 0
-# endif
#else
# define HAVE_PREADV 0
#endif
#if defined(__linux__) || defined(__sun)
# include <sys/sendfile.h>
-#elif defined(__APPLE__) || defined(__FreeBSD__)
-# include <sys/socket.h>
-#endif
-
-#if HAVE_PREADV || defined(__APPLE__)
-# include <sys/uio.h>
#endif
#define INIT(type) \
@@ -219,6 +203,9 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
static ssize_t uv__fs_read(uv_fs_t* req) {
+#if defined(__linux__)
+ static int no_preadv;
+#endif
ssize_t result;
#if defined(_AIX)
@@ -245,16 +232,12 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
#else
# if defined(__linux__)
- static int no_preadv;
- if (no_preadv)
+ if (no_preadv) retry:
# endif
{
off_t nread;
size_t index;
-# if defined(__linux__)
- retry:
-# endif
nread = 0;
index = 0;
result = 1;
@@ -578,6 +561,9 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
static ssize_t uv__fs_write(uv_fs_t* req) {
+#if defined(__linux__)
+ static int no_pwritev;
+#endif
ssize_t r;
/* Serialize writes on OS X, concurrent write() and pwrite() calls result in
@@ -603,16 +589,12 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
#else
# if defined(__linux__)
- static int no_pwritev;
- if (no_pwritev)
+ if (no_pwritev) retry:
# endif
{
off_t written;
size_t index;
-# if defined(__linux__)
- retry:
-# endif
written = 0;
index = 0;
r = 0;
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index daad61b782..03a9226101 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -52,9 +52,6 @@
# include <CoreServices/CoreServices.h>
#endif
-#define STATIC_ASSERT(expr) \
- void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])
-
#define ACCESS_ONCE(type, var) \
(*(volatile type*) &(var))
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index a2145b0f36..d77b13fd6f 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -33,7 +33,6 @@
#include <sys/prctl.h>
#include <sys/sysinfo.h>
#include <unistd.h>
-#include <signal.h>
#include <fcntl.h>
#include <time.h>
@@ -142,8 +141,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
struct uv__epoll_event e;
QUEUE* q;
uv__io_t* w;
- sigset_t* pset;
- sigset_t set;
+ uint64_t sigmask;
uint64_t base;
uint64_t diff;
int nevents;
@@ -194,24 +192,21 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w->events = w->pevents;
}
- pset = NULL;
- if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
- pset = &set;
- sigemptyset(pset);
- sigaddset(pset, SIGPROF);
- }
+ sigmask = 0;
+ if (loop->flags & UV_LOOP_BLOCK_SIGPROF)
+ sigmask |= 1 << (SIGPROF - 1);
assert(timeout >= -1);
base = loop->time;
count = 48; /* Benchmarks suggest this gives the best throughput. */
for (;;) {
- if (no_epoll_wait || pset != NULL) {
+ if (no_epoll_wait || sigmask) {
nfds = uv__epoll_pwait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout,
- pset);
+ sigmask);
} else {
nfds = uv__epoll_wait(loop->backend_fd,
events,
@@ -383,10 +378,13 @@ void uv_loadavg(double avg[3]) {
int uv_exepath(char* buffer, size_t* size) {
ssize_t n;
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
- n = readlink("/proc/self/exe", buffer, *size - 1);
+ n = *size - 1;
+ if (n > 0)
+ n = readlink("/proc/self/exe", buffer, n);
+
if (n == -1)
return -errno;
diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c
index e036fad5ef..7bf2c0f87d 100644
--- a/deps/uv/src/unix/linux-syscalls.c
+++ b/deps/uv/src/unix/linux-syscalls.c
@@ -321,15 +321,15 @@ int uv__epoll_pwait(int epfd,
struct uv__epoll_event* events,
int nevents,
int timeout,
- const sigset_t* sigmask) {
+ uint64_t sigmask) {
#if defined(__NR_epoll_pwait)
return syscall(__NR_epoll_pwait,
epfd,
events,
nevents,
timeout,
- sigmask,
- _NSIG / 8);
+ &sigmask,
+ sizeof(sigmask));
#else
return errno = ENOSYS, -1;
#endif
diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h
index fd6bb48665..6f249b7245 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -131,7 +131,7 @@ int uv__epoll_pwait(int epfd,
struct uv__epoll_event* events,
int nevents,
int timeout,
- const sigset_t* sigmask);
+ uint64_t sigmask);
int uv__eventfd2(unsigned int count, int flags);
int uv__inotify_init(void);
int uv__inotify_init1(int flags);
diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c
index 5f1182f8b4..de99d135f7 100644
--- a/deps/uv/src/unix/netbsd.c
+++ b/deps/uv/src/unix/netbsd.c
@@ -83,7 +83,7 @@ int uv_exepath(char* buffer, size_t* size) {
size_t cb;
pid_t mypid;
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
mypid = getpid();
diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c
index cde8d4d0c9..3e7ae848ee 100644
--- a/deps/uv/src/unix/openbsd.c
+++ b/deps/uv/src/unix/openbsd.c
@@ -85,7 +85,7 @@ int uv_exepath(char* buffer, size_t* size) {
pid_t mypid;
int err;
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
mypid = getpid();
@@ -108,17 +108,19 @@ int uv_exepath(char* buffer, size_t* size) {
}
argsbuf_size *= 2U;
}
+
if (argsbuf[0] == NULL) {
err = -EINVAL; /* FIXME(bnoordhuis) More appropriate error. */
goto out;
}
+
+ *size -= 1;
exepath_size = strlen(argsbuf[0]);
- if (exepath_size >= *size) {
- err = -EINVAL;
- goto out;
- }
- memcpy(buffer, argsbuf[0], exepath_size + 1U);
- *size = exepath_size;
+ if (*size > exepath_size)
+ *size = exepath_size;
+
+ memcpy(buffer, argsbuf[0], *size);
+ buffer[*size] = '\0';
err = 0;
out:
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index b20fb9210c..ef47700b7a 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -55,17 +55,15 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
/* Make a copy of the file name, it outlives this function's scope. */
pipe_fname = strdup(name);
- if (pipe_fname == NULL) {
- err = -ENOMEM;
- goto out;
- }
+ if (pipe_fname == NULL)
+ return -ENOMEM;
/* We've got a copy, don't touch the original any more. */
name = NULL;
err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
if (err < 0)
- goto out;
+ goto err_socket;
sockfd = err;
memset(&saddr, 0, sizeof saddr);
@@ -78,7 +76,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
/* Convert ENOENT to EACCES for compatibility with Windows. */
if (err == -ENOENT)
err = -EACCES;
- goto out;
+ goto err_bind;
}
/* Success. */
@@ -86,11 +84,10 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
handle->io_watcher.fd = sockfd;
return 0;
-out:
- /* unlink() before uv__close() to avoid races. */
- assert(pipe_fname != NULL);
- unlink(pipe_fname);
+err_bind:
uv__close(sockfd);
+
+err_socket:
free((void*)pipe_fname);
return err;
}
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index d6fb7f4950..ca183a6227 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -300,11 +300,15 @@ int uv_exepath(char* buffer, size_t* size) {
ssize_t res;
char buf[128];
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid());
- res = readlink(buf, buffer, *size - 1);
+
+ res = *size - 1;
+ if (res > 0)
+ res = readlink(buf, buffer, res);
+
if (res == -1)
return -errno;
diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c
index 7ae19905fb..068025eaf5 100644
--- a/deps/uv/src/unix/tty.c
+++ b/deps/uv/src/unix/tty.c
@@ -98,19 +98,19 @@ skip:
uv__nonblock(fd, 1);
uv__stream_open((uv_stream_t*) tty, fd, flags);
- tty->mode = 0;
+ tty->mode = UV_TTY_MODE_NORMAL;
return 0;
}
-int uv_tty_set_mode(uv_tty_t* tty, int mode) {
- struct termios raw;
+int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
+ struct termios tmp;
int fd;
fd = uv__stream_fd(tty);
- if (mode && tty->mode == 0) { /* on */
+ if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
if (tcgetattr(fd, &tty->orig_termios))
return -errno;
@@ -121,27 +121,30 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) {
orig_termios_fd = fd;
}
uv_spinlock_unlock(&termios_spinlock);
+ }
- raw = tty->orig_termios;
- raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
- raw.c_oflag |= (ONLCR);
- raw.c_cflag |= (CS8);
- raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
- raw.c_cc[VMIN] = 1;
- raw.c_cc[VTIME] = 0;
-
- /* Put terminal in raw mode after draining */
- if (tcsetattr(fd, TCSADRAIN, &raw))
- return -errno;
-
- tty->mode = 1;
- } else if (mode == 0 && tty->mode) { /* off */
- /* Put terminal in original mode after flushing */
- if (tcsetattr(fd, TCSAFLUSH, &tty->orig_termios))
- return -errno;
- tty->mode = 0;
+ tmp = tty->orig_termios;
+ switch (mode) {
+ case UV_TTY_MODE_NORMAL:
+ break;
+ case UV_TTY_MODE_RAW:
+ tmp.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ tmp.c_oflag |= (ONLCR);
+ tmp.c_cflag |= (CS8);
+ tmp.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+ tmp.c_cc[VMIN] = 1;
+ tmp.c_cc[VTIME] = 0;
+ break;
+ case UV_TTY_MODE_IO:
+ cfmakeraw(&tmp);
+ break;
}
+ /* Apply changes after draining */
+ if (tcsetattr(fd, TCSADRAIN, &tmp))
+ return -errno;
+
+ tty->mode = mode;
return 0;
}
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index 71a0e41f1f..2e1824c358 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -598,7 +598,11 @@ int uv_udp_set_membership(uv_udp_t* handle,
}
-static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) {
+static int uv__setsockopt_maybe_char(uv_udp_t* handle,
+ int option4,
+ int option6,
+ int val) {
+ int r;
#if defined(__sun) || defined(_AIX)
char arg = val;
#else
@@ -608,7 +612,20 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) {
if (val < 0 || val > 255)
return -EINVAL;
- if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, option, &arg, sizeof(arg)))
+ if (handle->flags & UV_HANDLE_IPV6)
+ r = setsockopt(handle->io_watcher.fd,
+ IPPROTO_IPV6,
+ option6,
+ &arg,
+ sizeof(arg));
+ else
+ r = setsockopt(handle->io_watcher.fd,
+ IPPROTO_IP,
+ option4,
+ &arg,
+ sizeof(arg));
+
+ if (r)
return -errno;
return 0;
@@ -632,20 +649,26 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
if (ttl < 1 || ttl > 255)
return -EINVAL;
- if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)))
- return -errno;
-
- return 0;
+ return uv__setsockopt_maybe_char(handle,
+ IP_TTL,
+ IPV6_UNICAST_HOPS,
+ ttl);
}
int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
- return uv__setsockopt_maybe_char(handle, IP_MULTICAST_TTL, ttl);
+ return uv__setsockopt_maybe_char(handle,
+ IP_MULTICAST_TTL,
+ IPV6_MULTICAST_HOPS,
+ ttl);
}
int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
- return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, on);
+ return uv__setsockopt_maybe_char(handle,
+ IP_MULTICAST_LOOP,
+ IPV6_MULTICAST_LOOP,
+ on);
}
int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index 7d3c58f121..11e7fc395c 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -46,6 +46,9 @@
#define container_of(ptr, type, member) \
((type *) ((char *) (ptr) - offsetof(type, member)))
+#define STATIC_ASSERT(expr) \
+ void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])
+
#ifndef _WIN32
enum {
UV__HANDLE_INTERNAL = 0x8000,
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index 48897cf29b..2bef8b7f33 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -387,6 +387,7 @@ int uv_loop_alive(const uv_loop_t* loop) {
int uv_run(uv_loop_t *loop, uv_run_mode mode) {
DWORD timeout;
int r;
+ int ran_pending;
void (*poll)(uv_loop_t* loop, DWORD timeout);
if (pGetQueuedCompletionStatusEx)
@@ -402,12 +403,12 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
uv_update_time(loop);
uv_process_timers(loop);
- uv_process_reqs(loop);
+ ran_pending = uv_process_reqs(loop);
uv_idle_invoke(loop);
uv_prepare_invoke(loop);
timeout = 0;
- if ((mode & UV_RUN_NOWAIT) == 0)
+ if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
(*poll)(loop, timeout);
@@ -428,7 +429,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
}
r = uv__loop_alive(loop);
- if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
+ if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
break;
}
diff --git a/deps/uv/src/win/dl.c b/deps/uv/src/win/dl.c
index 2ef1f6c54f..e5f3407f8e 100644
--- a/deps/uv/src/win/dl.c
+++ b/deps/uv/src/win/dl.c
@@ -69,17 +69,44 @@ const char* uv_dlerror(const uv_lib_t* lib) {
}
+static void uv__format_fallback_error(uv_lib_t* lib, int errorno){
+ DWORD_PTR args[1] = { (DWORD_PTR) errorno };
+ LPSTR fallback_error = "error: %1!d!";
+
+ FormatMessageA(FORMAT_MESSAGE_FROM_STRING |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ fallback_error, 0, 0,
+ (LPSTR) &lib->errmsg,
+ 0, (va_list*) args);
+}
+
+
+
static int uv__dlerror(uv_lib_t* lib, int errorno) {
+ DWORD res;
+
if (lib->errmsg) {
LocalFree((void*)lib->errmsg);
lib->errmsg = NULL;
}
if (errorno) {
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
- (LPSTR)&lib->errmsg, 0, NULL);
+ res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ (LPSTR) &lib->errmsg, 0, NULL);
+ if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) {
+ res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
+ 0, (LPSTR) &lib->errmsg, 0, NULL);
+ }
+
+ if (!res) {
+ uv__format_fallback_error(lib, errorno);
+ }
}
return errorno ? -1 : 0;
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 30a457a023..33bc9da304 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -43,8 +43,6 @@
#define UV_FS_FREE_PTR 0x0008
#define UV_FS_CLEANEDUP 0x0010
-static const int uv__fs_dirent_slide = 0x20;
-
#define QUEUE_FS_TP_JOB(loop, req) \
do { \
@@ -788,123 +786,203 @@ void fs__mkdtemp(uv_fs_t* req) {
void fs__scandir(uv_fs_t* req) {
- WCHAR* pathw = req->pathw;
- size_t len = wcslen(pathw);
- int result;
- WCHAR* name;
- HANDLE dir;
- WIN32_FIND_DATAW ent = { 0 };
- WCHAR* path2;
- const WCHAR* fmt;
- uv__dirent_t** dents;
- int dent_size;
-
- if (len == 0) {
- fmt = L"./*";
- } else if (pathw[len - 1] == L'/' || pathw[len - 1] == L'\\') {
- fmt = L"%s*";
- } else {
- fmt = L"%s\\*";
- }
+ static const size_t dirents_initial_size = 32;
- /* Figure out whether path is a file or a directory. */
- if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) {
- req->result = UV_ENOTDIR;
- req->sys_errno_ = ERROR_SUCCESS;
- return;
- }
-
- path2 = (WCHAR*)malloc(sizeof(WCHAR) * (len + 4));
- if (!path2) {
- SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
- return;
- }
+ HANDLE dir_handle = INVALID_HANDLE_VALUE;
- _snwprintf(path2, len + 3, fmt, pathw);
- dir = FindFirstFileW(path2, &ent);
- free(path2);
-
- if(dir == INVALID_HANDLE_VALUE) {
- SET_REQ_WIN32_ERROR(req, GetLastError());
- return;
- }
-
- result = 0;
- dents = NULL;
- dent_size = 0;
-
- do {
- uv__dirent_t* dent;
- int utf8_len;
-
- name = ent.cFileName;
-
- if (!(name[0] != L'.' || (name[1] && (name[1] != L'.' || name[2]))))
- continue;
+ uv__dirent_t** dirents = NULL;
+ size_t dirents_size = 0;
+ size_t dirents_used = 0;
- /* Grow dents buffer, if needed */
- if (result >= dent_size) {
- uv__dirent_t** tmp;
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS status;
- dent_size += uv__fs_dirent_slide;
- tmp = realloc(dents, dent_size * sizeof(*dents));
- if (tmp == NULL) {
- SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
- goto fatal;
+ /* Buffer to hold directory entries returned by NtQueryDirectoryFile.
+ * It's important that this buffer can hold at least one entry, regardless
+ * of the length of the file names present in the enumerated directory.
+ * A file name is at most 256 WCHARs long.
+ * According to MSDN, the buffer must be aligned at an 8-byte boundary.
+ */
+ __declspec(align(8)) char buffer[8192];
+
+ STATIC_ASSERT(sizeof buffer >=
+ sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR));
+
+ /* Open the directory. */
+ dir_handle =
+ CreateFileW(req->pathw,
+ FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+ if (dir_handle == INVALID_HANDLE_VALUE)
+ goto win32_error;
+
+ /* Read the first chunk. */
+ status = pNtQueryDirectoryFile(dir_handle,
+ NULL,
+ NULL,
+ NULL,
+ &iosb,
+ &buffer,
+ sizeof buffer,
+ FileDirectoryInformation,
+ FALSE,
+ NULL,
+ TRUE);
+
+ /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER.
+ * This should be reported back as UV_ENOTDIR.
+ */
+ if (status == STATUS_INVALID_PARAMETER)
+ goto not_a_directory_error;
+
+ while (NT_SUCCESS(status)) {
+ char* position = buffer;
+ size_t next_entry_offset = 0;
+
+ do {
+ FILE_DIRECTORY_INFORMATION* info;
+ uv__dirent_t* dirent;
+
+ size_t wchar_len;
+ size_t utf8_len;
+
+ /* Obtain a pointer to the current directory entry. */
+ position += next_entry_offset;
+ info = (FILE_DIRECTORY_INFORMATION*) position;
+
+ /* Fetch the offset to the next directory entry. */
+ next_entry_offset = info->NextEntryOffset;
+
+ /* Compute the length of the filename in WCHARs. */
+ wchar_len = info->FileNameLength / sizeof info->FileName[0];
+
+ /* Skip over '.' and '..' entries. */
+ if (wchar_len == 1 && info->FileName[0] == L'.')
+ continue;
+ if (wchar_len == 2 && info->FileName[0] == L'.' &&
+ info->FileName[1] == L'.')
+ continue;
+
+ /* Compute the space required to store the filename as UTF-8. */
+ utf8_len = WideCharToMultiByte(
+ CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL);
+ if (utf8_len == 0)
+ goto win32_error;
+
+ /* Resize the dirent array if needed. */
+ if (dirents_used >= dirents_size) {
+ size_t new_dirents_size =
+ dirents_size == 0 ? dirents_initial_size : dirents_size << 1;
+ uv__dirent_t** new_dirents =
+ realloc(dirents, new_dirents_size * sizeof *dirents);
+
+ if (new_dirents == NULL)
+ goto out_of_memory_error;
+
+ dirents_size = new_dirents_size;
+ dirents = new_dirents;
}
- dents = tmp;
- }
-
- /* Allocate enough space to fit utf8 encoding of file name */
- len = wcslen(name);
- utf8_len = uv_utf16_to_utf8(name, len, NULL, 0);
- if (!utf8_len) {
- SET_REQ_WIN32_ERROR(req, GetLastError());
- goto fatal;
- }
-
- dent = malloc(sizeof(*dent) + utf8_len + 1);
- if (dent == NULL) {
- SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
- goto fatal;
- }
- /* Copy file name */
- utf8_len = uv_utf16_to_utf8(name, len, dent->d_name, utf8_len);
- if (!utf8_len) {
- free(dent);
- SET_REQ_WIN32_ERROR(req, GetLastError());
- goto fatal;
- }
- dent->d_name[utf8_len] = '\0';
-
- /* Copy file type */
- if ((ent.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
- dent->d_type = UV__DT_DIR;
- else if ((ent.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
- dent->d_type = UV__DT_LINK;
- else
- dent->d_type = UV__DT_FILE;
+ /* Allocate space for the uv dirent structure. The dirent structure
+ * includes room for the first character of the filename, but `utf8_len`
+ * doesn't count the NULL terminator at this point.
+ */
+ dirent = malloc(sizeof *dirent + utf8_len);
+ if (dirent == NULL)
+ goto out_of_memory_error;
+
+ dirents[dirents_used++] = dirent;
+
+ /* Convert file name to UTF-8. */
+ if (WideCharToMultiByte(CP_UTF8,
+ 0,
+ &info->FileName[0],
+ wchar_len,
+ &dirent->d_name[0],
+ utf8_len,
+ NULL,
+ NULL) == 0)
+ goto win32_error;
+
+ /* Add a null terminator to the filename. */
+ dirent->d_name[utf8_len] = '\0';
+
+ /* Fill out the type field. */
+ if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE)
+ dirent->d_type = UV__DT_CHAR;
+ else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ dirent->d_type = UV__DT_LINK;
+ else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ dirent->d_type = UV__DT_DIR;
+ else
+ dirent->d_type = UV__DT_FILE;
+ } while (next_entry_offset != 0);
+
+ /* Read the next chunk. */
+ status = pNtQueryDirectoryFile(dir_handle,
+ NULL,
+ NULL,
+ NULL,
+ &iosb,
+ &buffer,
+ sizeof buffer,
+ FileDirectoryInformation,
+ FALSE,
+ NULL,
+ FALSE);
+
+ /* After the first pNtQueryDirectoryFile call, the function may return
+ * STATUS_SUCCESS even if the buffer was too small to hold at least one
+ * directory entry.
+ */
+ if (status == STATUS_SUCCESS && iosb.Information == 0)
+ status = STATUS_BUFFER_OVERFLOW;
+ }
- dents[result++] = dent;
- } while(FindNextFileW(dir, &ent));
+ if (status != STATUS_NO_MORE_FILES)
+ goto nt_error;
- FindClose(dir);
+ CloseHandle(dir_handle);
- if (dents != NULL)
+ /* Store the result in the request object. */
+ req->ptr = dirents;
+ if (dirents != NULL)
req->flags |= UV_FS_FREE_PTR;
- /* NOTE: nbufs will be used as index */
+ SET_REQ_RESULT(req, dirents_used);
+
+ /* `nbufs` will be used as index by uv_fs_scandir_next. */
req->nbufs = 0;
- req->ptr = dents;
- SET_REQ_RESULT(req, result);
+
return;
-fatal:
- /* Deallocate dents */
- for (result--; result >= 0; result--)
- free(dents[result]);
- free(dents);
+nt_error:
+ SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
+ goto cleanup;
+
+win32_error:
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ goto cleanup;
+
+not_a_directory_error:
+ SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
+ goto cleanup;
+
+out_of_memory_error:
+ SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+ goto cleanup;
+
+cleanup:
+ if (dir_handle != INVALID_HANDLE_VALUE)
+ CloseHandle(dir_handle);
+ while (dirents_used > 0)
+ free(dirents[--dirents_used]);
+ if (dirents != NULL)
+ free(dirents);
}
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index d87402b73a..89290aea32 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -364,8 +364,8 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
int* addr_len, WSAOVERLAPPED *overlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
-int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
- OVERLAPPED* overlapped);
+int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
+ AFD_POLL_INFO* info_out, OVERLAPPED* overlapped);
/* Whether there are any non-IFS LSPs stacked on TCP */
extern int uv_tcp_non_ifs_lsp_ipv4;
diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c
index 622cbabe39..578d9fff17 100644
--- a/deps/uv/src/win/poll.c
+++ b/deps/uv/src/win/poll.c
@@ -46,6 +46,8 @@ typedef struct uv_single_fd_set_s {
static OVERLAPPED overlapped_dummy_;
static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT;
+static AFD_POLL_INFO afd_poll_info_dummy_;
+
static void uv__init_overlapped_dummy(void) {
HANDLE event;
@@ -65,6 +67,11 @@ static OVERLAPPED* uv__get_overlapped_dummy() {
}
+static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() {
+ return &afd_poll_info_dummy_;
+}
+
+
static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
uv_req_t* req;
AFD_POLL_INFO* afd_poll_info;
@@ -79,7 +86,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
handle->mask_events_2 = handle->events;
} else if (handle->submitted_events_2 == 0) {
req = &handle->poll_req_2;
- afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[0];
+ afd_poll_info = &handle->afd_poll_info_2;
handle->submitted_events_2 = handle->events;
handle->mask_events_1 = handle->events;
handle->mask_events_2 = 0;
@@ -109,6 +116,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
result = uv_msafd_poll((SOCKET) handle->peer_socket,
afd_poll_info,
+ afd_poll_info,
&req->overlapped);
if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) {
/* Queue this req, reporting an error. */
@@ -119,26 +127,25 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
- AFD_POLL_INFO* afd_poll_info;
+ AFD_POLL_INFO afd_poll_info;
DWORD result;
- afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[1];
- afd_poll_info->Exclusive = TRUE;
- afd_poll_info->NumberOfHandles = 1;
- afd_poll_info->Timeout.QuadPart = INT64_MAX;
- afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket;
- afd_poll_info->Handles[0].Status = 0;
- afd_poll_info->Handles[0].Events = AFD_POLL_ALL;
+ afd_poll_info.Exclusive = TRUE;
+ afd_poll_info.NumberOfHandles = 1;
+ afd_poll_info.Timeout.QuadPart = INT64_MAX;
+ afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
+ afd_poll_info.Handles[0].Status = 0;
+ afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
result = uv_msafd_poll(handle->socket,
- afd_poll_info,
+ &afd_poll_info,
+ uv__get_afd_poll_info_dummy(),
uv__get_overlapped_dummy());
if (result == SOCKET_ERROR) {
DWORD error = WSAGetLastError();
- if (error != WSA_IO_PENDING) {
- return WSAGetLastError();
- }
+ if (error != WSA_IO_PENDING)
+ return error;
}
return 0;
@@ -155,7 +162,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
handle->submitted_events_1 = 0;
mask_events = handle->mask_events_1;
} else if (req == &handle->poll_req_2) {
- afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[0];
+ afd_poll_info = &handle->afd_poll_info_2;
handle->submitted_events_2 = 0;
mask_events = handle->mask_events_2;
} else {
@@ -558,11 +565,6 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
handle->poll_req_2.type = UV_POLL_REQ;
handle->poll_req_2.data = handle;
- handle->afd_poll_info_2.afd_poll_info_ptr = malloc(sizeof(*handle->afd_poll_info_2.afd_poll_info_ptr) * 2);
- if (handle->afd_poll_info_2.afd_poll_info_ptr == NULL) {
- return UV_ENOMEM;
- }
-
return 0;
}
@@ -624,9 +626,5 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
assert(handle->submitted_events_1 == 0);
assert(handle->submitted_events_2 == 0);
- if (handle->afd_poll_info_2.afd_poll_info_ptr) {
- free(handle->afd_poll_info_2.afd_poll_info_ptr);
- handle->afd_poll_info_2.afd_poll_info_ptr = NULL;
- }
uv__handle_close(handle);
}
diff --git a/deps/uv/src/win/req-inl.h b/deps/uv/src/win/req-inl.h
index 97342e5c7e..46c7d9b106 100644
--- a/deps/uv/src/win/req-inl.h
+++ b/deps/uv/src/win/req-inl.h
@@ -130,14 +130,13 @@ INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) {
} while (0)
-INLINE static void uv_process_reqs(uv_loop_t* loop) {
+INLINE static int uv_process_reqs(uv_loop_t* loop) {
uv_req_t* req;
uv_req_t* first;
uv_req_t* next;
- if (loop->pending_reqs_tail == NULL) {
- return;
- }
+ if (loop->pending_reqs_tail == NULL)
+ return 0;
first = loop->pending_reqs_tail->next_req;
next = first;
@@ -207,6 +206,8 @@ INLINE static void uv_process_reqs(uv_loop_t* loop) {
assert(0);
}
}
+
+ return 1;
}
#endif /* UV_WIN_REQ_INL_H_ */
diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c
index a697d7ae74..993d66162c 100644
--- a/deps/uv/src/win/thread.c
+++ b/deps/uv/src/win/thread.c
@@ -117,7 +117,19 @@ void uv_once(uv_once_t* guard, void (*callback)(void)) {
uv__once_inner(guard, callback);
}
-static UV_THREAD_LOCAL uv_thread_t uv__current_thread = NULL;
+
+/* Verify that uv_thread_t can be stored in a TLS slot. */
+STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*));
+
+static uv_key_t uv__current_thread_key;
+static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT;
+
+
+static void uv__init_current_thread_key(void) {
+ if (uv_key_create(&uv__current_thread_key))
+ abort();
+}
+
struct thread_ctx {
void (*entry)(void* arg);
@@ -126,8 +138,7 @@ struct thread_ctx {
};
-static UINT __stdcall uv__thread_start(void* arg)
-{
+static UINT __stdcall uv__thread_start(void* arg) {
struct thread_ctx *ctx_p;
struct thread_ctx ctx;
@@ -135,7 +146,9 @@ static UINT __stdcall uv__thread_start(void* arg)
ctx = *ctx_p;
free(ctx_p);
- uv__current_thread = ctx.self;
+ uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
+ uv_key_set(&uv__current_thread_key, (void*) ctx.self);
+
ctx.entry(ctx.arg);
return 0;
@@ -177,9 +190,10 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
uv_thread_t uv_thread_self(void) {
- return uv__current_thread;
+ return (uv_thread_t) uv_key_get(&uv__current_thread_key);
}
+
int uv_thread_join(uv_thread_t *tid) {
if (WaitForSingleObject(*tid, INFINITE))
return uv_translate_sys_error(GetLastError());
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index 6d6709f79e..be4a8b81e4 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -170,7 +170,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
}
-int uv_tty_set_mode(uv_tty_t* tty, int mode) {
+int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
DWORD flags;
unsigned char was_reading;
uv_alloc_cb alloc_cb;
@@ -185,12 +185,15 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) {
return 0;
}
- if (mode) {
- /* Raw input */
- flags = ENABLE_WINDOW_INPUT;
- } else {
- /* Line-buffered mode. */
- flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
+ switch (mode) {
+ case UV_TTY_MODE_NORMAL:
+ flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
+ break;
+ case UV_TTY_MODE_RAW:
+ flags = ENABLE_WINDOW_INPUT;
+ break;
+ case UV_TTY_MODE_IO:
+ return UV_ENOTSUP;
}
if (!SetConsoleMode(tty->handle, flags)) {
diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c
index 84ce73e3a0..f3f27f77c1 100644
--- a/deps/uv/src/win/winapi.c
+++ b/deps/uv/src/win/winapi.c
@@ -31,6 +31,7 @@ sNtDeviceIoControlFile pNtDeviceIoControlFile;
sNtQueryInformationFile pNtQueryInformationFile;
sNtSetInformationFile pNtSetInformationFile;
sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
+sNtQueryDirectoryFile pNtQueryDirectoryFile;
sNtQuerySystemInformation pNtQuerySystemInformation;
@@ -97,6 +98,12 @@ void uv_winapi_init() {
uv_fatal_error(GetLastError(), "GetProcAddress");
}
+ pNtQueryDirectoryFile = (sNtQueryDirectoryFile)
+ GetProcAddress(ntdll_module, "NtQueryDirectoryFile");
+ if (pNtQueryVolumeInformationFile == NULL) {
+ uv_fatal_error(GetLastError(), "GetProcAddress");
+ }
+
pNtQuerySystemInformation = (sNtQuerySystemInformation) GetProcAddress(
ntdll_module,
"NtQuerySystemInformation");
diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h
index 1bb0e9aae1..f4f9145b38 100644
--- a/deps/uv/src/win/winapi.h
+++ b/deps/uv/src/win/winapi.h
@@ -4104,12 +4104,23 @@
# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000
#endif
+/* from winternl.h */
+typedef struct _UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR Buffer;
+} UNICODE_STRING, *PUNICODE_STRING;
+
+typedef const UNICODE_STRING *PCUNICODE_STRING;
+
+/* from ntifs.h */
#ifndef DEVICE_TYPE
# define DEVICE_TYPE DWORD
#endif
-/* from ntifs.h */
-/* MinGW already has it, mingw-w64 does not. */
+/* MinGW already has a definition for REPARSE_DATA_BUFFER, but mingw-w64 does
+ * not.
+ */
#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
@@ -4205,6 +4216,37 @@ typedef enum _FILE_INFORMATION_CLASS {
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+typedef struct _FILE_DIRECTORY_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
+
+typedef struct _FILE_BOTH_DIR_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ CCHAR ShortNameLength;
+ WCHAR ShortName[12];
+ WCHAR FileName[1];
+} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
+
typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
@@ -4512,6 +4554,19 @@ typedef NTSTATUS (NTAPI *sNtQuerySystemInformation)
ULONG SystemInformationLength,
PULONG ReturnLength);
+typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
+ (HANDLE FileHandle,
+ HANDLE Event,
+ PIO_APC_ROUTINE ApcRoutine,
+ PVOID ApcContext,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID FileInformation,
+ ULONG Length,
+ FILE_INFORMATION_CLASS FileInformationClass,
+ BOOLEAN ReturnSingleEntry,
+ PUNICODE_STRING FileName,
+ BOOLEAN RestartScan
+ );
/*
* Kernel32 headers
@@ -4555,6 +4610,30 @@ typedef NTSTATUS (NTAPI *sNtQuerySystemInformation)
# define ERROR_SYMLINK_NOT_SUPPORTED 1464
#endif
+#ifndef ERROR_MUI_FILE_NOT_FOUND
+# define ERROR_MUI_FILE_NOT_FOUND 15100
+#endif
+
+#ifndef ERROR_MUI_INVALID_FILE
+# define ERROR_MUI_INVALID_FILE 15101
+#endif
+
+#ifndef ERROR_MUI_INVALID_RC_CONFIG
+# define ERROR_MUI_INVALID_RC_CONFIG 15102
+#endif
+
+#ifndef ERROR_MUI_INVALID_LOCALE_NAME
+# define ERROR_MUI_INVALID_LOCALE_NAME 15103
+#endif
+
+#ifndef ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME
+# define ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME 15104
+#endif
+
+#ifndef ERROR_MUI_FILE_NOT_LOADED
+# define ERROR_MUI_FILE_NOT_LOADED 15105
+#endif
+
typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
(HANDLE CompletionPort,
LPOVERLAPPED_ENTRY lpCompletionPortEntries,
@@ -4626,6 +4705,7 @@ extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
extern sNtQueryInformationFile pNtQueryInformationFile;
extern sNtSetInformationFile pNtSetInformationFile;
extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
+extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
extern sNtQuerySystemInformation pNtQuerySystemInformation;
diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c
index 3711ee9cb6..d2e667e9f7 100644
--- a/deps/uv/src/win/winsock.c
+++ b/deps/uv/src/win/winsock.c
@@ -474,8 +474,8 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
}
-int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
- OVERLAPPED* overlapped) {
+int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
+ AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) {
IO_STATUS_BLOCK iosb;
IO_STATUS_BLOCK* iosb_ptr;
HANDLE event = NULL;
@@ -513,10 +513,10 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info,
apc_context,
iosb_ptr,
IOCTL_AFD_POLL,
- info,
- sizeof *info,
- info,
- sizeof *info);
+ info_in,
+ sizeof *info_in,
+ info_out,
+ sizeof *info_out);
if (overlapped == NULL) {
/* If this is a blocking operation, wait for the event to become */