libuv 2017-05-09 (e11dcd43)

Code extracted from:

    https://github.com/libuv/libuv.git

at commit e11dcd4377185359874e67f4962995fdb7e83d19 (v1.x).
This commit is contained in:
libuv upstream
2017-05-09 15:51:26 -04:00
committed by Brad King
parent 1f661e87a6
commit 12a78bc824
47 changed files with 959 additions and 713 deletions

View File

@@ -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; \

View File

@@ -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]);

View File

@@ -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),

View File

@@ -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;

View File

@@ -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);
assert(w == &loop->async_io_watcher);
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);
}
}
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);
#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;
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);
}
#endif
wa->cb(loop, wa, n);
}
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)
return;
int uv__async_fork(uv_loop_t* loop) {
if (loop->async_io_watcher.fd == -1) /* never started */
return 0;
if (wa->wfd != -1) {
if (wa->wfd != wa->io_watcher.fd)
uv__close(wa->wfd);
wa->wfd = -1;
}
uv__async_stop(loop);
uv__io_stop(loop, &wa->io_watcher, POLLIN);
uv__close(wa->io_watcher.fd);
wa->io_watcher.fd = -1;
return uv__async_start(loop);
}
static int uv__async_eventfd() {
void uv__async_stop(uv_loop_t* loop) {
if (loop->async_io_watcher.fd == -1)
return;
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, &loop->async_io_watcher, POLLIN);
uv__close(loop->async_io_watcher.fd);
loop->async_io_watcher.fd = -1;
}
static int uv__async_eventfd(void) {
#if defined(__linux__)
static int no_eventfd2;
static int no_eventfd;

133
src/unix/bsd-ifaddrs.c Normal file
View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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;

35
src/unix/posix-hrtime.c Normal file
View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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_ */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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));

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;