summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlibuv upstream <libuv@googlegroups.com>2017-05-09 19:51:26 (GMT)
committerBrad King <brad.king@kitware.com>2017-05-15 14:43:03 (GMT)
commit12a78bc824655524d817508d6107ef4dcf8e3626 (patch)
tree39bcf5989f7696efbb2cb777b1ce5b0062df7939
parent1f661e87a6a8304edb77bd30b546e5d113477c59 (diff)
downloadCMake-12a78bc824655524d817508d6107ef4dcf8e3626.zip
CMake-12a78bc824655524d817508d6107ef4dcf8e3626.tar.gz
CMake-12a78bc824655524d817508d6107ef4dcf8e3626.tar.bz2
libuv 2017-05-09 (e11dcd43)
Code extracted from: https://github.com/libuv/libuv.git at commit e11dcd4377185359874e67f4962995fdb7e83d19 (v1.x).
-rw-r--r--include/uv-unix.h15
-rw-r--r--include/uv.h8
-rw-r--r--src/threadpool.c35
-rw-r--r--src/unix/aix.c7
-rw-r--r--src/unix/async.c121
-rw-r--r--src/unix/bsd-ifaddrs.c133
-rw-r--r--src/unix/core.c45
-rw-r--r--src/unix/darwin.c104
-rw-r--r--src/unix/freebsd.c114
-rw-r--r--src/unix/internal.h22
-rw-r--r--src/unix/kqueue.c36
-rw-r--r--src/unix/linux-core.c53
-rw-r--r--src/unix/linux-inotify.c67
-rw-r--r--src/unix/loop.c38
-rw-r--r--src/unix/netbsd.c108
-rw-r--r--src/unix/openbsd.c111
-rw-r--r--src/unix/os390-syscalls.c2
-rw-r--r--src/unix/os390.c6
-rw-r--r--src/unix/pipe.c8
-rw-r--r--src/unix/posix-hrtime.c35
-rw-r--r--src/unix/signal.c100
-rw-r--r--src/unix/stream.c9
-rw-r--r--src/unix/sunos.c38
-rw-r--r--src/unix/udp.c33
-rw-r--r--src/uv-common.h35
-rw-r--r--src/win/async.c3
-rw-r--r--src/win/atomicops-inl.h3
-rw-r--r--src/win/core.c21
-rw-r--r--src/win/detect-wakeup.c6
-rw-r--r--src/win/fs-event.c33
-rw-r--r--src/win/fs.c10
-rw-r--r--src/win/getaddrinfo.c4
-rw-r--r--src/win/getnameinfo.c3
-rw-r--r--src/win/internal.h23
-rw-r--r--src/win/pipe.c17
-rw-r--r--src/win/poll.c10
-rw-r--r--src/win/process.c3
-rw-r--r--src/win/req-inl.h9
-rw-r--r--src/win/signal.c45
-rw-r--r--src/win/stream-inl.h3
-rw-r--r--src/win/stream.c3
-rw-r--r--src/win/tcp.c13
-rw-r--r--src/win/tty.c5
-rw-r--r--src/win/udp.c6
-rw-r--r--src/win/util.c161
-rw-r--r--src/win/winapi.c2
-rw-r--r--src/win/winsock.c2
47 files changed, 957 insertions, 711 deletions
diff --git a/include/uv-unix.h b/include/uv-unix.h
index 3030f71..5440729 100644
--- a/include/uv-unix.h
+++ b/include/uv-unix.h
@@ -79,7 +79,6 @@
#endif
struct uv__io_s;
-struct uv__async;
struct uv_loop_s;
typedef void (*uv__io_cb)(struct uv_loop_s* loop,
@@ -97,16 +96,6 @@ struct uv__io_s {
UV_IO_PRIVATE_PLATFORM_FIELDS
};
-typedef void (*uv__async_cb)(struct uv_loop_s* loop,
- struct uv__async* w,
- unsigned int nevents);
-
-struct uv__async {
- uv__async_cb cb;
- uv__io_t io_watcher;
- int wfd;
-};
-
#ifndef UV_PLATFORM_SEM_T
# define UV_PLATFORM_SEM_T sem_t
#endif
@@ -216,7 +205,9 @@ typedef struct {
void* check_handles[2]; \
void* idle_handles[2]; \
void* async_handles[2]; \
- struct uv__async async_watcher; \
+ void (*async_unused)(void); /* TODO(bnoordhuis) Remove in libuv v2. */ \
+ uv__io_t async_io_watcher; \
+ int async_wfd; \
struct { \
void* min; \
unsigned int nelts; \
diff --git a/include/uv.h b/include/uv.h
index 31f09f0..14e09e4 100644
--- a/include/uv.h
+++ b/include/uv.h
@@ -274,6 +274,7 @@ UV_EXTERN void uv_loop_delete(uv_loop_t*);
UV_EXTERN size_t uv_loop_size(void);
UV_EXTERN int uv_loop_alive(const uv_loop_t* loop);
UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...);
+UV_EXTERN int uv_loop_fork(uv_loop_t* loop);
UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
UV_EXTERN void uv_stop(uv_loop_t*);
@@ -1073,6 +1074,10 @@ UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count);
+UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
+UV_EXTERN int uv_os_setenv(const char* name, const char* value);
+UV_EXTERN int uv_os_unsetenv(const char* name);
+
typedef enum {
UV_FS_UNKNOWN = -1,
@@ -1324,6 +1329,9 @@ UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle);
UV_EXTERN int uv_signal_start(uv_signal_t* handle,
uv_signal_cb signal_cb,
int signum);
+UV_EXTERN int uv_signal_start_oneshot(uv_signal_t* handle,
+ uv_signal_cb signal_cb,
+ int signum);
UV_EXTERN int uv_signal_stop(uv_signal_t* handle);
UV_EXTERN void uv_loadavg(double avg[3]);
diff --git a/src/threadpool.c b/src/threadpool.c
index 2c5152b..1089341 100644
--- a/src/threadpool.c
+++ b/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/src/unix/aix.c b/src/unix/aix.c
index 1d2cd4a..388c9cc 100644
--- a/src/unix/aix.c
+++ b/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/src/unix/async.c b/src/unix/async.c
index 393cdeb..45c088e 100644
--- a/src/unix/async.c
+++ b/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/src/unix/bsd-ifaddrs.c b/src/unix/bsd-ifaddrs.c
new file mode 100644
index 0000000..0b5653d
--- /dev/null
+++ b/src/unix/bsd-ifaddrs.c
@@ -0,0 +1,133 @@
+/* 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>
+#include <net/if_dl.h>
+
+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) {
+ struct sockaddr_dl* sa_addr;
+ 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/src/unix/core.c b/src/unix/core.c
index 9ef7134..96495b8 100644
--- a/src/unix/core.c
+++ b/src/unix/core.c
@@ -1240,3 +1240,48 @@ 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;
+}
diff --git a/src/unix/darwin.c b/src/unix/darwin.c
index cf95da2..df6dd1c 100644
--- a/src/unix/darwin.c
+++ b/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/src/unix/freebsd.c b/src/unix/freebsd.c
index cba44a3..e52ae99 100644
--- a/src/unix/freebsd.c
+++ b/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/src/unix/internal.h b/src/unix/internal.h
index b48f8fa..2e3afa6 100644
--- a/src/unix/internal.h
+++ b/src/unix/internal.h
@@ -192,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);
@@ -233,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);
@@ -302,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.
*/
@@ -327,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/src/unix/kqueue.c b/src/unix/kqueue.c
index fffd462..6bc60bb 100644
--- a/src/unix/kqueue.c
+++ b/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/src/unix/linux-core.c b/src/unix/linux-core.c
index 58dd813..646be4f 100644
--- a/src/unix/linux-core.c
+++ b/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);
@@ -868,6 +886,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 +918,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 +936,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 +960,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/src/unix/linux-inotify.c b/src/unix/linux-inotify.c
index 4708c05..5934c5d 100644
--- a/src/unix/linux-inotify.c
+++ b/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/src/unix/loop.c b/src/unix/loop.c
index bd63c2f..bcd4924 100644
--- a/src/unix/loop.c
+++ b/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/src/unix/netbsd.c b/src/unix/netbsd.c
index 4a9e6cb..9b5546b 100644
--- a/src/unix/netbsd.c
+++ b/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/src/unix/openbsd.c b/src/unix/openbsd.c
index ac28b69..7e4b253 100644
--- a/src/unix/openbsd.c
+++ b/src/unix/openbsd.c
@@ -28,10 +28,6 @@
#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>
@@ -40,9 +36,6 @@
#include <string.h>
#include <unistd.h>
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
static char *process_title;
@@ -56,13 +49,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);
@@ -297,100 +283,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/src/unix/os390-syscalls.c b/src/unix/os390-syscalls.c
index 2bf3b73..7edf235 100644
--- a/src/unix/os390-syscalls.c
+++ b/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/src/unix/os390.c b/src/unix/os390.c
index be325a9..e9ba90c 100644
--- a/src/unix/os390.c
+++ b/src/unix/os390.c
@@ -863,3 +863,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/src/unix/pipe.c b/src/unix/pipe.c
index b73994c..dd3d034 100644
--- a/src/unix/pipe.c
+++ b/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;
diff --git a/src/unix/posix-hrtime.c b/src/unix/posix-hrtime.c
new file mode 100644
index 0000000..323dfc2
--- /dev/null
+++ b/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/src/unix/signal.c b/src/unix/signal.c
index dbd8f86..cb09ead 100644
--- a/src/unix/signal.c
+++ b/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/src/unix/stream.c b/src/unix/stream.c
index 7059df1..dbd04f2 100644
--- a/src/unix/stream.c
+++ b/src/unix/stream.c
@@ -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);
diff --git a/src/unix/sunos.c b/src/unix/sunos.c
index a43f7f1..c34b870 100644
--- a/src/unix/sunos.c
+++ b/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);
@@ -746,6 +760,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 +784,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 +798,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/src/unix/udp.c b/src/unix/udp.c
index 1cd4925..c556325 100644
--- a/src/unix/udp.c
+++ b/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/src/uv-common.h b/src/uv-common.h
index 27902fd..781a855 100644
--- a/src/uv-common.h
+++ b/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/src/win/async.c b/src/win/async.c
index ad240ab..0b636ed 100644
--- a/src/win/async.c
+++ b/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/src/win/atomicops-inl.h b/src/win/atomicops-inl.h
index 61e0060..6d8126f 100644
--- a/src/win/atomicops-inl.h
+++ b/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/src/win/core.c b/src/win/core.c
index e84186d..9ed4e82 100644
--- a/src/win/core.c
+++ b/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/src/win/detect-wakeup.c b/src/win/detect-wakeup.c
index a12179f..72dfb7a 100644
--- a/src/win/detect-wakeup.c
+++ b/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/src/win/fs-event.c b/src/win/fs-event.c
index 05fc1d0..95f843a 100644
--- a/src/win/fs-event.c
+++ b/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;
@@ -196,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) {
@@ -306,6 +315,9 @@ error:
handle->buffer = NULL;
}
+ if (uv__is_active(handle))
+ uv__handle_stop(handle);
+
return uv_translate_sys_error(last_error);
}
@@ -345,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/src/win/fs.c b/src/win/fs.c
index 6902d4f..2d72cdc 100644
--- a/src/win/fs.c
+++ b/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/src/win/getaddrinfo.c b/src/win/getaddrinfo.c
index c13bfec..baab838 100644
--- a/src/win/getaddrinfo.c
+++ b/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/src/win/getnameinfo.c b/src/win/getnameinfo.c
index 66b64b8..9f10cd2 100644
--- a/src/win/getnameinfo.c
+++ b/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/src/win/internal.h b/src/win/internal.h
index b8cfde9..444327d 100644
--- a/src/win/internal.h
+++ b/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/src/win/pipe.c b/src/win/pipe.c
index 2442be7..edf3002 100644
--- a/src/win/pipe.c
+++ b/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/src/win/poll.c b/src/win/poll.c
index d479e52..a648ba7 100644
--- a/src/win/poll.c
+++ b/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/src/win/process.c b/src/win/process.c
index bdf88d2..d141601 100644
--- a/src/win/process.c
+++ b/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/src/win/req-inl.h b/src/win/req-inl.h
index b5e502e..f2513b7 100644
--- a/src/win/req-inl.h
+++ b/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/src/win/signal.c b/src/win/signal.c
index af7974c..7b42dd9 100644
--- a/src/win/signal.c
+++ b/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/src/win/stream-inl.h b/src/win/stream-inl.h
index b7a3c11..bf12148 100644
--- a/src/win/stream-inl.h
+++ b/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/src/win/stream.c b/src/win/stream.c
index a2466e5..13cbfdc 100644
--- a/src/win/stream.c
+++ b/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/src/win/tcp.c b/src/win/tcp.c
index 0709696..972539f 100644
--- a/src/win/tcp.c
+++ b/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/src/win/tty.c b/src/win/tty.c
index 1b7adf6..a6f5839 100644
--- a/src/win/tty.c
+++ b/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/src/win/udp.c b/src/win/udp.c
index 9bf1453..2fd15cf 100644
--- a/src/win/udp.c
+++ b/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/src/win/util.c b/src/win/util.c
index 050058a..1d64d4c 100644
--- a/src/win/util.c
+++ b/src/win/util.c
@@ -59,6 +59,9 @@
# define UNLEN 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 +77,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 +323,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 +346,7 @@ int uv_parent_pid() {
}
-int uv_current_pid() {
+int uv_current_pid(void) {
if (current_pid == 0) {
current_pid = GetCurrentProcessId();
}
@@ -405,7 +408,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 +1325,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 +1431,112 @@ 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;
+}
diff --git a/src/win/winapi.c b/src/win/winapi.c
index 1fa179b..aa5d719 100644
--- a/src/win/winapi.c
+++ b/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/src/win/winsock.c b/src/win/winsock.c
index d2e667e..e86d76b 100644
--- a/src/win/winsock.c
+++ b/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;