aboutsummaryrefslogtreecommitdiff
path: root/deps/uv/src
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uv/src')
-rw-r--r--deps/uv/src/threadpool.c35
-rw-r--r--deps/uv/src/unix/aix.c7
-rw-r--r--deps/uv/src/unix/async.c121
-rw-r--r--deps/uv/src/unix/bsd-ifaddrs.c139
-rw-r--r--deps/uv/src/unix/core.c96
-rw-r--r--deps/uv/src/unix/cygwin.c54
-rw-r--r--deps/uv/src/unix/darwin.c104
-rw-r--r--deps/uv/src/unix/freebsd.c114
-rw-r--r--deps/uv/src/unix/fsevents.c3
-rw-r--r--deps/uv/src/unix/internal.h25
-rw-r--r--deps/uv/src/unix/kqueue.c36
-rw-r--r--deps/uv/src/unix/linux-core.c102
-rw-r--r--deps/uv/src/unix/linux-inotify.c67
-rw-r--r--deps/uv/src/unix/loop.c38
-rw-r--r--deps/uv/src/unix/netbsd.c108
-rw-r--r--deps/uv/src/unix/no-fsevents.c42
-rw-r--r--deps/uv/src/unix/no-proctitle.c42
-rw-r--r--deps/uv/src/unix/openbsd.c114
-rw-r--r--deps/uv/src/unix/os390-syscalls.c2
-rw-r--r--deps/uv/src/unix/os390.c28
-rw-r--r--deps/uv/src/unix/pipe.c16
-rw-r--r--deps/uv/src/unix/posix-hrtime.c35
-rw-r--r--deps/uv/src/unix/posix-poll.c324
-rw-r--r--deps/uv/src/unix/procfs-exepath.c45
-rw-r--r--deps/uv/src/unix/signal.c100
-rw-r--r--deps/uv/src/unix/stream.c24
-rw-r--r--deps/uv/src/unix/sunos.c57
-rw-r--r--deps/uv/src/unix/sysinfo-loadavg.c36
-rw-r--r--deps/uv/src/unix/sysinfo-memory.c42
-rw-r--r--deps/uv/src/unix/udp.c33
-rw-r--r--deps/uv/src/uv-common.h35
-rw-r--r--deps/uv/src/win/async.c3
-rw-r--r--deps/uv/src/win/atomicops-inl.h3
-rw-r--r--deps/uv/src/win/core.c21
-rw-r--r--deps/uv/src/win/detect-wakeup.c6
-rw-r--r--deps/uv/src/win/fs-event.c36
-rw-r--r--deps/uv/src/win/fs.c10
-rw-r--r--deps/uv/src/win/getaddrinfo.c4
-rw-r--r--deps/uv/src/win/getnameinfo.c3
-rw-r--r--deps/uv/src/win/handle.c5
-rw-r--r--deps/uv/src/win/internal.h23
-rw-r--r--deps/uv/src/win/pipe.c17
-rw-r--r--deps/uv/src/win/poll.c10
-rw-r--r--deps/uv/src/win/process.c3
-rw-r--r--deps/uv/src/win/req-inl.h9
-rw-r--r--deps/uv/src/win/signal.c45
-rw-r--r--deps/uv/src/win/stream-inl.h3
-rw-r--r--deps/uv/src/win/stream.c3
-rw-r--r--deps/uv/src/win/tcp.c13
-rw-r--r--deps/uv/src/win/tty.c5
-rw-r--r--deps/uv/src/win/udp.c6
-rw-r--r--deps/uv/src/win/util.c195
-rw-r--r--deps/uv/src/win/winapi.c2
-rw-r--r--deps/uv/src/win/winsock.c2
54 files changed, 1647 insertions, 804 deletions
diff --git a/deps/uv/src/threadpool.c b/deps/uv/src/threadpool.c
index 2c5152b420..108934112c 100644
--- a/deps/uv/src/threadpool.c
+++ b/deps/uv/src/threadpool.c
@@ -23,18 +23,6 @@
#if !defined(_WIN32)
# include "unix/internal.h"
-#else
-# include "win/req-inl.h"
-/* TODO(saghul): unify internal req functions */
-static void uv__req_init(uv_loop_t* loop,
- uv_req_t* req,
- uv_req_type type) {
- uv_req_init(loop, req);
- req->type = type;
- uv__req_register(loop, req);
-}
-# define uv__req_init(loop, req, type) \
- uv__req_init((loop), (uv_req_t*)(req), (type))
#endif
#include <stdlib.h>
@@ -139,7 +127,7 @@ UV_DESTRUCTOR(static void cleanup(void)) {
#endif
-static void init_once(void) {
+static void init_threads(void) {
unsigned int i;
const char* val;
@@ -177,6 +165,27 @@ static void init_once(void) {
}
+#ifndef _WIN32
+static void reset_once(void) {
+ uv_once_t child_once = UV_ONCE_INIT;
+ memcpy(&once, &child_once, sizeof(child_once));
+}
+#endif
+
+
+static void init_once(void) {
+#ifndef _WIN32
+ /* Re-initialize the threadpool after fork.
+ * Note that this discards the global mutex and condition as well
+ * as the work queue.
+ */
+ if (pthread_atfork(NULL, NULL, &reset_once))
+ abort();
+#endif
+ init_threads();
+}
+
+
void uv__work_submit(uv_loop_t* loop,
struct uv__work* w,
void (*work)(struct uv__work* w),
diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c
index 1d2cd4a80e..388c9cca97 100644
--- a/deps/uv/src/unix/aix.c
+++ b/deps/uv/src/unix/aix.c
@@ -96,6 +96,13 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
+int uv__io_fork(uv_loop_t* loop) {
+ uv__platform_loop_delete(loop);
+
+ return uv__platform_loop_init(loop);
+}
+
+
int uv__io_check_fd(uv_loop_t* loop, int fd) {
struct poll_ctl pc;
diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c
index 393cdebd4e..45c088ea1b 100644
--- a/deps/uv/src/unix/async.c
+++ b/deps/uv/src/unix/async.c
@@ -33,16 +33,15 @@
#include <string.h>
#include <unistd.h>
-static void uv__async_event(uv_loop_t* loop,
- struct uv__async* w,
- unsigned int nevents);
+static void uv__async_send(uv_loop_t* loop);
+static int uv__async_start(uv_loop_t* loop);
static int uv__async_eventfd(void);
int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
int err;
- err = uv__async_start(loop, &loop->async_watcher, uv__async_event);
+ err = uv__async_start(loop);
if (err)
return err;
@@ -63,7 +62,7 @@ int uv_async_send(uv_async_t* handle) {
return 0;
if (cmpxchgi(&handle->pending, 0, 1) == 0)
- uv__async_send(&handle->loop->async_watcher);
+ uv__async_send(handle->loop);
return 0;
}
@@ -75,44 +74,18 @@ void uv__async_close(uv_async_t* handle) {
}
-static void uv__async_event(uv_loop_t* loop,
- struct uv__async* w,
- unsigned int nevents) {
+static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+ char buf[1024];
+ ssize_t r;
QUEUE queue;
QUEUE* q;
uv_async_t* h;
- QUEUE_MOVE(&loop->async_handles, &queue);
- while (!QUEUE_EMPTY(&queue)) {
- q = QUEUE_HEAD(&queue);
- h = QUEUE_DATA(q, uv_async_t, queue);
-
- QUEUE_REMOVE(q);
- QUEUE_INSERT_TAIL(&loop->async_handles, q);
-
- if (cmpxchgi(&h->pending, 1, 0) == 0)
- continue;
-
- if (h->async_cb == NULL)
- continue;
- h->async_cb(h);
- }
-}
-
+ assert(w == &loop->async_io_watcher);
-static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
- struct uv__async* wa;
- char buf[1024];
- unsigned n;
- ssize_t r;
-
- n = 0;
for (;;) {
r = read(w->fd, buf, sizeof(buf));
- if (r > 0)
- n += r;
-
if (r == sizeof(buf))
continue;
@@ -128,23 +101,26 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
abort();
}
- wa = container_of(w, struct uv__async, io_watcher);
+ QUEUE_MOVE(&loop->async_handles, &queue);
+ while (!QUEUE_EMPTY(&queue)) {
+ q = QUEUE_HEAD(&queue);
+ h = QUEUE_DATA(q, uv_async_t, queue);
+
+ QUEUE_REMOVE(q);
+ QUEUE_INSERT_TAIL(&loop->async_handles, q);
-#if defined(__linux__)
- if (wa->wfd == -1) {
- uint64_t val;
- assert(n == sizeof(val));
- memcpy(&val, buf, sizeof(val)); /* Avoid alignment issues. */
- wa->cb(loop, wa, val);
- return;
- }
-#endif
+ if (cmpxchgi(&h->pending, 1, 0) == 0)
+ continue;
+
+ if (h->async_cb == NULL)
+ continue;
- wa->cb(loop, wa, n);
+ h->async_cb(h);
+ }
}
-void uv__async_send(struct uv__async* wa) {
+static void uv__async_send(uv_loop_t* loop) {
const void* buf;
ssize_t len;
int fd;
@@ -152,14 +128,14 @@ void uv__async_send(struct uv__async* wa) {
buf = "";
len = 1;
- fd = wa->wfd;
+ fd = loop->async_wfd;
#if defined(__linux__)
if (fd == -1) {
static const uint64_t val = 1;
buf = &val;
len = sizeof(val);
- fd = wa->io_watcher.fd; /* eventfd */
+ fd = loop->async_io_watcher.fd; /* eventfd */
}
#endif
@@ -178,17 +154,11 @@ void uv__async_send(struct uv__async* wa) {
}
-void uv__async_init(struct uv__async* wa) {
- wa->io_watcher.fd = -1;
- wa->wfd = -1;
-}
-
-
-int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) {
+static int uv__async_start(uv_loop_t* loop) {
int pipefd[2];
int err;
- if (wa->io_watcher.fd != -1)
+ if (loop->async_io_watcher.fd != -1)
return 0;
err = uv__async_eventfd();
@@ -222,32 +192,41 @@ int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) {
if (err < 0)
return err;
- uv__io_init(&wa->io_watcher, uv__async_io, pipefd[0]);
- uv__io_start(loop, &wa->io_watcher, POLLIN);
- wa->wfd = pipefd[1];
- wa->cb = cb;
+ uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]);
+ uv__io_start(loop, &loop->async_io_watcher, POLLIN);
+ loop->async_wfd = pipefd[1];
return 0;
}
-void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) {
- if (wa->io_watcher.fd == -1)
+int uv__async_fork(uv_loop_t* loop) {
+ if (loop->async_io_watcher.fd == -1) /* never started */
+ return 0;
+
+ uv__async_stop(loop);
+
+ return uv__async_start(loop);
+}
+
+
+void uv__async_stop(uv_loop_t* loop) {
+ if (loop->async_io_watcher.fd == -1)
return;
- if (wa->wfd != -1) {
- if (wa->wfd != wa->io_watcher.fd)
- uv__close(wa->wfd);
- wa->wfd = -1;
+ if (loop->async_wfd != -1) {
+ if (loop->async_wfd != loop->async_io_watcher.fd)
+ uv__close(loop->async_wfd);
+ loop->async_wfd = -1;
}
- uv__io_stop(loop, &wa->io_watcher, POLLIN);
- uv__close(wa->io_watcher.fd);
- wa->io_watcher.fd = -1;
+ uv__io_stop(loop, &loop->async_io_watcher, POLLIN);
+ uv__close(loop->async_io_watcher.fd);
+ loop->async_io_watcher.fd = -1;
}
-static int uv__async_eventfd() {
+static int uv__async_eventfd(void) {
#if defined(__linux__)
static int no_eventfd2;
static int no_eventfd;
diff --git a/deps/uv/src/unix/bsd-ifaddrs.c b/deps/uv/src/unix/bsd-ifaddrs.c
new file mode 100644
index 0000000000..414789451a
--- /dev/null
+++ b/deps/uv/src/unix/bsd-ifaddrs.c
@@ -0,0 +1,139 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+#include <ifaddrs.h>
+#include <net/if.h>
+#if !defined(__CYGWIN__) && !defined(__MSYS__)
+#include <net/if_dl.h>
+#endif
+
+static int uv__ifaddr_exclude(struct ifaddrs *ent) {
+ if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
+ return 1;
+ if (ent->ifa_addr == NULL)
+ return 1;
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
+ /*
+ * On BSD getifaddrs returns information related to the raw underlying
+ * devices. We're not interested in this information.
+ */
+ if (ent->ifa_addr->sa_family == AF_LINK)
+ return 1;
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+ if (ent->ifa_addr->sa_family != PF_INET)
+ return 1;
+#endif
+ return 0;
+}
+
+int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
+ struct ifaddrs* addrs;
+ struct ifaddrs* ent;
+ uv_interface_address_t* address;
+ int i;
+
+ if (getifaddrs(&addrs) != 0)
+ return -errno;
+
+ *count = 0;
+
+ /* Count the number of interfaces */
+ for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
+ if (uv__ifaddr_exclude(ent))
+ continue;
+ (*count)++;
+ }
+
+ *addresses = uv__malloc(*count * sizeof(**addresses));
+
+ if (*addresses == NULL) {
+ freeifaddrs(addrs);
+ return -ENOMEM;
+ }
+
+ address = *addresses;
+
+ for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
+ if (uv__ifaddr_exclude(ent))
+ continue;
+
+ address->name = uv__strdup(ent->ifa_name);
+
+ if (ent->ifa_addr->sa_family == AF_INET6) {
+ address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
+ } else {
+ address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
+ }
+
+ if (ent->ifa_netmask->sa_family == AF_INET6) {
+ address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
+ } else {
+ address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
+ }
+
+ address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
+
+ address++;
+ }
+
+ /* Fill in physical addresses for each interface */
+ for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
+ if (uv__ifaddr_exclude(ent))
+ continue;
+
+ address = *addresses;
+
+ for (i = 0; i < *count; i++) {
+ if (strcmp(address->name, ent->ifa_name) == 0) {
+#if defined(__CYGWIN__) || defined(__MSYS__)
+ memset(address->phys_addr, 0, sizeof(address->phys_addr));
+#else
+ struct sockaddr_dl* sa_addr;
+ sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
+ memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
+#endif
+ }
+ address++;
+ }
+ }
+
+ freeifaddrs(addrs);
+
+ return 0;
+}
+
+
+void uv_free_interface_addresses(uv_interface_address_t* addresses,
+ int count) {
+ int i;
+
+ for (i = 0; i < count; i++) {
+ uv__free(addresses[i].name);
+ }
+
+ uv__free(addresses);
+}
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 1ec549cccb..8276c60413 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <assert.h>
#include <unistd.h>
+#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -42,6 +43,7 @@
#include <pwd.h>
#ifdef __sun
+# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
# include <sys/filio.h>
# include <sys/types.h>
# include <sys/wait.h>
@@ -80,6 +82,11 @@
#include <sys/ioctl.h>
#endif
+/* Fallback for the maximum hostname length */
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 256
+#endif
+
static int uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
@@ -538,6 +545,7 @@ int uv__nonblock_ioctl(int fd, int set) {
}
+#if !defined(__CYGWIN__) && !defined(__MSYS__)
int uv__cloexec_ioctl(int fd, int set) {
int r;
@@ -550,6 +558,7 @@ int uv__cloexec_ioctl(int fd, int set) {
return 0;
}
+#endif
int uv__nonblock_fcntl(int fd, int set) {
@@ -839,13 +848,8 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
* every tick of the event loop but the other backends allow us to
* short-circuit here if the event mask is unchanged.
*/
- if (w->events == w->pevents) {
- if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) {
- QUEUE_REMOVE(&w->watcher_queue);
- QUEUE_INIT(&w->watcher_queue);
- }
+ if (w->events == w->pevents)
return;
- }
#endif
if (QUEUE_EMPTY(&w->watcher_queue))
@@ -1245,3 +1249,83 @@ int uv_translate_sys_error(int sys_errno) {
/* If < 0 then it's already a libuv error. */
return sys_errno <= 0 ? sys_errno : -sys_errno;
}
+
+
+int uv_os_getenv(const char* name, char* buffer, size_t* size) {
+ char* var;
+ size_t len;
+
+ if (name == NULL || buffer == NULL || size == NULL || *size == 0)
+ return -EINVAL;
+
+ var = getenv(name);
+
+ if (var == NULL)
+ return -ENOENT;
+
+ len = strlen(var);
+
+ if (len >= *size) {
+ *size = len + 1;
+ return -ENOBUFS;
+ }
+
+ memcpy(buffer, var, len + 1);
+ *size = len;
+
+ return 0;
+}
+
+
+int uv_os_setenv(const char* name, const char* value) {
+ if (name == NULL || value == NULL)
+ return -EINVAL;
+
+ if (setenv(name, value, 1) != 0)
+ return -errno;
+
+ return 0;
+}
+
+
+int uv_os_unsetenv(const char* name) {
+ if (unsetenv(name) != 0)
+ return -errno;
+
+ return 0;
+}
+
+
+int uv_os_gethostname(char* buffer, size_t* size) {
+ /*
+ On some platforms, if the input buffer is not large enough, gethostname()
+ succeeds, but truncates the result. libuv can detect this and return ENOBUFS
+ instead by creating a large enough buffer and comparing the hostname length
+ to the size input.
+ */
+ char buf[MAXHOSTNAMELEN + 1];
+ size_t len;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return -EINVAL;
+
+ if (gethostname(buf, sizeof(buf)) != 0)
+ return -errno;
+
+ buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
+ len = strlen(buf);
+
+ if (len >= *size) {
+ *size = len + 1;
+ return -ENOBUFS;
+ }
+
+ memcpy(buffer, buf, len + 1);
+ *size = len;
+ return 0;
+}
+
+
+uv_os_fd_t uv_get_osfhandle(int fd) {
+ return fd;
+}
diff --git a/deps/uv/src/unix/cygwin.c b/deps/uv/src/unix/cygwin.c
new file mode 100644
index 0000000000..5a887dd4c2
--- /dev/null
+++ b/deps/uv/src/unix/cygwin.c
@@ -0,0 +1,54 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <sys/sysinfo.h>
+#include <unistd.h>
+
+int uv_uptime(double* uptime) {
+ struct sysinfo info;
+
+ if (sysinfo(&info) < 0)
+ return -errno;
+
+ *uptime = info.uptime;
+ return 0;
+}
+
+int uv_resident_set_memory(size_t* rss) {
+ /* FIXME: read /proc/meminfo? */
+ *rss = 0;
+ return UV_ENOSYS;
+}
+
+int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+ /* FIXME: read /proc/stat? */
+ *cpu_infos = NULL;
+ *count = 0;
+ return UV_ENOSYS;
+}
+
+void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
+ (void)cpu_infos;
+ (void)count;
+}
diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c
index cf95da2169..df6dd1c61b 100644
--- a/deps/uv/src/unix/darwin.c
+++ b/deps/uv/src/unix/darwin.c
@@ -25,10 +25,6 @@
#include <stdint.h>
#include <errno.h>
-#include <ifaddrs.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
@@ -233,103 +229,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
uv__free(cpu_infos);
}
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
- struct ifaddrs *addrs, *ent;
- uv_interface_address_t* address;
- int i;
- struct sockaddr_dl *sa_addr;
-
- if (getifaddrs(&addrs))
- return -errno;
-
- *count = 0;
-
- /* Count the number of interfaces */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family == AF_LINK)) {
- continue;
- }
-
- (*count)++;
- }
-
- *addresses = uv__malloc(*count * sizeof(**addresses));
- if (!(*addresses)) {
- freeifaddrs(addrs);
- return -ENOMEM;
- }
-
- address = *addresses;
-
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
- continue;
-
- if (ent->ifa_addr == NULL)
- continue;
-
- /*
- * On Mac OS X getifaddrs returns information related to Mac Addresses for
- * various devices, such as firewire, etc. These are not relevant here.
- */
- if (ent->ifa_addr->sa_family == AF_LINK)
- continue;
-
- address->name = uv__strdup(ent->ifa_name);
-
- if (ent->ifa_addr->sa_family == AF_INET6) {
- address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
- } else {
- address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
- }
-
- if (ent->ifa_netmask->sa_family == AF_INET6) {
- address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
- } else {
- address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
- }
-
- address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
- address++;
- }
-
- /* Fill in physical addresses for each interface */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family != AF_LINK)) {
- continue;
- }
-
- address = *addresses;
-
- for (i = 0; i < (*count); i++) {
- if (strcmp(address->name, ent->ifa_name) == 0) {
- sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
- memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
- }
- address++;
- }
- }
-
- freeifaddrs(addrs);
-
- return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
- int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(addresses[i].name);
- }
-
- uv__free(addresses);
-}
diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c
index cba44a3e0b..e52ae99dbe 100644
--- a/deps/uv/src/unix/freebsd.c
+++ b/deps/uv/src/unix/freebsd.c
@@ -25,10 +25,6 @@
#include <string.h>
#include <errno.h>
-#include <ifaddrs.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-
#include <kvm.h>
#include <paths.h>
#include <sys/user.h>
@@ -41,9 +37,6 @@
#include <unistd.h> /* sysconf */
#include <fcntl.h>
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
#ifndef CPUSTATES
# define CPUSTATES 5U
#endif
@@ -67,13 +60,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
-uint64_t uv__hrtime(uv_clocktype_t type) {
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
-}
-
-
#ifdef __DragonFly__
int uv_exepath(char* buffer, size_t* size) {
char abspath[PATH_MAX * 2 + 1];
@@ -358,103 +344,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
uv__free(cpu_infos);
}
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
- struct ifaddrs *addrs, *ent;
- uv_interface_address_t* address;
- int i;
- struct sockaddr_dl *sa_addr;
-
- if (getifaddrs(&addrs))
- return -errno;
-
- *count = 0;
-
- /* Count the number of interfaces */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family == AF_LINK)) {
- continue;
- }
-
- (*count)++;
- }
-
- *addresses = uv__malloc(*count * sizeof(**addresses));
- if (!(*addresses)) {
- freeifaddrs(addrs);
- return -ENOMEM;
- }
-
- address = *addresses;
-
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
- continue;
-
- if (ent->ifa_addr == NULL)
- continue;
-
- /*
- * On FreeBSD getifaddrs returns information related to the raw underlying
- * devices. We're not interested in this information yet.
- */
- if (ent->ifa_addr->sa_family == AF_LINK)
- continue;
-
- address->name = uv__strdup(ent->ifa_name);
-
- if (ent->ifa_addr->sa_family == AF_INET6) {
- address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
- } else {
- address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
- }
-
- if (ent->ifa_netmask->sa_family == AF_INET6) {
- address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
- } else {
- address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
- }
-
- address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
- address++;
- }
-
- /* Fill in physical addresses for each interface */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family != AF_LINK)) {
- continue;
- }
-
- address = *addresses;
-
- for (i = 0; i < (*count); i++) {
- if (strcmp(address->name, ent->ifa_name) == 0) {
- sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
- memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
- }
- address++;
- }
- }
-
- freeifaddrs(addrs);
-
- return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
- int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(addresses[i].name);
- }
-
- uv__free(addresses);
-}
diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c
index d331a13172..643e233cfe 100644
--- a/deps/uv/src/unix/fsevents.c
+++ b/deps/uv/src/unix/fsevents.c
@@ -378,9 +378,6 @@ static void uv__fsevents_destroy_stream(uv_loop_t* loop) {
if (state->fsevent_stream == NULL)
return;
- /* Flush all accumulated events */
- pFSEventStreamFlushSync(state->fsevent_stream);
-
/* Stop emitting events */
pFSEventStreamStop(state->fsevent_stream);
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 1188e8fe70..2e3afa6c85 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -162,7 +162,8 @@ struct uv__stream_queued_fds_s {
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
- defined(__linux__)
+ defined(__linux__) || \
+ defined(__OpenBSD__)
#define uv__cloexec uv__cloexec_ioctl
#define uv__nonblock uv__nonblock_ioctl
#else
@@ -191,12 +192,12 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w);
int uv__io_active(const uv__io_t* w, unsigned int events);
int uv__io_check_fd(uv_loop_t* loop, int fd);
void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
+int uv__io_fork(uv_loop_t* loop);
/* async */
-void uv__async_send(struct uv__async* wa);
-void uv__async_init(struct uv__async* wa);
-int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb);
-void uv__async_stop(uv_loop_t* loop, struct uv__async* wa);
+void uv__async_stop(uv_loop_t* loop);
+int uv__async_fork(uv_loop_t* loop);
+
/* loop */
void uv__run_idle(uv_loop_t* loop);
@@ -232,6 +233,7 @@ int uv__next_timeout(const uv_loop_t* loop);
void uv__signal_close(uv_signal_t* handle);
void uv__signal_global_once_init(void);
void uv__signal_loop_cleanup(uv_loop_t* loop);
+int uv__signal_loop_fork(uv_loop_t* loop);
/* platform specific */
uint64_t uv__hrtime(uv_clocktype_t type);
@@ -301,15 +303,6 @@ static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000;
#endif /* defined(__APPLE__) */
-UV_UNUSED(static void uv__req_init(uv_loop_t* loop,
- uv_req_t* req,
- uv_req_type type)) {
- req->type = type;
- uv__req_register(loop, req);
-}
-#define uv__req_init(loop, req, type) \
- uv__req_init((loop), (uv_req_t*)(req), (type))
-
UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {
/* Use a fast time source if available. We only need millisecond precision.
*/
@@ -326,4 +319,8 @@ UV_UNUSED(static char* uv__basename_r(const char* path)) {
return s + 1;
}
+#if defined(__linux__)
+int uv__inotify_fork(uv_loop_t* loop, void* old_watchers);
+#endif
+
#endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index fffd4626f1..6bc60bbe46 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -48,6 +48,37 @@ int uv__kqueue_init(uv_loop_t* loop) {
}
+static int uv__has_forked_with_cfrunloop;
+
+int uv__io_fork(uv_loop_t* loop) {
+ int err;
+ uv__close(loop->backend_fd);
+ loop->backend_fd = -1;
+ err = uv__kqueue_init(loop);
+ if (err)
+ return err;
+
+#if defined(__APPLE__)
+ if (loop->cf_state != NULL) {
+ /* We cannot start another CFRunloop and/or thread in the child
+ process; CF aborts if you try or if you try to touch the thread
+ at all to kill it. So the best we can do is ignore it from now
+ on. This means we can't watch directories in the same way
+ anymore (like other BSDs). It also means we cannot properly
+ clean up the allocated resources; calling
+ uv__fsevents_loop_delete from uv_loop_close will crash the
+ process. So we sidestep the issue by pretending like we never
+ started it in the first place.
+ */
+ uv__has_forked_with_cfrunloop = 1;
+ uv__free(loop->cf_state);
+ loop->cf_state = NULL;
+ }
+#endif
+ return err;
+}
+
+
int uv__io_check_fd(uv_loop_t* loop, int fd) {
struct kevent ev;
int rc;
@@ -404,6 +435,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
handle->cb = cb;
#if defined(__APPLE__)
+ if (uv__has_forked_with_cfrunloop)
+ goto fallback;
+
/* Nullify field to perform checks later */
handle->cf_cb = NULL;
handle->realpath = NULL;
@@ -438,7 +472,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__handle_stop(handle);
#if defined(__APPLE__)
- if (uv__fsevents_close(handle))
+ if (uv__has_forked_with_cfrunloop || uv__fsevents_close(handle))
#endif /* defined(__APPLE__) */
{
uv__io_close(handle->loop, &handle->event_watcher);
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index 58dd813ddf..2866e93854 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -107,6 +107,24 @@ int uv__platform_loop_init(uv_loop_t* loop) {
}
+int uv__io_fork(uv_loop_t* loop) {
+ int err;
+ void* old_watchers;
+
+ old_watchers = loop->inotify_watchers;
+
+ uv__close(loop->backend_fd);
+ loop->backend_fd = -1;
+ uv__platform_loop_delete(loop);
+
+ err = uv__platform_loop_init(loop);
+ if (err)
+ return err;
+
+ return uv__inotify_fork(loop, old_watchers);
+}
+
+
void uv__platform_loop_delete(uv_loop_t* loop) {
if (loop->inotify_fd == -1) return;
uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN);
@@ -454,55 +472,6 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
}
-void uv_loadavg(double avg[3]) {
- struct sysinfo info;
-
- if (sysinfo(&info) < 0) return;
-
- avg[0] = (double) info.loads[0] / 65536.0;
- avg[1] = (double) info.loads[1] / 65536.0;
- avg[2] = (double) info.loads[2] / 65536.0;
-}
-
-
-int uv_exepath(char* buffer, size_t* size) {
- ssize_t n;
-
- if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
-
- n = *size - 1;
- if (n > 0)
- n = readlink("/proc/self/exe", buffer, n);
-
- if (n == -1)
- return -errno;
-
- buffer[n] = '\0';
- *size = n;
-
- return 0;
-}
-
-
-uint64_t uv_get_free_memory(void) {
- struct sysinfo info;
-
- if (sysinfo(&info) == 0)
- return (uint64_t) info.freeram * info.mem_unit;
- return 0;
-}
-
-
-uint64_t uv_get_total_memory(void) {
- struct sysinfo info;
-
- if (sysinfo(&info) == 0)
- return (uint64_t) info.totalram * info.mem_unit;
- return 0;
-}
-
-
int uv_resident_set_memory(size_t* rss) {
char buf[1024];
const char* s;
@@ -868,6 +837,19 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
uv__free(cpu_infos);
}
+static int uv__ifaddr_exclude(struct ifaddrs *ent) {
+ if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
+ return 1;
+ if (ent->ifa_addr == NULL)
+ return 1;
+ /*
+ * On Linux getifaddrs returns information related to the raw underlying
+ * devices. We're not interested in this information yet.
+ */
+ if (ent->ifa_addr->sa_family == PF_PACKET)
+ return 1;
+ return 0;
+}
int uv_interface_addresses(uv_interface_address_t** addresses,
int* count) {
@@ -887,11 +869,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
/* Count the number of interfaces */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family == PF_PACKET)) {
+ if (uv__ifaddr_exclude(ent))
continue;
- }
(*count)++;
}
@@ -908,17 +887,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
- continue;
-
- if (ent->ifa_addr == NULL)
- continue;
-
- /*
- * On Linux getifaddrs returns information related to the raw underlying
- * devices. We're not interested in this information yet.
- */
- if (ent->ifa_addr->sa_family == PF_PACKET)
+ if (uv__ifaddr_exclude(ent))
continue;
address->name = uv__strdup(ent->ifa_name);
@@ -942,11 +911,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
/* Fill in physical addresses for each interface */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family != PF_PACKET)) {
+ if (uv__ifaddr_exclude(ent))
continue;
- }
address = *addresses;
diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c
index 4708c051d3..5934c5d8cb 100644
--- a/deps/uv/src/unix/linux-inotify.c
+++ b/deps/uv/src/unix/linux-inotify.c
@@ -61,6 +61,8 @@ static void uv__inotify_read(uv_loop_t* loop,
uv__io_t* w,
unsigned int revents);
+static void maybe_free_watcher_list(struct watcher_list* w,
+ uv_loop_t* loop);
static int new_inotify_fd(void) {
int err;
@@ -108,6 +110,71 @@ static int init_inotify(uv_loop_t* loop) {
}
+int uv__inotify_fork(uv_loop_t* loop, void* old_watchers) {
+ /* Open the inotify_fd, and re-arm all the inotify watchers. */
+ int err;
+ struct watcher_list* tmp_watcher_list_iter;
+ struct watcher_list* watcher_list;
+ struct watcher_list tmp_watcher_list;
+ QUEUE queue;
+ QUEUE* q;
+ uv_fs_event_t* handle;
+ char* tmp_path;
+
+ if (old_watchers != NULL) {
+ /* We must restore the old watcher list to be able to close items
+ * out of it.
+ */
+ loop->inotify_watchers = old_watchers;
+
+ QUEUE_INIT(&tmp_watcher_list.watchers);
+ /* Note that the queue we use is shared with the start and stop()
+ * functions, making QUEUE_FOREACH unsafe to use. So we use the
+ * QUEUE_MOVE trick to safely iterate. Also don't free the watcher
+ * list until we're done iterating. c.f. uv__inotify_read.
+ */
+ RB_FOREACH_SAFE(watcher_list, watcher_root,
+ CAST(&old_watchers), tmp_watcher_list_iter) {
+ watcher_list->iterating = 1;
+ QUEUE_MOVE(&watcher_list->watchers, &queue);
+ while (!QUEUE_EMPTY(&queue)) {
+ q = QUEUE_HEAD(&queue);
+ handle = QUEUE_DATA(q, uv_fs_event_t, watchers);
+ /* It's critical to keep a copy of path here, because it
+ * will be set to NULL by stop() and then deallocated by
+ * maybe_free_watcher_list
+ */
+ tmp_path = uv__strdup(handle->path);
+ assert(tmp_path != NULL);
+ QUEUE_REMOVE(q);
+ QUEUE_INSERT_TAIL(&watcher_list->watchers, q);
+ uv_fs_event_stop(handle);
+
+ QUEUE_INSERT_TAIL(&tmp_watcher_list.watchers, &handle->watchers);
+ handle->path = tmp_path;
+ }
+ watcher_list->iterating = 0;
+ maybe_free_watcher_list(watcher_list, loop);
+ }
+
+ QUEUE_MOVE(&tmp_watcher_list.watchers, &queue);
+ while (!QUEUE_EMPTY(&queue)) {
+ q = QUEUE_HEAD(&queue);
+ QUEUE_REMOVE(q);
+ handle = QUEUE_DATA(q, uv_fs_event_t, watchers);
+ tmp_path = handle->path;
+ handle->path = NULL;
+ err = uv_fs_event_start(handle, handle->cb, tmp_path, 0);
+ uv__free(tmp_path);
+ if (err)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+
static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) {
struct watcher_list w;
w.wd = wd;
diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c
index bd63c2f9d1..bcd49242ce 100644
--- a/deps/uv/src/unix/loop.c
+++ b/deps/uv/src/unix/loop.c
@@ -54,7 +54,8 @@ int uv_loop_init(uv_loop_t* loop) {
loop->closing_handles = NULL;
uv__update_time(loop);
- uv__async_init(&loop->async_watcher);
+ loop->async_io_watcher.fd = -1;
+ loop->async_wfd = -1;
loop->signal_pipefd[0] = -1;
loop->signal_pipefd[1] = -1;
loop->backend_fd = -1;
@@ -108,10 +109,43 @@ fail_signal_init:
}
+int uv_loop_fork(uv_loop_t* loop) {
+ int err;
+ unsigned int i;
+ uv__io_t* w;
+
+ err = uv__io_fork(loop);
+ if (err)
+ return err;
+
+ err = uv__async_fork(loop);
+ if (err)
+ return err;
+
+ err = uv__signal_loop_fork(loop);
+ if (err)
+ return err;
+
+ /* Rearm all the watchers that aren't re-queued by the above. */
+ for (i = 0; i < loop->nwatchers; i++) {
+ w = loop->watchers[i];
+ if (w == NULL)
+ continue;
+
+ if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) {
+ w->events = 0; /* Force re-registration in uv__io_poll. */
+ QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
+ }
+ }
+
+ return 0;
+}
+
+
void uv__loop_close(uv_loop_t* loop) {
uv__signal_loop_cleanup(loop);
uv__platform_loop_delete(loop);
- uv__async_stop(loop, &loop->async_watcher);
+ uv__async_stop(loop);
if (loop->emfile_fd != -1) {
uv__close(loop->emfile_fd);
diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c
index 4a9e6cbc17..9b5546b7e6 100644
--- a/deps/uv/src/unix/netbsd.c
+++ b/deps/uv/src/unix/netbsd.c
@@ -27,14 +27,11 @@
#include <kvm.h>
#include <paths.h>
-#include <ifaddrs.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <fcntl.h>
-#include <net/if.h>
-#include <net/if_dl.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/sysctl.h>
@@ -43,9 +40,6 @@
#include <unistd.h>
#include <time.h>
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
static char *process_title;
@@ -58,13 +52,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
-uint64_t uv__hrtime(uv_clocktype_t type) {
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
-}
-
-
void uv_loadavg(double avg[3]) {
struct loadavg info;
size_t size = sizeof(info);
@@ -283,98 +270,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
uv__free(cpu_infos);
}
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
- struct ifaddrs *addrs, *ent;
- uv_interface_address_t* address;
- int i;
- struct sockaddr_dl *sa_addr;
-
- if (getifaddrs(&addrs))
- return -errno;
-
- *count = 0;
-
- /* Count the number of interfaces */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family != PF_INET)) {
- continue;
- }
- (*count)++;
- }
-
- *addresses = uv__malloc(*count * sizeof(**addresses));
-
- if (!(*addresses)) {
- freeifaddrs(addrs);
- return -ENOMEM;
- }
-
- address = *addresses;
-
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
- continue;
-
- if (ent->ifa_addr == NULL)
- continue;
-
- if (ent->ifa_addr->sa_family != PF_INET)
- continue;
-
- address->name = uv__strdup(ent->ifa_name);
-
- if (ent->ifa_addr->sa_family == AF_INET6) {
- address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
- } else {
- address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
- }
-
- if (ent->ifa_netmask->sa_family == AF_INET6) {
- address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
- } else {
- address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
- }
-
- address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
- address++;
- }
-
- /* Fill in physical addresses for each interface */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family != AF_LINK)) {
- continue;
- }
-
- address = *addresses;
-
- for (i = 0; i < (*count); i++) {
- if (strcmp(address->name, ent->ifa_name) == 0) {
- sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
- memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
- }
- address++;
- }
- }
-
- freeifaddrs(addrs);
-
- return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(addresses[i].name);
- }
-
- uv__free(addresses);
-}
diff --git a/deps/uv/src/unix/no-fsevents.c b/deps/uv/src/unix/no-fsevents.c
new file mode 100644
index 0000000000..38fb6ab0bb
--- /dev/null
+++ b/deps/uv/src/unix/no-fsevents.c
@@ -0,0 +1,42 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <errno.h>
+
+int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
+ return -ENOSYS;
+}
+
+int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
+ const char* filename, unsigned int flags) {
+ return -ENOSYS;
+}
+
+int uv_fs_event_stop(uv_fs_event_t* handle) {
+ return -ENOSYS;
+}
+
+void uv__fs_event_close(uv_fs_event_t* handle) {
+ UNREACHABLE();
+}
diff --git a/deps/uv/src/unix/no-proctitle.c b/deps/uv/src/unix/no-proctitle.c
new file mode 100644
index 0000000000..a5c19fbff5
--- /dev/null
+++ b/deps/uv/src/unix/no-proctitle.c
@@ -0,0 +1,42 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+char** uv_setup_args(int argc, char** argv) {
+ return argv;
+}
+
+int uv_set_process_title(const char* title) {
+ return 0;
+}
+
+int uv_get_process_title(char* buffer, size_t size) {
+ if (buffer == NULL || size == 0)
+ return -EINVAL;
+
+ buffer[0] = '\0';
+ return 0;
+}
diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c
index 909288cc88..56f0af15c3 100644
--- a/deps/uv/src/unix/openbsd.c
+++ b/deps/uv/src/unix/openbsd.c
@@ -28,21 +28,13 @@
#include <sys/time.h>
#include <sys/sysctl.h>
-#include <ifaddrs.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-
#include <errno.h>
#include <fcntl.h>
-#include <kvm.h>
#include <paths.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
static char *process_title;
@@ -56,13 +48,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
-uint64_t uv__hrtime(uv_clocktype_t type) {
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
-}
-
-
void uv_loadavg(double avg[3]) {
struct loadavg info;
size_t size = sizeof(info);
@@ -163,7 +148,7 @@ char** uv_setup_args(int argc, char** argv) {
int uv_set_process_title(const char* title) {
uv__free(process_title);
process_title = uv__strdup(title);
- setproctitle(title);
+ setproctitle("%s", title);
return 0;
}
@@ -297,100 +282,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
uv__free(cpu_infos);
}
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses,
- int* count) {
- struct ifaddrs *addrs, *ent;
- uv_interface_address_t* address;
- int i;
- struct sockaddr_dl *sa_addr;
-
- if (getifaddrs(&addrs) != 0)
- return -errno;
-
- *count = 0;
-
- /* Count the number of interfaces */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family != PF_INET)) {
- continue;
- }
- (*count)++;
- }
-
- *addresses = uv__malloc(*count * sizeof(**addresses));
-
- if (!(*addresses)) {
- freeifaddrs(addrs);
- return -ENOMEM;
- }
-
- address = *addresses;
-
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
- continue;
-
- if (ent->ifa_addr == NULL)
- continue;
-
- if (ent->ifa_addr->sa_family != PF_INET)
- continue;
-
- address->name = uv__strdup(ent->ifa_name);
-
- if (ent->ifa_addr->sa_family == AF_INET6) {
- address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
- } else {
- address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
- }
-
- if (ent->ifa_netmask->sa_family == AF_INET6) {
- address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
- } else {
- address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
- }
-
- address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
- address++;
- }
-
- /* Fill in physical addresses for each interface */
- for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family != AF_LINK)) {
- continue;
- }
-
- address = *addresses;
-
- for (i = 0; i < (*count); i++) {
- if (strcmp(address->name, ent->ifa_name) == 0) {
- sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
- memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
- }
- address++;
- }
- }
-
- freeifaddrs(addrs);
-
- return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
- int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(addresses[i].name);
- }
-
- uv__free(addresses);
-}
diff --git a/deps/uv/src/unix/os390-syscalls.c b/deps/uv/src/unix/os390-syscalls.c
index 2bf3b73815..7edf2358d4 100644
--- a/deps/uv/src/unix/os390-syscalls.c
+++ b/deps/uv/src/unix/os390-syscalls.c
@@ -120,7 +120,7 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
}
-static void epoll_init() {
+static void epoll_init(void) {
QUEUE_INIT(&global_epoll_queue);
if (uv_mutex_init(&global_epoll_lock))
abort();
diff --git a/deps/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c
index be325a9230..2ba5abf354 100644
--- a/deps/uv/src/unix/os390.c
+++ b/deps/uv/src/unix/os390.c
@@ -663,28 +663,6 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
return 0;
}
-
-void uv__fs_event_close(uv_fs_event_t* handle) {
- UNREACHABLE();
-}
-
-
-int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
- return -ENOSYS;
-}
-
-
-int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
- const char* filename, unsigned int flags) {
- return -ENOSYS;
-}
-
-
-int uv_fs_event_stop(uv_fs_event_t* handle) {
- return -ENOSYS;
-}
-
-
void uv__io_poll(uv_loop_t* loop, int timeout) {
static const int max_safe_timeout = 1789569;
struct epoll_event events[1024];
@@ -863,3 +841,9 @@ update_timeout:
void uv__set_process_title(const char* title) {
/* do nothing */
}
+
+int uv__io_fork(uv_loop_t* loop) {
+ uv__platform_loop_delete(loop);
+
+ return uv__platform_loop_init(loop);
+}
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index b73994cb8d..4a812955b0 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -47,7 +47,6 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
int err;
pipe_fname = NULL;
- sockfd = -1;
/* Already bound? */
if (uv__stream_fd(handle) >= 0)
@@ -76,7 +75,9 @@ 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 err_bind;
+
+ uv__close(sockfd);
+ goto err_socket;
}
/* Success. */
@@ -85,9 +86,6 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
handle->io_watcher.fd = sockfd;
return 0;
-err_bind:
- uv__close(sockfd);
-
err_socket:
uv__free((void*)pipe_fname);
return err;
@@ -183,6 +181,14 @@ void uv_pipe_connect(uv_connect_t* req,
if (r == -1 && errno != EINPROGRESS) {
err = -errno;
+#if defined(__CYGWIN__) || defined(__MSYS__)
+ /* EBADF is supposed to mean that the socket fd is bad, but
+ Cygwin reports EBADF instead of ENOTSOCK when the file is
+ not a socket. We do not expect to see a bad fd here
+ (e.g. due to new_sock), so translate the error. */
+ if (err == -EBADF)
+ err = -ENOTSOCK;
+#endif
goto out;
}
diff --git a/deps/uv/src/unix/posix-hrtime.c b/deps/uv/src/unix/posix-hrtime.c
new file mode 100644
index 0000000000..323dfc2039
--- /dev/null
+++ b/deps/uv/src/unix/posix-hrtime.c
@@ -0,0 +1,35 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stdint.h>
+#include <time.h>
+
+#undef NANOSEC
+#define NANOSEC ((uint64_t) 1e9)
+
+uint64_t uv__hrtime(uv_clocktype_t type) {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
+}
diff --git a/deps/uv/src/unix/posix-poll.c b/deps/uv/src/unix/posix-poll.c
new file mode 100644
index 0000000000..3fba96e1bf
--- /dev/null
+++ b/deps/uv/src/unix/posix-poll.c
@@ -0,0 +1,324 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+/* POSIX defines poll() as a portable way to wait on file descriptors.
+ * Here we maintain a dynamically sized array of file descriptors and
+ * events to pass as the first argument to poll().
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+
+int uv__platform_loop_init(uv_loop_t* loop) {
+ loop->poll_fds = NULL;
+ loop->poll_fds_used = 0;
+ loop->poll_fds_size = 0;
+ loop->poll_fds_iterating = 0;
+ return 0;
+}
+
+void uv__platform_loop_delete(uv_loop_t* loop) {
+ uv__free(loop->poll_fds);
+ loop->poll_fds = NULL;
+}
+
+int uv__io_fork(uv_loop_t* loop) {
+ uv__platform_loop_delete(loop);
+ return uv__platform_loop_init(loop);
+}
+
+/* Allocate or dynamically resize our poll fds array. */
+static void uv__pollfds_maybe_resize(uv_loop_t* loop) {
+ size_t i;
+ size_t n;
+ struct pollfd* p;
+
+ if (loop->poll_fds_used < loop->poll_fds_size)
+ return;
+
+ n = loop->poll_fds_size ? loop->poll_fds_size * 2 : 64;
+ p = uv__realloc(loop->poll_fds, n * sizeof(*loop->poll_fds));
+ if (p == NULL)
+ abort();
+
+ loop->poll_fds = p;
+ for (i = loop->poll_fds_size; i < n; i++) {
+ loop->poll_fds[i].fd = -1;
+ loop->poll_fds[i].events = 0;
+ loop->poll_fds[i].revents = 0;
+ }
+ loop->poll_fds_size = n;
+}
+
+/* Primitive swap operation on poll fds array elements. */
+static void uv__pollfds_swap(uv_loop_t* loop, size_t l, size_t r) {
+ struct pollfd pfd;
+ pfd = loop->poll_fds[l];
+ loop->poll_fds[l] = loop->poll_fds[r];
+ loop->poll_fds[r] = pfd;
+}
+
+/* Add a watcher's fd to our poll fds array with its pending events. */
+static void uv__pollfds_add(uv_loop_t* loop, uv__io_t* w) {
+ size_t i;
+ struct pollfd* pe;
+
+ /* If the fd is already in the set just update its events. */
+ assert(!loop->poll_fds_iterating);
+ for (i = 0; i < loop->poll_fds_used; ++i) {
+ if (loop->poll_fds[i].fd == w->fd) {
+ loop->poll_fds[i].events = w->pevents;
+ return;
+ }
+ }
+
+ /* Otherwise, allocate a new slot in the set for the fd. */
+ uv__pollfds_maybe_resize(loop);
+ pe = &loop->poll_fds[loop->poll_fds_used++];
+ pe->fd = w->fd;
+ pe->events = w->pevents;
+}
+
+/* Remove a watcher's fd from our poll fds array. */
+static void uv__pollfds_del(uv_loop_t* loop, int fd) {
+ size_t i;
+ assert(!loop->poll_fds_iterating);
+ for (i = 0; i < loop->poll_fds_used; ++i) {
+ if (loop->poll_fds[i].fd == fd) {
+ /* swap to last position and remove */
+ --loop->poll_fds_used;
+ uv__pollfds_swap(loop, i, loop->poll_fds_used);
+ loop->poll_fds[loop->poll_fds_used].fd = -1;
+ loop->poll_fds[loop->poll_fds_used].events = 0;
+ loop->poll_fds[loop->poll_fds_used].revents = 0;
+ return;
+ }
+ }
+}
+
+
+void uv__io_poll(uv_loop_t* loop, int timeout) {
+ sigset_t* pset;
+ sigset_t set;
+ uint64_t time_base;
+ uint64_t time_diff;
+ QUEUE* q;
+ uv__io_t* w;
+ size_t i;
+ unsigned int nevents;
+ int nfds;
+ int have_signals;
+ struct pollfd* pe;
+ int fd;
+
+ if (loop->nfds == 0) {
+ assert(QUEUE_EMPTY(&loop->watcher_queue));
+ return;
+ }
+
+ /* Take queued watchers and add their fds to our poll fds array. */
+ while (!QUEUE_EMPTY(&loop->watcher_queue)) {
+ q = QUEUE_HEAD(&loop->watcher_queue);
+ QUEUE_REMOVE(q);
+ QUEUE_INIT(q);
+
+ w = QUEUE_DATA(q, uv__io_t, watcher_queue);
+ assert(w->pevents != 0);
+ assert(w->fd >= 0);
+ assert(w->fd < (int) loop->nwatchers);
+
+ uv__pollfds_add(loop, w);
+
+ w->events = w->pevents;
+ }
+
+ /* Prepare a set of signals to block around poll(), if any. */
+ pset = NULL;
+ if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
+ pset = &set;
+ sigemptyset(pset);
+ sigaddset(pset, SIGPROF);
+ }
+
+ assert(timeout >= -1);
+ time_base = loop->time;
+
+ /* Loop calls to poll() and processing of results. If we get some
+ * results from poll() but they turn out not to be interesting to
+ * our caller then we need to loop around and poll() again.
+ */
+ for (;;) {
+ if (pset != NULL)
+ if (pthread_sigmask(SIG_BLOCK, pset, NULL))
+ abort();
+ nfds = poll(loop->poll_fds, (nfds_t)loop->poll_fds_used, timeout);
+ if (pset != NULL)
+ if (pthread_sigmask(SIG_UNBLOCK, pset, NULL))
+ abort();
+
+ /* Update loop->time unconditionally. It's tempting to skip the update when
+ * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
+ * operating system didn't reschedule our process while in the syscall.
+ */
+ SAVE_ERRNO(uv__update_time(loop));
+
+ if (nfds == 0) {
+ assert(timeout != -1);
+ return;
+ }
+
+ if (nfds == -1) {
+ if (errno != EINTR)
+ abort();
+
+ if (timeout == -1)
+ continue;
+
+ if (timeout == 0)
+ return;
+
+ /* Interrupted by a signal. Update timeout and poll again. */
+ goto update_timeout;
+ }
+
+ /* Tell uv__platform_invalidate_fd not to manipulate our array
+ * while we are iterating over it.
+ */
+ loop->poll_fds_iterating = 1;
+
+ /* Initialize a count of events that we care about. */
+ nevents = 0;
+ have_signals = 0;
+
+ /* Loop over the entire poll fds array looking for returned events. */
+ for (i = 0; i < loop->poll_fds_used; i++) {
+ pe = loop->poll_fds + i;
+ fd = pe->fd;
+
+ /* Skip invalidated events, see uv__platform_invalidate_fd. */
+ if (fd == -1)
+ continue;
+
+ assert(fd >= 0);
+ assert((unsigned) fd < loop->nwatchers);
+
+ w = loop->watchers[fd];
+
+ if (w == NULL) {
+ /* File descriptor that we've stopped watching, ignore. */
+ uv__platform_invalidate_fd(loop, fd);
+ continue;
+ }
+
+ /* Filter out events that user has not requested us to watch
+ * (e.g. POLLNVAL).
+ */
+ pe->revents &= w->pevents | POLLERR | POLLHUP;
+
+ if (pe->revents != 0) {
+ /* Run signal watchers last. */
+ 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->poll_fds_iterating = 0;
+
+ /* Purge invalidated fds from our poll fds array. */
+ uv__pollfds_del(loop, -1);
+
+ if (have_signals != 0)
+ return; /* Event loop should cycle now so don't poll again. */
+
+ if (nevents != 0)
+ return;
+
+ if (timeout == 0)
+ return;
+
+ if (timeout == -1)
+ continue;
+
+update_timeout:
+ assert(timeout > 0);
+
+ time_diff = loop->time - time_base;
+ if (time_diff >= (uint64_t) timeout)
+ return;
+
+ timeout -= time_diff;
+ }
+}
+
+/* Remove the given fd from our poll fds array because no one
+ * is interested in its events anymore.
+ */
+void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
+ size_t i;
+
+ if (loop->poll_fds_iterating) {
+ /* uv__io_poll is currently iterating. Just invalidate fd. */
+ for (i = 0; i < loop->poll_fds_used; i++)
+ if (loop->poll_fds[i].fd == fd) {
+ loop->poll_fds[i].fd = -1;
+ loop->poll_fds[i].events = 0;
+ loop->poll_fds[i].revents = 0;
+ }
+ } else {
+ /* uv__io_poll is not iterating. Delete fd from the set. */
+ uv__pollfds_del(loop, fd);
+ }
+}
+
+/* Check whether the given fd is supported by poll(). */
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ struct pollfd p[1];
+ int rv;
+
+ p[0].fd = fd;
+ p[0].events = POLLIN;
+
+ do
+ rv = poll(p, 1, 0);
+ while (rv == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (rv == -1)
+ return -errno;
+
+ if (p[0].revents & POLLNVAL)
+ return -EINVAL;
+
+ return 0;
+}
diff --git a/deps/uv/src/unix/procfs-exepath.c b/deps/uv/src/unix/procfs-exepath.c
new file mode 100644
index 0000000000..5fdb611550
--- /dev/null
+++ b/deps/uv/src/unix/procfs-exepath.c
@@ -0,0 +1,45 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stddef.h>
+#include <unistd.h>
+
+int uv_exepath(char* buffer, size_t* size) {
+ ssize_t n;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return -EINVAL;
+
+ n = *size - 1;
+ if (n > 0)
+ n = readlink("/proc/self/exe", buffer, n);
+
+ if (n == -1)
+ return -errno;
+
+ buffer[n] = '\0';
+ *size = n;
+
+ return 0;
+}
diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c
index dbd8f86448..cb09ead50a 100644
--- a/deps/uv/src/unix/signal.c
+++ b/deps/uv/src/unix/signal.c
@@ -38,9 +38,14 @@ RB_HEAD(uv__signal_tree_s, uv_signal_s);
static int uv__signal_unlock(void);
+static int uv__signal_start(uv_signal_t* handle,
+ uv_signal_cb signal_cb,
+ int signum,
+ int oneshot);
static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events);
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
static void uv__signal_stop(uv_signal_t* handle);
+static void uv__signal_unregister_handler(int signum);
static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
@@ -53,8 +58,19 @@ RB_GENERATE_STATIC(uv__signal_tree_s,
uv_signal_s, tree_entry,
uv__signal_compare)
+static void uv__signal_global_reinit(void);
static void uv__signal_global_init(void) {
+ if (!uv__signal_lock_pipefd[0])
+ /* pthread_atfork can register before and after handlers, one
+ * for each child. This only registers one for the child. That
+ * state is both persistent and cumulative, so if we keep doing
+ * it the handler functions will be called multiple times. Thus
+ * we only want to do it once.
+ */
+ if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
+ abort();
+
if (uv__make_pipe(uv__signal_lock_pipefd, 0))
abort();
@@ -63,6 +79,22 @@ static void uv__signal_global_init(void) {
}
+static void uv__signal_global_reinit(void) {
+ /* We can only use signal-safe functions here.
+ * That includes read/write and close, fortunately.
+ * We do all of this directly here instead of resetting
+ * uv__signal_global_init_guard because
+ * uv__signal_global_once_init is only called from uv_loop_init
+ * and this needs to function in existing loops.
+ */
+ uv__close(uv__signal_lock_pipefd[0]);
+ uv__signal_lock_pipefd[0] = -1;
+ uv__close(uv__signal_lock_pipefd[1]);
+ uv__signal_lock_pipefd[1] = -1;
+ uv__signal_global_init();
+}
+
+
void uv__signal_global_once_init(void) {
uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
}
@@ -122,6 +154,7 @@ static uv_signal_t* uv__signal_first_handle(int signum) {
uv_signal_t* handle;
lookup.signum = signum;
+ lookup.flags = 0;
lookup.loop = NULL;
handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup);
@@ -174,7 +207,7 @@ static void uv__signal_handler(int signum) {
}
-static int uv__signal_register_handler(int signum) {
+static int uv__signal_register_handler(int signum, int oneshot) {
/* When this function is called, the signal lock must be held. */
struct sigaction sa;
@@ -183,6 +216,7 @@ static int uv__signal_register_handler(int signum) {
if (sigfillset(&sa.sa_mask))
abort();
sa.sa_handler = uv__signal_handler;
+ sa.sa_flags = oneshot ? SA_RESETHAND : 0;
/* XXX save old action so we can restore it later on? */
if (sigaction(signum, &sa, NULL))
@@ -228,6 +262,16 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) {
}
+int uv__signal_loop_fork(uv_loop_t* loop) {
+ uv__io_stop(loop, &loop->signal_io_watcher, POLLIN);
+ uv__close(loop->signal_pipefd[0]);
+ uv__close(loop->signal_pipefd[1]);
+ loop->signal_pipefd[0] = -1;
+ loop->signal_pipefd[1] = -1;
+ return uv__signal_loop_once_init(loop);
+}
+
+
void uv__signal_loop_cleanup(uv_loop_t* loop) {
QUEUE* q;
@@ -287,8 +331,24 @@ void uv__signal_close(uv_signal_t* handle) {
int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
+ return uv__signal_start(handle, signal_cb, signum, 0);
+}
+
+
+int uv_signal_start_oneshot(uv_signal_t* handle,
+ uv_signal_cb signal_cb,
+ int signum) {
+ return uv__signal_start(handle, signal_cb, signum, 1);
+}
+
+
+static int uv__signal_start(uv_signal_t* handle,
+ uv_signal_cb signal_cb,
+ int signum,
+ int oneshot) {
sigset_t saved_sigmask;
int err;
+ uv_signal_t* first_handle;
assert(!uv__is_closing(handle));
@@ -318,9 +378,12 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
/* If at this point there are no active signal watchers for this signum (in
* any of the loops), it's time to try and register a handler for it here.
+ * Also in case there's only one-shot handlers and a regular handler comes in.
*/
- if (uv__signal_first_handle(signum) == NULL) {
- err = uv__signal_register_handler(signum);
+ first_handle = uv__signal_first_handle(signum);
+ if (first_handle == NULL ||
+ (!oneshot && (first_handle->flags & UV__SIGNAL_ONE_SHOT))) {
+ err = uv__signal_register_handler(signum, oneshot);
if (err) {
/* Registering the signal handler failed. Must be an invalid signal. */
uv__signal_unlock_and_unblock(&saved_sigmask);
@@ -329,6 +392,9 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
}
handle->signum = signum;
+ if (oneshot)
+ handle->flags |= UV__SIGNAL_ONE_SHOT;
+
RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
uv__signal_unlock_and_unblock(&saved_sigmask);
@@ -390,6 +456,9 @@ static void uv__signal_event(uv_loop_t* loop,
handle->dispatched_signals++;
+ if (handle->flags & UV__SIGNAL_ONE_SHOT)
+ uv__signal_stop(handle);
+
/* If uv_close was called while there were caught signals that were not
* yet dispatched, the uv__finish_close was deferred. Make close pending
* now if this has happened.
@@ -414,12 +483,22 @@ static void uv__signal_event(uv_loop_t* loop,
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
+ int f1;
+ int f2;
/* Compare signums first so all watchers with the same signnum end up
* adjacent.
*/
if (w1->signum < w2->signum) return -1;
if (w1->signum > w2->signum) return 1;
+ /* Handlers without UV__SIGNAL_ONE_SHOT set will come first, so if the first
+ * handler returned is a one-shot handler, the rest will be too.
+ */
+ f1 = w1->flags & UV__SIGNAL_ONE_SHOT;
+ f2 = w2->flags & UV__SIGNAL_ONE_SHOT;
+ if (f1 < f2) return -1;
+ if (f1 > f2) return 1;
+
/* Sort by loop pointer, so we can easily look up the first item after
* { .signum = x, .loop = NULL }.
*/
@@ -443,6 +522,10 @@ int uv_signal_stop(uv_signal_t* handle) {
static void uv__signal_stop(uv_signal_t* handle) {
uv_signal_t* removed_handle;
sigset_t saved_sigmask;
+ uv_signal_t* first_handle;
+ int rem_oneshot;
+ int first_oneshot;
+ int ret;
/* If the watcher wasn't started, this is a no-op. */
if (handle->signum == 0)
@@ -457,8 +540,17 @@ static void uv__signal_stop(uv_signal_t* handle) {
/* Check if there are other active signal watchers observing this signal. If
* not, unregister the signal handler.
*/
- if (uv__signal_first_handle(handle->signum) == NULL)
+ first_handle = uv__signal_first_handle(handle->signum);
+ if (first_handle == NULL) {
uv__signal_unregister_handler(handle->signum);
+ } else {
+ rem_oneshot = handle->flags & UV__SIGNAL_ONE_SHOT;
+ first_oneshot = first_handle->flags & UV__SIGNAL_ONE_SHOT;
+ if (first_oneshot && !rem_oneshot) {
+ ret = uv__signal_register_handler(handle->signum, 1);
+ assert(ret == 0);
+ }
+ }
uv__signal_unlock_and_unblock(&saved_sigmask);
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 7059df16a6..7b23d16ecf 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -390,7 +390,7 @@ failed_malloc:
int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
-#if defined(__APPLE__) || defined(__MVS__)
+#if defined(__APPLE__)
int enable;
#endif
@@ -409,7 +409,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
return -errno;
}
-#if defined(__APPLE__) || defined(__MVS__)
+#if defined(__APPLE__)
enable = 1;
if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
errno != ENOTSOCK &&
@@ -785,7 +785,12 @@ start:
struct msghdr msg;
struct cmsghdr *cmsg;
int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
- char scratch[64] = {0};
+ union {
+ char data[64];
+ struct cmsghdr alias;
+ } scratch;
+
+ memset(&scratch, 0, sizeof(scratch));
assert(fd_to_send >= 0);
@@ -795,7 +800,7 @@ start:
msg.msg_iovlen = iovcnt;
msg.msg_flags = 0;
- msg.msg_control = (void*) scratch;
+ msg.msg_control = &scratch.alias;
msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send));
cmsg = CMSG_FIRSTHDR(&msg);
@@ -1168,6 +1173,11 @@ static void uv__read(uv_stream_t* stream) {
uv__stream_osx_interrupt_select(stream);
}
stream->read_cb(stream, 0, &buf);
+#if defined(__CYGWIN__) || defined(__MSYS__)
+ } else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) {
+ uv__stream_eof(stream, &buf);
+ return;
+#endif
} else {
/* Error. User should call uv_close(). */
stream->read_cb(stream, -errno, &buf);
@@ -1400,6 +1410,12 @@ int uv_write2(uv_write_t* req,
*/
if (uv__handle_fd((uv_handle_t*) send_handle) < 0)
return -EBADF;
+
+#if defined(__CYGWIN__) || defined(__MSYS__)
+ /* Cygwin recvmsg always sets msg_controllen to zero, so we cannot send it.
+ See https://github.com/mirror/newlib-cygwin/blob/86fc4bf0/winsup/cygwin/fhandler_socket.cc#L1736-L1743 */
+ return -ENOSYS;
+#endif
}
/* It's legal for write_queue_size > 0 even when the write_queue is empty;
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index a43f7f1b1c..2dc02ae457 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -99,6 +99,18 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
+int uv__io_fork(uv_loop_t* loop) {
+#if defined(PORT_SOURCE_FILE)
+ if (loop->fs_fd != -1) {
+ /* stop the watcher before we blow away its fileno */
+ uv__io_stop(loop, &loop->fs_event_watcher, POLLIN);
+ }
+#endif
+ uv__platform_loop_delete(loop);
+ return uv__platform_loop_init(loop);
+}
+
+
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct port_event* events;
uintptr_t i;
@@ -469,8 +481,10 @@ int uv_fs_event_start(uv_fs_event_t* handle,
memset(&handle->fo, 0, sizeof handle->fo);
handle->fo.fo_name = handle->path;
err = uv__fs_event_rearm(handle);
- if (err != 0)
+ if (err != 0) {
+ uv_fs_event_stop(handle);
return err;
+ }
if (first_run) {
uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd);
@@ -531,25 +545,6 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
#endif /* defined(PORT_SOURCE_FILE) */
-char** uv_setup_args(int argc, char** argv) {
- return argv;
-}
-
-
-int uv_set_process_title(const char* title) {
- return 0;
-}
-
-
-int uv_get_process_title(char* buffer, size_t size) {
- if (buffer == NULL || size == 0)
- return -EINVAL;
-
- buffer[0] = '\0';
- return 0;
-}
-
-
int uv_resident_set_memory(size_t* rss) {
psinfo_t psinfo;
int err;
@@ -746,6 +741,17 @@ static int uv__set_phys_addr(uv_interface_address_t* address,
return 0;
}
+
+static int uv__ifaddr_exclude(struct ifaddrs *ent) {
+ if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
+ return 1;
+ if (ent->ifa_addr == NULL)
+ return 1;
+ if (ent->ifa_addr->sa_family == PF_PACKET)
+ return 1;
+ return 0;
+}
+
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address;
struct ifaddrs* addrs;
@@ -759,12 +765,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
/* Count the number of interfaces */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
- (ent->ifa_addr == NULL) ||
- (ent->ifa_addr->sa_family == PF_PACKET)) {
+ if (uv__ifaddr_exclude(ent))
continue;
- }
-
(*count)++;
}
@@ -777,10 +779,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
- continue;
-
- if (ent->ifa_addr == NULL)
+ if (uv__ifaddr_exclude(ent))
continue;
address->name = uv__strdup(ent->ifa_name);
diff --git a/deps/uv/src/unix/sysinfo-loadavg.c b/deps/uv/src/unix/sysinfo-loadavg.c
new file mode 100644
index 0000000000..ebad0e89db
--- /dev/null
+++ b/deps/uv/src/unix/sysinfo-loadavg.c
@@ -0,0 +1,36 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stdint.h>
+#include <sys/sysinfo.h>
+
+void uv_loadavg(double avg[3]) {
+ struct sysinfo info;
+
+ if (sysinfo(&info) < 0) return;
+
+ avg[0] = (double) info.loads[0] / 65536.0;
+ avg[1] = (double) info.loads[1] / 65536.0;
+ avg[2] = (double) info.loads[2] / 65536.0;
+}
diff --git a/deps/uv/src/unix/sysinfo-memory.c b/deps/uv/src/unix/sysinfo-memory.c
new file mode 100644
index 0000000000..23b4fc6e91
--- /dev/null
+++ b/deps/uv/src/unix/sysinfo-memory.c
@@ -0,0 +1,42 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stdint.h>
+#include <sys/sysinfo.h>
+
+uint64_t uv_get_free_memory(void) {
+ struct sysinfo info;
+
+ if (sysinfo(&info) == 0)
+ return (uint64_t) info.freeram * info.mem_unit;
+ return 0;
+}
+
+uint64_t uv_get_total_memory(void) {
+ struct sysinfo info;
+
+ if (sysinfo(&info) == 0)
+ return (uint64_t) info.totalram * info.mem_unit;
+ return 0;
+}
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index 1cd4925786..c556325de0 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -307,7 +307,7 @@ int uv__udp_bind(uv_udp_t* handle,
if (flags & UV_UDP_REUSEADDR) {
err = uv__set_reuse(fd);
if (err)
- goto out;
+ return err;
}
if (flags & UV_UDP_IPV6ONLY) {
@@ -315,11 +315,11 @@ int uv__udp_bind(uv_udp_t* handle,
yes = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) {
err = -errno;
- goto out;
+ return err;
}
#else
err = -ENOTSUP;
- goto out;
+ return err;
#endif
}
@@ -329,27 +329,25 @@ int uv__udp_bind(uv_udp_t* handle,
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
* socket created with AF_INET to an AF_INET6 address or vice versa. */
err = -EINVAL;
- goto out;
+ return err;
}
if (addr->sa_family == AF_INET6)
handle->flags |= UV_HANDLE_IPV6;
handle->flags |= UV_HANDLE_BOUND;
-
return 0;
-
-out:
- uv__close(handle->io_watcher.fd);
- handle->io_watcher.fd = -1;
- return err;
}
static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
int domain,
unsigned int flags) {
- unsigned char taddr[sizeof(struct sockaddr_in6)];
+ union {
+ struct sockaddr_in6 in6;
+ struct sockaddr_in in;
+ struct sockaddr addr;
+ } taddr;
socklen_t addrlen;
if (handle->io_watcher.fd != -1)
@@ -358,7 +356,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
switch (domain) {
case AF_INET:
{
- struct sockaddr_in* addr = (void*)&taddr;
+ struct sockaddr_in* addr = &taddr.in;
memset(addr, 0, sizeof *addr);
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = INADDR_ANY;
@@ -367,7 +365,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
}
case AF_INET6:
{
- struct sockaddr_in6* addr = (void*)&taddr;
+ struct sockaddr_in6* addr = &taddr.in6;
memset(addr, 0, sizeof *addr);
addr->sin6_family = AF_INET6;
addr->sin6_addr = in6addr_any;
@@ -379,7 +377,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
abort();
}
- return uv__udp_bind(handle, (const struct sockaddr*) &taddr, addrlen, flags);
+ return uv__udp_bind(handle, &taddr.addr, addrlen, flags);
}
@@ -429,6 +427,13 @@ int uv__udp_send(uv_udp_send_t* req,
if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) {
uv__udp_sendmsg(handle);
+
+ /* `uv__udp_sendmsg` may not be able to do non-blocking write straight
+ * away. In such cases the `io_watcher` has to be queued for asynchronous
+ * write.
+ */
+ if (!QUEUE_EMPTY(&handle->write_queue))
+ uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
} else {
uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
}
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index 27902fdf86..781a8559dc 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -55,16 +55,19 @@ extern int snprintf(char*, size_t, const char*, ...);
#ifndef _WIN32
enum {
+ UV__SIGNAL_ONE_SHOT = 0x80000, /* On signal reception remove sighandler */
UV__HANDLE_INTERNAL = 0x8000,
UV__HANDLE_ACTIVE = 0x4000,
UV__HANDLE_REF = 0x2000,
UV__HANDLE_CLOSING = 0 /* no-op on unix */
};
#else
-# define UV__HANDLE_INTERNAL 0x80
-# define UV__HANDLE_ACTIVE 0x40
-# define UV__HANDLE_REF 0x20
-# define UV__HANDLE_CLOSING 0x01
+# define UV__SIGNAL_ONE_SHOT_DISPATCHED 0x200
+# define UV__SIGNAL_ONE_SHOT 0x100
+# define UV__HANDLE_INTERNAL 0x80
+# define UV__HANDLE_ACTIVE 0x40
+# define UV__HANDLE_REF 0x20
+# define UV__HANDLE_CLOSING 0x01
#endif
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
@@ -215,6 +218,30 @@ void uv__fs_scandir_cleanup(uv_fs_t* req);
} \
while (0)
+/* Note: uses an open-coded version of SET_REQ_SUCCESS() because of
+ * a circular dependency between src/uv-common.h and src/win/internal.h.
+ */
+#if defined(_WIN32)
+# define UV_REQ_INIT(req, typ) \
+ do { \
+ (req)->type = (typ); \
+ (req)->u.io.overlapped.Internal = 0; /* SET_REQ_SUCCESS() */ \
+ } \
+ while (0)
+#else
+# define UV_REQ_INIT(req, typ) \
+ do { \
+ (req)->type = (typ); \
+ } \
+ while (0)
+#endif
+
+#define uv__req_init(loop, req, typ) \
+ do { \
+ UV_REQ_INIT(req, typ); \
+ uv__req_register(loop, req); \
+ } \
+ while (0)
/* Allocator prototypes */
void *uv__calloc(size_t count, size_t size);
diff --git a/deps/uv/src/win/async.c b/deps/uv/src/win/async.c
index ad240ab897..0b636ed1e9 100644
--- a/deps/uv/src/win/async.c
+++ b/deps/uv/src/win/async.c
@@ -45,8 +45,7 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
handle->async_cb = async_cb;
req = &handle->async_req;
- uv_req_init(loop, req);
- req->type = UV_WAKEUP;
+ UV_REQ_INIT(req, UV_WAKEUP);
req->data = handle;
uv__handle_start(handle);
diff --git a/deps/uv/src/win/atomicops-inl.h b/deps/uv/src/win/atomicops-inl.h
index 61e006026c..6d8126f692 100644
--- a/deps/uv/src/win/atomicops-inl.h
+++ b/deps/uv/src/win/atomicops-inl.h
@@ -23,6 +23,7 @@
#define UV_WIN_ATOMICOPS_INL_H_
#include "uv.h"
+#include "internal.h"
/* Atomic set operation on char */
@@ -34,7 +35,7 @@
/* target to be aligned. */
#pragma intrinsic(_InterlockedOr8)
-static char __declspec(inline) uv__atomic_exchange_set(char volatile* target) {
+static char INLINE uv__atomic_exchange_set(char volatile* target) {
return _InterlockedOr8(target, 1);
}
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index e84186d4ec..9ed4e824c6 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -83,13 +83,8 @@ static int uv__loops_capacity;
#define UV__LOOPS_CHUNK_SIZE 8
static uv_mutex_t uv__loops_lock;
-static void uv__loops_init() {
+static void uv__loops_init(void) {
uv_mutex_init(&uv__loops_lock);
- uv__loops = uv__calloc(UV__LOOPS_CHUNK_SIZE, sizeof(uv_loop_t*));
- if (!uv__loops)
- uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
- uv__loops_size = 0;
- uv__loops_capacity = UV__LOOPS_CHUNK_SIZE;
}
static int uv__loops_add(uv_loop_t* loop) {
@@ -138,6 +133,13 @@ static void uv__loops_remove(uv_loop_t* loop) {
uv__loops[uv__loops_size - 1] = NULL;
--uv__loops_size;
+ if (uv__loops_size == 0) {
+ uv__loops_capacity = 0;
+ uv__free(uv__loops);
+ uv__loops = NULL;
+ goto loop_removed;
+ }
+
/* If we didn't grow to big skip downsizing */
if (uv__loops_capacity < 4 * UV__LOOPS_CHUNK_SIZE)
goto loop_removed;
@@ -156,7 +158,7 @@ loop_removed:
uv_mutex_unlock(&uv__loops_lock);
}
-void uv__wake_all_loops() {
+void uv__wake_all_loops(void) {
int i;
uv_loop_t* loop;
@@ -332,6 +334,11 @@ int uv_backend_fd(const uv_loop_t* loop) {
}
+int uv_loop_fork(uv_loop_t* loop) {
+ return UV_ENOSYS;
+}
+
+
int uv_backend_timeout(const uv_loop_t* loop) {
if (loop->stop_flag != 0)
return 0;
diff --git a/deps/uv/src/win/detect-wakeup.c b/deps/uv/src/win/detect-wakeup.c
index a12179f798..72dfb7a177 100644
--- a/deps/uv/src/win/detect-wakeup.c
+++ b/deps/uv/src/win/detect-wakeup.c
@@ -2,9 +2,9 @@
#include "internal.h"
#include "winapi.h"
-static void uv__register_system_resume_callback();
+static void uv__register_system_resume_callback(void);
-void uv__init_detect_system_wakeup() {
+void uv__init_detect_system_wakeup(void) {
/* Try registering system power event callback. This is the cleanest
* method, but it will only work on Win8 and above.
*/
@@ -20,7 +20,7 @@ static ULONG CALLBACK uv__system_resume_callback(PVOID Context,
return 0;
}
-static void uv__register_system_resume_callback() {
+static void uv__register_system_resume_callback(void) {
_DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS recipient;
_HPOWERNOTIFY registration_handle;
diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c
index 03e4adc058..95f843ad08 100644
--- a/deps/uv/src/win/fs-event.c
+++ b/deps/uv/src/win/fs-event.c
@@ -81,8 +81,17 @@ static void uv_relative_path(const WCHAR* filename,
static int uv_split_path(const WCHAR* filename, WCHAR** dir,
WCHAR** file) {
- int len = wcslen(filename);
- int i = len;
+ size_t len, i;
+
+ if (filename == NULL) {
+ if (dir != NULL)
+ *dir = NULL;
+ *file = NULL;
+ return 0;
+ }
+
+ len = wcslen(filename);
+ i = len;
while (i > 0 && filename[--i] != '\\' && filename[i] != '/');
if (i == 0) {
@@ -131,8 +140,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
handle->short_filew = NULL;
handle->dirw = NULL;
- uv_req_init(loop, (uv_req_t*)&handle->req);
- handle->req.type = UV_FS_EVENT_REQ;
+ UV_REQ_INIT(&handle->req, UV_FS_EVENT_REQ);
handle->req.data = handle;
return 0;
@@ -146,7 +154,8 @@ int uv_fs_event_start(uv_fs_event_t* handle,
int name_size, is_path_dir;
DWORD attr, last_error;
WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
- WCHAR short_path[MAX_PATH];
+ WCHAR short_path_buffer[MAX_PATH];
+ WCHAR* short_path;
if (uv__is_active(handle))
return UV_EINVAL;
@@ -188,7 +197,6 @@ int uv_fs_event_start(uv_fs_event_t* handle,
if (is_path_dir) {
/* path is a directory, so that's the directory that we will watch. */
- handle->dirw = pathw;
dir_to_watch = pathw;
} else {
/*
@@ -197,9 +205,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
*/
/* Convert to short path. */
+ short_path = short_path_buffer;
if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) {
- last_error = GetLastError();
- goto error;
+ short_path = NULL;
}
if (uv_split_path(pathw, &dir, &handle->filew) != 0) {
@@ -274,6 +282,8 @@ int uv_fs_event_start(uv_fs_event_t* handle,
goto error;
}
+ assert(is_path_dir ? pathw != NULL : pathw == NULL);
+ handle->dirw = pathw;
handle->req_pending = 1;
return 0;
@@ -305,6 +315,9 @@ error:
handle->buffer = NULL;
}
+ if (uv__is_active(handle))
+ uv__handle_stop(handle);
+
return uv_translate_sys_error(last_error);
}
@@ -344,8 +357,11 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
}
-static int file_info_cmp(WCHAR* str, WCHAR* file_name, int file_name_len) {
- int str_len;
+static int file_info_cmp(WCHAR* str, WCHAR* file_name, size_t file_name_len) {
+ size_t str_len;
+
+ if (str == NULL)
+ return -1;
str_len = wcslen(str);
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 6902d4f1a6..2d72cdc70f 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -114,7 +114,7 @@ const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
const WCHAR UNC_PATH_PREFIX_LEN = 8;
-void uv_fs_init() {
+void uv_fs_init(void) {
_fmode = _O_BINARY;
}
@@ -220,9 +220,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
uv_fs_type fs_type, const uv_fs_cb cb) {
- uv_req_init(loop, (uv_req_t*) req);
-
- req->type = UV_FS;
+ UV_REQ_INIT(req, UV_FS);
req->loop = loop;
req->flags = 0;
req->fs_type = fs_type;
@@ -1373,7 +1371,7 @@ static void fs__access(uv_fs_t* req) {
* - or it's a directory.
* (Directories cannot be read-only on Windows.)
*/
- if (!(req->flags & W_OK) ||
+ if (!(req->fs.info.mode & W_OK) ||
!(attr & FILE_ATTRIBUTE_READONLY) ||
(attr & FILE_ATTRIBUTE_DIRECTORY)) {
SET_REQ_RESULT(req, 0);
@@ -2400,7 +2398,7 @@ int uv_fs_access(uv_loop_t* loop,
if (err)
return uv_translate_sys_error(err);
- req->flags = flags;
+ req->fs.info.mode = flags;
if (cb) {
QUEUE_FS_TP_JOB(loop, req);
diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c
index c13bfec350..baab838898 100644
--- a/deps/uv/src/win/getaddrinfo.c
+++ b/deps/uv/src/win/getaddrinfo.c
@@ -265,11 +265,9 @@ int uv_getaddrinfo(uv_loop_t* loop,
return UV_EINVAL;
}
- uv_req_init(loop, (uv_req_t*)req);
-
+ UV_REQ_INIT(req, UV_GETADDRINFO);
req->getaddrinfo_cb = getaddrinfo_cb;
req->addrinfo = NULL;
- req->type = UV_GETADDRINFO;
req->loop = loop;
req->retcode = 0;
diff --git a/deps/uv/src/win/getnameinfo.c b/deps/uv/src/win/getnameinfo.c
index 66b64b8832..9f10cd2a5a 100644
--- a/deps/uv/src/win/getnameinfo.c
+++ b/deps/uv/src/win/getnameinfo.c
@@ -127,12 +127,11 @@ int uv_getnameinfo(uv_loop_t* loop,
return UV_EINVAL;
}
- uv_req_init(loop, (uv_req_t*)req);
+ UV_REQ_INIT(req, UV_GETNAMEINFO);
uv__req_register(loop, req);
req->getnameinfo_cb = getnameinfo_cb;
req->flags = flags;
- req->type = UV_GETNAMEINFO;
req->loop = loop;
req->retcode = 0;
diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c
index 72b49d9790..39150702dd 100644
--- a/deps/uv/src/win/handle.c
+++ b/deps/uv/src/win/handle.c
@@ -152,3 +152,8 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
int uv_is_closing(const uv_handle_t* handle) {
return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED));
}
+
+
+uv_os_fd_t uv_get_osfhandle(int fd) {
+ return uv__get_osfhandle(fd);
+}
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index b8cfde90e8..444327d647 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -206,7 +206,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
/*
* TTY
*/
-void uv_console_init();
+void uv_console_init(void);
int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
@@ -259,7 +259,7 @@ void uv_prepare_invoke(uv_loop_t* loop);
void uv_check_invoke(uv_loop_t* loop);
void uv_idle_invoke(uv_loop_t* loop);
-void uv__once_init();
+void uv__once_init(void);
/*
@@ -275,7 +275,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
/*
* Signal watcher
*/
-void uv_signals_init();
+void uv_signals_init(void);
int uv__signal_dispatch(int signum);
void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle);
@@ -302,7 +302,7 @@ int uv_translate_sys_error(int sys_errno);
/*
* FS
*/
-void uv_fs_init();
+void uv_fs_init(void);
/*
@@ -323,14 +323,15 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
/*
* Utilities.
*/
-void uv__util_init();
+void uv__util_init(void);
uint64_t uv__hrtime(double scale);
-int uv_parent_pid();
-int uv_current_pid();
+int uv_parent_pid(void);
+int uv_current_pid(void);
__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, int utf16len, char** utf8);
+int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
/*
@@ -349,13 +350,13 @@ HANDLE uv__stdio_handle(BYTE* buffer, int fd);
/*
* Winapi and ntapi utility functions
*/
-void uv_winapi_init();
+void uv_winapi_init(void);
/*
* Winsock utility functions
*/
-void uv_winsock_init();
+void uv_winsock_init(void);
int uv_ntstatus_to_winsock_error(NTSTATUS status);
@@ -384,11 +385,11 @@ extern struct sockaddr_in6 uv_addr_ip6_any_;
/*
* Wake all loops with fake message
*/
-void uv__wake_all_loops();
+void uv__wake_all_loops(void);
/*
* Init system wake-up detection
*/
-void uv__init_detect_system_wakeup();
+void uv__init_detect_system_wakeup(void);
#endif /* UV_WIN_INTERNAL_H_ */
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index 2442be7301..edf3002121 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -103,7 +103,7 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
handle->pipe.conn.non_overlapped_writes_tail = NULL;
handle->pipe.conn.readfile_thread = NULL;
- uv_req_init(loop, (uv_req_t*) &handle->pipe.conn.ipc_header_write_req);
+ UV_REQ_INIT(&handle->pipe.conn.ipc_header_write_req, UV_UNKNOWN_REQ);
return 0;
}
@@ -505,8 +505,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
req = &handle->pipe.serv.accept_reqs[i];
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_ACCEPT;
+ UV_REQ_INIT(req, UV_ACCEPT);
req->data = handle;
req->pipeHandle = INVALID_HANDLE_VALUE;
req->next_pending = NULL;
@@ -626,8 +625,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
HANDLE pipeHandle = INVALID_HANDLE_VALUE;
DWORD duplex_flags;
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_CONNECT;
+ UV_REQ_INIT(req, UV_CONNECT);
req->handle = (uv_stream_t*) handle;
req->cb = cb;
@@ -962,7 +960,7 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) {
uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */
if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
GetCurrentProcess(), &hThread,
- 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ 0, FALSE, DUPLICATE_SAME_ACCESS)) {
handle->pipe.conn.readfile_thread = hThread;
} else {
hThread = NULL;
@@ -1239,8 +1237,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
assert(handle->handle != INVALID_HANDLE_VALUE);
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_WRITE;
+ UV_REQ_INIT(req, UV_WRITE);
req->handle = (uv_stream_t*) handle;
req->cb = cb;
req->ipc_header = 0;
@@ -1301,8 +1298,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
}
}
- uv_req_init(loop, (uv_req_t*) ipc_header_req);
- ipc_header_req->type = UV_WRITE;
+ UV_REQ_INIT(ipc_header_req, UV_WRITE);
ipc_header_req->handle = (uv_stream_t*) handle;
ipc_header_req->cb = NULL;
ipc_header_req->ipc_header = 1;
@@ -2076,7 +2072,6 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
buffer[addrlen] = '\0';
err = 0;
- goto cleanup;
error:
uv__free(name_info);
diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c
index d479e521ef..a648ba711d 100644
--- a/deps/uv/src/win/poll.c
+++ b/deps/uv/src/win/poll.c
@@ -61,13 +61,13 @@ static void uv__init_overlapped_dummy(void) {
}
-static OVERLAPPED* uv__get_overlapped_dummy() {
+static OVERLAPPED* uv__get_overlapped_dummy(void) {
uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy);
return &overlapped_dummy_;
}
-static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() {
+static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) {
return &afd_poll_info_dummy_;
}
@@ -572,13 +572,11 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
/* Initialize 2 poll reqs. */
handle->submitted_events_1 = 0;
- uv_req_init(loop, (uv_req_t*) &(handle->poll_req_1));
- handle->poll_req_1.type = UV_POLL_REQ;
+ UV_REQ_INIT(&handle->poll_req_1, UV_POLL_REQ);
handle->poll_req_1.data = handle;
handle->submitted_events_2 = 0;
- uv_req_init(loop, (uv_req_t*) &(handle->poll_req_2));
- handle->poll_req_2.type = UV_POLL_REQ;
+ UV_REQ_INIT(&handle->poll_req_2, UV_POLL_REQ);
handle->poll_req_2.data = handle;
return 0;
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index bdf88d2cdd..d141601607 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -148,8 +148,7 @@ static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
handle->child_stdio_buffer = NULL;
handle->exit_cb_pending = 0;
- uv_req_init(loop, (uv_req_t*)&handle->exit_req);
- handle->exit_req.type = UV_PROCESS_EXIT;
+ UV_REQ_INIT(&handle->exit_req, UV_PROCESS_EXIT);
handle->exit_req.data = handle;
}
diff --git a/deps/uv/src/win/req-inl.h b/deps/uv/src/win/req-inl.h
index b5e502eef5..f2513b7d3e 100644
--- a/deps/uv/src/win/req-inl.h
+++ b/deps/uv/src/win/req-inl.h
@@ -34,6 +34,9 @@
#define SET_REQ_ERROR(req, error) \
SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error)))
+/* Note: used open-coded in UV_REQ_INIT() because of a circular dependency
+ * between src/uv-common.h and src/win/internal.h.
+ */
#define SET_REQ_SUCCESS(req) \
SET_REQ_STATUS((req), STATUS_SUCCESS)
@@ -79,12 +82,6 @@
}
-INLINE static void uv_req_init(uv_loop_t* loop, uv_req_t* req) {
- req->type = UV_UNKNOWN_REQ;
- SET_REQ_SUCCESS(req);
-}
-
-
INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) {
return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped);
}
diff --git a/deps/uv/src/win/signal.c b/deps/uv/src/win/signal.c
index af7974c364..7b42dd9928 100644
--- a/deps/uv/src/win/signal.c
+++ b/deps/uv/src/win/signal.c
@@ -34,7 +34,12 @@ static CRITICAL_SECTION uv__signal_lock;
static BOOL WINAPI uv__signal_control_handler(DWORD type);
-void uv_signals_init() {
+int uv__signal_start(uv_signal_t* handle,
+ uv_signal_cb signal_cb,
+ int signum,
+ int oneshot);
+
+void uv_signals_init(void) {
InitializeCriticalSection(&uv__signal_lock);
if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
abort();
@@ -70,7 +75,9 @@ RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare
int uv__signal_dispatch(int signum) {
uv_signal_t lookup;
uv_signal_t* handle;
- int dispatched = 0;
+ int dispatched;
+
+ dispatched = 0;
EnterCriticalSection(&uv__signal_lock);
@@ -83,11 +90,16 @@ int uv__signal_dispatch(int signum) {
unsigned long previous = InterlockedExchange(
(volatile LONG*) &handle->pending_signum, signum);
+ if (handle->flags & UV__SIGNAL_ONE_SHOT_DISPATCHED)
+ continue;
+
if (!previous) {
POST_COMPLETION_FOR_REQ(handle->loop, &handle->signal_req);
}
dispatched = 1;
+ if (handle->flags & UV__SIGNAL_ONE_SHOT)
+ handle->flags |= UV__SIGNAL_ONE_SHOT_DISPATCHED;
}
LeaveCriticalSection(&uv__signal_lock);
@@ -128,17 +140,13 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
- uv_req_t* req;
-
uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
handle->pending_signum = 0;
handle->signum = 0;
handle->signal_cb = NULL;
- req = &handle->signal_req;
- uv_req_init(loop, req);
- req->type = UV_SIGNAL_REQ;
- req->data = handle;
+ UV_REQ_INIT(&handle->signal_req, UV_SIGNAL_REQ);
+ handle->signal_req.data = handle;
return 0;
}
@@ -166,6 +174,21 @@ int uv_signal_stop(uv_signal_t* handle) {
int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
+ return uv__signal_start(handle, signal_cb, signum, 0);
+}
+
+
+int uv_signal_start_oneshot(uv_signal_t* handle,
+ uv_signal_cb signal_cb,
+ int signum) {
+ return uv__signal_start(handle, signal_cb, signum, 1);
+}
+
+
+int uv__signal_start(uv_signal_t* handle,
+ uv_signal_cb signal_cb,
+ int signum,
+ int oneshot) {
/* Test for invalid signal values. */
if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG))
return UV_EINVAL;
@@ -189,6 +212,9 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
EnterCriticalSection(&uv__signal_lock);
handle->signum = signum;
+ if (oneshot)
+ handle->flags |= UV__SIGNAL_ONE_SHOT;
+
RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
LeaveCriticalSection(&uv__signal_lock);
@@ -217,6 +243,9 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
if (dispatched_signum == handle->signum)
handle->signal_cb(handle, dispatched_signum);
+ if (handle->flags & UV__SIGNAL_ONE_SHOT)
+ uv_signal_stop(handle);
+
if (handle->flags & UV__HANDLE_CLOSING) {
/* When it is closing, it must be stopped at this point. */
assert(handle->signum == 0);
diff --git a/deps/uv/src/win/stream-inl.h b/deps/uv/src/win/stream-inl.h
index b7a3c11958..bf12148afe 100644
--- a/deps/uv/src/win/stream-inl.h
+++ b/deps/uv/src/win/stream-inl.h
@@ -43,10 +43,9 @@ INLINE static void uv_connection_init(uv_stream_t* handle) {
handle->flags |= UV_HANDLE_CONNECTION;
handle->stream.conn.write_reqs_pending = 0;
- uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req));
+ UV_REQ_INIT(&handle->read_req, UV_READ);
handle->read_req.event_handle = NULL;
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
- handle->read_req.type = UV_READ;
handle->read_req.data = handle;
handle->stream.conn.shutdown_req = NULL;
diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c
index a2466e5e9d..13cbfdcb9e 100644
--- a/deps/uv/src/win/stream.c
+++ b/deps/uv/src/win/stream.c
@@ -210,8 +210,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
return UV_EPIPE;
}
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_SHUTDOWN;
+ UV_REQ_INIT(req, UV_SHUTDOWN);
req->handle = handle;
req->cb = cb;
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index 0709696ff9..972539f4df 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -555,7 +555,6 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
- uv_loop_t* loop = handle->loop;
unsigned int i, simultaneous_accepts;
uv_tcp_accept_t* req;
int err;
@@ -612,8 +611,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
for (i = 0; i < simultaneous_accepts; i++) {
req = &handle->tcp.serv.accept_reqs[i];
- uv_req_init(loop, (uv_req_t*)req);
- req->type = UV_ACCEPT;
+ UV_REQ_INIT(req, UV_ACCEPT);
req->accept_socket = INVALID_SOCKET;
req->data = handle;
@@ -635,8 +633,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
/* try to clean up {uv_simultaneous_server_accepts} requests. */
for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
req = &handle->tcp.serv.accept_reqs[i];
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_ACCEPT;
+ UV_REQ_INIT(req, UV_ACCEPT);
req->accept_socket = INVALID_SOCKET;
req->data = handle;
req->wait_handle = INVALID_HANDLE_VALUE;
@@ -779,8 +776,7 @@ static int uv_tcp_try_connect(uv_connect_t* req,
}
}
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_CONNECT;
+ UV_REQ_INIT(req, UV_CONNECT);
req->handle = (uv_stream_t*) handle;
req->cb = cb;
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
@@ -863,8 +859,7 @@ int uv_tcp_write(uv_loop_t* loop,
int result;
DWORD bytes;
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_WRITE;
+ UV_REQ_INIT(req, UV_WRITE);
req->handle = (uv_stream_t*) handle;
req->cb = cb;
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index 1b7adf64ff..a6f583956f 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -138,7 +138,7 @@ typedef enum {
static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED;
static void uv__determine_vterm_state(HANDLE handle);
-void uv_console_init() {
+void uv_console_init(void) {
if (uv_sem_init(&uv_tty_output_lock, 1))
abort();
}
@@ -2126,8 +2126,7 @@ int uv_tty_write(uv_loop_t* loop,
uv_write_cb cb) {
DWORD error;
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_WRITE;
+ UV_REQ_INIT(req, UV_WRITE);
req->handle = (uv_stream_t*) handle;
req->cb = cb;
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index 9bf1453e53..2fd15cfa9a 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -142,8 +142,7 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
handle->func_wsarecvfrom = WSARecvFrom;
handle->send_queue_size = 0;
handle->send_queue_count = 0;
- uv_req_init(loop, (uv_req_t*) &(handle->recv_req));
- handle->recv_req.type = UV_UDP_RECV;
+ UV_REQ_INIT(&handle->recv_req, UV_UDP_RECV);
handle->recv_req.data = handle;
/* If anything fails beyond this point we need to remove the handle from
@@ -417,8 +416,7 @@ static int uv__send(uv_udp_send_t* req,
uv_loop_t* loop = handle->loop;
DWORD result, bytes;
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_UDP_SEND;
+ UV_REQ_INIT(req, UV_UDP_SEND);
req->handle = handle;
req->cb = cb;
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index 050058afaa..d2e7f772ce 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -59,6 +59,17 @@
# define UNLEN 256
#endif
+/*
+ Max hostname length. The Windows gethostname() documentation states that 256
+ bytes will always be large enough to hold the null-terminated hostname.
+*/
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 256
+#endif
+
+/* Maximum environment variable size, including the terminating null */
+#define MAX_ENV_VAR_LENGTH 32767
+
/* Cached copy of the process title, plus a mutex guarding it. */
static char *process_title;
static CRITICAL_SECTION process_title_lock;
@@ -74,7 +85,7 @@ static double hrtime_interval_ = 0;
/*
* One-time initialization code for functionality defined in util.c.
*/
-void uv__util_init() {
+void uv__util_init(void) {
LARGE_INTEGER perf_frequency;
/* Initialize process title access mutex. */
@@ -320,7 +331,7 @@ uint64_t uv_get_total_memory(void) {
}
-int uv_parent_pid() {
+int uv_parent_pid(void) {
int parent_pid = -1;
HANDLE handle;
PROCESSENTRY32 pe;
@@ -343,7 +354,7 @@ int uv_parent_pid() {
}
-int uv_current_pid() {
+int uv_current_pid(void) {
if (current_pid == 0) {
current_pid = GetCurrentProcessId();
}
@@ -405,7 +416,7 @@ done:
}
-static int uv__get_process_title() {
+static int uv__get_process_title(void) {
WCHAR title_w[MAX_TITLE_LENGTH];
if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
@@ -1322,6 +1333,47 @@ int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {
}
+/*
+ * Converts a UTF-8 string into a UTF-16 one. The resulting string is
+ * null-terminated.
+ *
+ * If utf8 is null terminated, utf8len can be set to -1, otherwise it must
+ * be specified.
+ */
+int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {
+ int bufsize;
+
+ if (utf8 == NULL)
+ return UV_EINVAL;
+
+ /* Check how much space we need */
+ bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0);
+
+ if (bufsize == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ /* Allocate the destination buffer adding an extra byte for the terminating
+ * NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so
+ * we do it ourselves always, just in case. */
+ *utf16 = uv__malloc(sizeof(WCHAR) * (bufsize + 1));
+
+ if (*utf16 == NULL)
+ return UV_ENOMEM;
+
+ /* Convert to UTF-16 */
+ bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
+
+ if (bufsize == 0) {
+ uv__free(*utf16);
+ *utf16 = NULL;
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ (*utf16)[bufsize] = '\0';
+ return 0;
+}
+
+
int uv__getpwuid_r(uv_passwd_t* pwd) {
HANDLE token;
wchar_t username[UNLEN + 1];
@@ -1387,3 +1439,138 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
int uv_os_get_passwd(uv_passwd_t* pwd) {
return uv__getpwuid_r(pwd);
}
+
+
+int uv_os_getenv(const char* name, char* buffer, size_t* size) {
+ wchar_t var[MAX_ENV_VAR_LENGTH];
+ wchar_t* name_w;
+ DWORD bufsize;
+ size_t len;
+ int r;
+
+ if (name == NULL || buffer == NULL || size == NULL || *size == 0)
+ return UV_EINVAL;
+
+ r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+
+ if (r != 0)
+ return r;
+
+ len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH);
+ uv__free(name_w);
+ assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */
+
+ if (len == 0) {
+ r = GetLastError();
+
+ if (r == ERROR_ENVVAR_NOT_FOUND)
+ return UV_ENOENT;
+
+ return uv_translate_sys_error(r);
+ }
+
+ /* Check how much space we need */
+ bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
+
+ if (bufsize == 0) {
+ return uv_translate_sys_error(GetLastError());
+ } else if (bufsize > *size) {
+ *size = bufsize;
+ return UV_ENOBUFS;
+ }
+
+ /* Convert to UTF-8 */
+ bufsize = WideCharToMultiByte(CP_UTF8,
+ 0,
+ var,
+ -1,
+ buffer,
+ *size,
+ NULL,
+ NULL);
+
+ if (bufsize == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ *size = bufsize - 1;
+ return 0;
+}
+
+
+int uv_os_setenv(const char* name, const char* value) {
+ wchar_t* name_w;
+ wchar_t* value_w;
+ int r;
+
+ if (name == NULL || value == NULL)
+ return UV_EINVAL;
+
+ r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+
+ if (r != 0)
+ return r;
+
+ r = uv__convert_utf8_to_utf16(value, -1, &value_w);
+
+ if (r != 0) {
+ uv__free(name_w);
+ return r;
+ }
+
+ r = SetEnvironmentVariableW(name_w, value_w);
+ uv__free(name_w);
+ uv__free(value_w);
+
+ if (r == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ return 0;
+}
+
+
+int uv_os_unsetenv(const char* name) {
+ wchar_t* name_w;
+ int r;
+
+ if (name == NULL)
+ return UV_EINVAL;
+
+ r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+
+ if (r != 0)
+ return r;
+
+ r = SetEnvironmentVariableW(name_w, NULL);
+ uv__free(name_w);
+
+ if (r == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ return 0;
+}
+
+
+int uv_os_gethostname(char* buffer, size_t* size) {
+ char buf[MAXHOSTNAMELEN + 1];
+ size_t len;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return UV_EINVAL;
+
+ uv__once_init(); /* Initialize winsock */
+
+ if (gethostname(buf, sizeof(buf)) != 0)
+ return uv_translate_sys_error(WSAGetLastError());
+
+ buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
+ len = strlen(buf);
+
+ if (len >= *size) {
+ *size = len + 1;
+ return UV_ENOBUFS;
+ }
+
+ memcpy(buffer, buf, len + 1);
+ *size = len;
+ return 0;
+}
diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c
index 1fa179b572..aa5d719fbe 100644
--- a/deps/uv/src/win/winapi.c
+++ b/deps/uv/src/win/winapi.c
@@ -53,7 +53,7 @@ sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
-void uv_winapi_init() {
+void uv_winapi_init(void) {
HMODULE ntdll_module;
HMODULE kernel32_module;
HMODULE powrprof_module;
diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c
index d2e667e9f7..e86d76b131 100644
--- a/deps/uv/src/win/winsock.c
+++ b/deps/uv/src/win/winsock.c
@@ -80,7 +80,7 @@ static int error_means_no_support(DWORD error) {
}
-void uv_winsock_init() {
+void uv_winsock_init(void) {
WSADATA wsa_data;
int errorno;
SOCKET dummy;