forked from cory/tildefriends
libuv 1.48.0.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4828 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
9
deps/libuv/src/idna.c
vendored
9
deps/libuv/src/idna.c
vendored
@ -322,6 +322,9 @@ ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
char* ds;
|
||||
int rc;
|
||||
|
||||
if (s == se)
|
||||
return UV_EINVAL;
|
||||
|
||||
ds = d;
|
||||
|
||||
si = s;
|
||||
@ -356,9 +359,10 @@ ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (d < de)
|
||||
*d++ = '\0';
|
||||
if (d >= de)
|
||||
return UV_EINVAL;
|
||||
|
||||
*d++ = '\0';
|
||||
return d - ds; /* Number of bytes written. */
|
||||
}
|
||||
|
||||
@ -400,6 +404,7 @@ void uv_wtf8_to_utf16(const char* source_ptr,
|
||||
}
|
||||
} while (*source_ptr++);
|
||||
|
||||
(void)w_target_len;
|
||||
assert(w_target_len == 0);
|
||||
}
|
||||
|
||||
|
43
deps/libuv/src/timer.c
vendored
43
deps/libuv/src/timer.c
vendored
@ -40,8 +40,8 @@ static int timer_less_than(const struct heap_node* ha,
|
||||
const uv_timer_t* a;
|
||||
const uv_timer_t* b;
|
||||
|
||||
a = container_of(ha, uv_timer_t, heap_node);
|
||||
b = container_of(hb, uv_timer_t, heap_node);
|
||||
a = container_of(ha, uv_timer_t, node.heap);
|
||||
b = container_of(hb, uv_timer_t, node.heap);
|
||||
|
||||
if (a->timeout < b->timeout)
|
||||
return 1;
|
||||
@ -60,6 +60,7 @@ int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
|
||||
handle->timer_cb = NULL;
|
||||
handle->timeout = 0;
|
||||
handle->repeat = 0;
|
||||
uv__queue_init(&handle->node.queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -73,8 +74,7 @@ int uv_timer_start(uv_timer_t* handle,
|
||||
if (uv__is_closing(handle) || cb == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (uv__is_active(handle))
|
||||
uv_timer_stop(handle);
|
||||
uv_timer_stop(handle);
|
||||
|
||||
clamped_timeout = handle->loop->time + timeout;
|
||||
if (clamped_timeout < timeout)
|
||||
@ -87,7 +87,7 @@ int uv_timer_start(uv_timer_t* handle,
|
||||
handle->start_id = handle->loop->timer_counter++;
|
||||
|
||||
heap_insert(timer_heap(handle->loop),
|
||||
(struct heap_node*) &handle->heap_node,
|
||||
(struct heap_node*) &handle->node.heap,
|
||||
timer_less_than);
|
||||
uv__handle_start(handle);
|
||||
|
||||
@ -96,14 +96,16 @@ int uv_timer_start(uv_timer_t* handle,
|
||||
|
||||
|
||||
int uv_timer_stop(uv_timer_t* handle) {
|
||||
if (!uv__is_active(handle))
|
||||
return 0;
|
||||
|
||||
heap_remove(timer_heap(handle->loop),
|
||||
(struct heap_node*) &handle->heap_node,
|
||||
timer_less_than);
|
||||
uv__handle_stop(handle);
|
||||
if (uv__is_active(handle)) {
|
||||
heap_remove(timer_heap(handle->loop),
|
||||
(struct heap_node*) &handle->node.heap,
|
||||
timer_less_than);
|
||||
uv__handle_stop(handle);
|
||||
} else {
|
||||
uv__queue_remove(&handle->node.queue);
|
||||
}
|
||||
|
||||
uv__queue_init(&handle->node.queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -148,7 +150,7 @@ int uv__next_timeout(const uv_loop_t* loop) {
|
||||
if (heap_node == NULL)
|
||||
return -1; /* block indefinitely */
|
||||
|
||||
handle = container_of(heap_node, uv_timer_t, heap_node);
|
||||
handle = container_of(heap_node, uv_timer_t, node.heap);
|
||||
if (handle->timeout <= loop->time)
|
||||
return 0;
|
||||
|
||||
@ -163,17 +165,30 @@ int uv__next_timeout(const uv_loop_t* loop) {
|
||||
void uv__run_timers(uv_loop_t* loop) {
|
||||
struct heap_node* heap_node;
|
||||
uv_timer_t* handle;
|
||||
struct uv__queue* queue_node;
|
||||
struct uv__queue ready_queue;
|
||||
|
||||
uv__queue_init(&ready_queue);
|
||||
|
||||
for (;;) {
|
||||
heap_node = heap_min(timer_heap(loop));
|
||||
if (heap_node == NULL)
|
||||
break;
|
||||
|
||||
handle = container_of(heap_node, uv_timer_t, heap_node);
|
||||
handle = container_of(heap_node, uv_timer_t, node.heap);
|
||||
if (handle->timeout > loop->time)
|
||||
break;
|
||||
|
||||
uv_timer_stop(handle);
|
||||
uv__queue_insert_tail(&ready_queue, &handle->node.queue);
|
||||
}
|
||||
|
||||
while (!uv__queue_empty(&ready_queue)) {
|
||||
queue_node = uv__queue_head(&ready_queue);
|
||||
uv__queue_remove(queue_node);
|
||||
uv__queue_init(queue_node);
|
||||
handle = container_of(queue_node, uv_timer_t, node.queue);
|
||||
|
||||
uv_timer_again(handle);
|
||||
handle->timer_cb(handle);
|
||||
}
|
||||
|
125
deps/libuv/src/unix/core.c
vendored
125
deps/libuv/src/unix/core.c
vendored
@ -90,6 +90,7 @@ extern char** environ;
|
||||
#if defined(__linux__)
|
||||
# include <sched.h>
|
||||
# include <sys/syscall.h>
|
||||
# define gettid() syscall(SYS_gettid)
|
||||
# define uv__accept4 accept4
|
||||
#endif
|
||||
|
||||
@ -1557,6 +1558,130 @@ int uv_os_setpriority(uv_pid_t pid, int priority) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function succeeds, the return value is 0.
|
||||
* If the function fails, the return value is non-zero.
|
||||
* for Linux, when schedule policy is SCHED_OTHER (default), priority is 0.
|
||||
* So the output parameter priority is actually the nice value.
|
||||
*/
|
||||
int uv_thread_getpriority(uv_thread_t tid, int* priority) {
|
||||
int r;
|
||||
int policy;
|
||||
struct sched_param param;
|
||||
#ifdef __linux__
|
||||
pid_t pid = gettid();
|
||||
#endif
|
||||
|
||||
if (priority == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
r = pthread_getschedparam(tid, &policy, ¶m);
|
||||
if (r != 0)
|
||||
return UV__ERR(errno);
|
||||
|
||||
#ifdef __linux__
|
||||
if (SCHED_OTHER == policy && pthread_equal(tid, pthread_self())) {
|
||||
errno = 0;
|
||||
r = getpriority(PRIO_PROCESS, pid);
|
||||
if (r == -1 && errno != 0)
|
||||
return UV__ERR(errno);
|
||||
*priority = r;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
*priority = param.sched_priority;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static int set_nice_for_calling_thread(int priority) {
|
||||
int r;
|
||||
int nice;
|
||||
|
||||
if (priority < UV_THREAD_PRIORITY_LOWEST || priority > UV_THREAD_PRIORITY_HIGHEST)
|
||||
return UV_EINVAL;
|
||||
|
||||
pid_t pid = gettid();
|
||||
nice = 0 - priority * 2;
|
||||
r = setpriority(PRIO_PROCESS, pid, nice);
|
||||
if (r != 0)
|
||||
return UV__ERR(errno);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* If the function succeeds, the return value is 0.
|
||||
* If the function fails, the return value is non-zero.
|
||||
*/
|
||||
int uv_thread_setpriority(uv_thread_t tid, int priority) {
|
||||
int r;
|
||||
int min;
|
||||
int max;
|
||||
int range;
|
||||
int prio;
|
||||
int policy;
|
||||
struct sched_param param;
|
||||
|
||||
if (priority < UV_THREAD_PRIORITY_LOWEST || priority > UV_THREAD_PRIORITY_HIGHEST)
|
||||
return UV_EINVAL;
|
||||
|
||||
r = pthread_getschedparam(tid, &policy, ¶m);
|
||||
if (r != 0)
|
||||
return UV__ERR(errno);
|
||||
|
||||
#ifdef __linux__
|
||||
/**
|
||||
* for Linux, when schedule policy is SCHED_OTHER (default), priority must be 0,
|
||||
* we should set the nice value in this case.
|
||||
*/
|
||||
if (SCHED_OTHER == policy && pthread_equal(tid, pthread_self()))
|
||||
return set_nice_for_calling_thread(priority);
|
||||
#endif
|
||||
|
||||
#ifdef __PASE__
|
||||
min = 1;
|
||||
max = 127;
|
||||
#else
|
||||
min = sched_get_priority_min(policy);
|
||||
max = sched_get_priority_max(policy);
|
||||
#endif
|
||||
|
||||
if (min == -1 || max == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
range = max - min;
|
||||
|
||||
switch (priority) {
|
||||
case UV_THREAD_PRIORITY_HIGHEST:
|
||||
prio = max;
|
||||
break;
|
||||
case UV_THREAD_PRIORITY_ABOVE_NORMAL:
|
||||
prio = min + range * 3 / 4;
|
||||
break;
|
||||
case UV_THREAD_PRIORITY_NORMAL:
|
||||
prio = min + range / 2;
|
||||
break;
|
||||
case UV_THREAD_PRIORITY_BELOW_NORMAL:
|
||||
prio = min + range / 4;
|
||||
break;
|
||||
case UV_THREAD_PRIORITY_LOWEST:
|
||||
prio = min;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (param.sched_priority != prio) {
|
||||
param.sched_priority = prio;
|
||||
r = pthread_setschedparam(tid, policy, ¶m);
|
||||
if (r != 0)
|
||||
return UV__ERR(errno);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uv_os_uname(uv_utsname_t* buffer) {
|
||||
struct utsname buf;
|
||||
|
14
deps/libuv/src/unix/fs.c
vendored
14
deps/libuv/src/unix/fs.c
vendored
@ -84,7 +84,9 @@
|
||||
|
||||
#if defined(__CYGWIN__) || \
|
||||
(defined(__HAIKU__) && B_HAIKU_VERSION < B_HAIKU_VERSION_1_PRE_BETA_5) || \
|
||||
(defined(__sun) && !defined(__illumos__))
|
||||
(defined(__sun) && !defined(__illumos__)) || \
|
||||
(defined(__APPLE__) && !TARGET_OS_IPHONE && \
|
||||
MAC_OS_X_VERSION_MIN_REQUIRED < 110000)
|
||||
#define preadv(fd, bufs, nbufs, off) \
|
||||
pread(fd, (bufs)->iov_base, (bufs)->iov_len, off)
|
||||
#define pwritev(fd, bufs, nbufs, off) \
|
||||
@ -1628,6 +1630,16 @@ static void uv__fs_done(struct uv__work* w, int status) {
|
||||
}
|
||||
|
||||
|
||||
void uv__fs_post(uv_loop_t* loop, uv_fs_t* req) {
|
||||
uv__req_register(loop, req);
|
||||
uv__work_submit(loop,
|
||||
&req->work_req,
|
||||
UV__WORK_FAST_IO,
|
||||
uv__fs_work,
|
||||
uv__fs_done);
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_access(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
|
1
deps/libuv/src/unix/internal.h
vendored
1
deps/libuv/src/unix/internal.h
vendored
@ -425,6 +425,7 @@ UV_UNUSED(static int uv__stat(const char* path, struct stat* s)) {
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
void uv__fs_post(uv_loop_t* loop, uv_fs_t* req);
|
||||
ssize_t
|
||||
uv__fs_copy_file_range(int fd_in,
|
||||
off_t* off_in,
|
||||
|
16
deps/libuv/src/unix/kqueue.c
vendored
16
deps/libuv/src/unix/kqueue.c
vendored
@ -488,11 +488,21 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) {
|
||||
* the struct's kf_structsize must be initialised beforehand
|
||||
* whether with the KINFO_FILE_SIZE constant or this way.
|
||||
*/
|
||||
struct stat statbuf;
|
||||
struct kinfo_file kf;
|
||||
kf.kf_structsize = sizeof(kf);
|
||||
|
||||
if (fcntl(handle->event_watcher.fd, F_KINFO, &kf) == 0)
|
||||
path = uv__basename_r(kf.kf_path);
|
||||
if (handle->event_watcher.fd != -1 &&
|
||||
(!uv__fstat(handle->event_watcher.fd, &statbuf) && !(statbuf.st_mode & S_IFDIR))) {
|
||||
/* we are purposely not using KINFO_FILE_SIZE here
|
||||
* as it is not available on non intl archs
|
||||
* and here it gives 1392 too on intel.
|
||||
* anyway, the man page also mentions we can proceed
|
||||
* this way.
|
||||
*/
|
||||
kf.kf_structsize = sizeof(kf);
|
||||
if (fcntl(handle->event_watcher.fd, F_KINFO, &kf) == 0)
|
||||
path = uv__basename_r(kf.kf_path);
|
||||
}
|
||||
#endif
|
||||
handle->cb(handle, path, events, 0);
|
||||
|
||||
|
50
deps/libuv/src/unix/linux.c
vendored
50
deps/libuv/src/unix/linux.c
vendored
@ -37,12 +37,16 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <netpacket/packet.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
@ -120,25 +124,6 @@
|
||||
# endif
|
||||
#endif /* __NR_getrandom */
|
||||
|
||||
#define HAVE_IFADDRS_H 1
|
||||
|
||||
# if defined(__ANDROID_API__) && __ANDROID_API__ < 24
|
||||
# undef HAVE_IFADDRS_H
|
||||
#endif
|
||||
|
||||
#ifdef __UCLIBC__
|
||||
# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
|
||||
# undef HAVE_IFADDRS_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
# include <ifaddrs.h>
|
||||
# include <sys/socket.h>
|
||||
# include <net/ethernet.h>
|
||||
# include <netpacket/packet.h>
|
||||
#endif /* HAVE_IFADDRS_H */
|
||||
|
||||
enum {
|
||||
UV__IORING_SETUP_SQPOLL = 2u,
|
||||
};
|
||||
@ -478,6 +463,9 @@ static int uv__use_io_uring(void) {
|
||||
#elif defined(__arm__) && __SIZEOF_POINTER__ == 4
|
||||
/* See https://github.com/libuv/libuv/issues/4158. */
|
||||
return 0; /* All 32 bits kernels appear buggy. */
|
||||
#elif defined(__powerpc64__) || defined(__ppc64__)
|
||||
/* See https://github.com/libuv/libuv/issues/4283. */
|
||||
return 0; /* Random SIGSEGV in signal handler. */
|
||||
#else
|
||||
/* Ternary: unknown=0, yes=1, no=-1 */
|
||||
static _Atomic int use_io_uring;
|
||||
@ -487,8 +475,16 @@ static int uv__use_io_uring(void) {
|
||||
use = atomic_load_explicit(&use_io_uring, memory_order_relaxed);
|
||||
|
||||
if (use == 0) {
|
||||
use = uv__kernel_version() >=
|
||||
#if defined(__hppa__)
|
||||
/* io_uring first supported on parisc in 6.1, functional in .51 */
|
||||
/* https://lore.kernel.org/all/cb912694-b1fe-dbb0-4d8c-d608f3526905@gmx.de/ */
|
||||
/* 6.1.51 */ 0x060133
|
||||
#else
|
||||
/* Older kernels have a bug where the sqpoll thread uses 100% CPU. */
|
||||
use = uv__kernel_version() >= /* 5.10.186 */ 0x050ABA ? 1 : -1;
|
||||
/* 5.10.186 */ 0x050ABA
|
||||
#endif
|
||||
? 1 : -1;
|
||||
|
||||
/* But users can still enable it if they so desire. */
|
||||
val = getenv("UV_USE_IO_URING");
|
||||
@ -1162,6 +1158,12 @@ static void uv__poll_io_uring(uv_loop_t* loop, struct uv__iou* iou) {
|
||||
uv__req_unregister(loop, req);
|
||||
iou->in_flight--;
|
||||
|
||||
/* If the op is not supported by the kernel retry using the thread pool */
|
||||
if (e->res == -EOPNOTSUPP) {
|
||||
uv__fs_post(loop, req);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* io_uring stores error codes as negative numbers, same as libuv. */
|
||||
req->result = e->res;
|
||||
|
||||
@ -1908,7 +1910,6 @@ nocpuinfo:
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
||||
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
|
||||
return 1;
|
||||
@ -1922,14 +1923,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
||||
return exclude_type;
|
||||
return !exclude_type;
|
||||
}
|
||||
#endif
|
||||
|
||||
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
#ifndef HAVE_IFADDRS_H
|
||||
*count = 0;
|
||||
*addresses = NULL;
|
||||
return UV_ENOSYS;
|
||||
#else
|
||||
struct ifaddrs *addrs, *ent;
|
||||
uv_interface_address_t* address;
|
||||
int i;
|
||||
@ -2008,7 +2003,6 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
freeifaddrs(addrs);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
65
deps/libuv/src/unix/pipe.c
vendored
65
deps/libuv/src/unix/pipe.c
vendored
@ -30,6 +30,19 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/* Does the file path contain embedded nul bytes? */
|
||||
static int includes_nul(const char *s, size_t n) {
|
||||
if (n == 0)
|
||||
return 0;
|
||||
#ifdef __linux__
|
||||
/* Accept abstract socket namespace path ("\0/virtual/path"). */
|
||||
s++;
|
||||
n--;
|
||||
#endif
|
||||
return NULL != memchr(s, '\0', n);
|
||||
}
|
||||
|
||||
|
||||
int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
|
||||
uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
|
||||
handle->shutdown_req = NULL;
|
||||
@ -53,6 +66,7 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
char* pipe_fname;
|
||||
int sockfd;
|
||||
int err;
|
||||
socklen_t addrlen;
|
||||
|
||||
pipe_fname = NULL;
|
||||
|
||||
@ -65,11 +79,8 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
if (namelen == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
#ifndef __linux__
|
||||
/* Abstract socket namespace only works on Linux. */
|
||||
if (*name == '\0')
|
||||
if (includes_nul(name, namelen))
|
||||
return UV_EINVAL;
|
||||
#endif
|
||||
|
||||
if (flags & UV_PIPE_NO_TRUNCATE)
|
||||
if (namelen > sizeof(saddr.sun_path))
|
||||
@ -90,10 +101,15 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
* We unlink the file later but abstract sockets disappear
|
||||
* automatically since they're not real file system entities.
|
||||
*/
|
||||
if (*name != '\0') {
|
||||
pipe_fname = uv__strdup(name);
|
||||
if (*name == '\0') {
|
||||
addrlen = offsetof(struct sockaddr_un, sun_path) + namelen;
|
||||
} else {
|
||||
pipe_fname = uv__malloc(namelen + 1);
|
||||
if (pipe_fname == NULL)
|
||||
return UV_ENOMEM;
|
||||
memcpy(pipe_fname, name, namelen);
|
||||
pipe_fname[namelen] = '\0';
|
||||
addrlen = sizeof saddr;
|
||||
}
|
||||
|
||||
err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
@ -105,7 +121,7 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
memcpy(&saddr.sun_path, name, namelen);
|
||||
saddr.sun_family = AF_UNIX;
|
||||
|
||||
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
|
||||
if (bind(sockfd, (struct sockaddr*)&saddr, addrlen)) {
|
||||
err = UV__ERR(errno);
|
||||
/* Convert ENOENT to EACCES for compatibility with Windows. */
|
||||
if (err == UV_ENOENT)
|
||||
@ -117,7 +133,7 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
|
||||
/* Success. */
|
||||
handle->flags |= UV_HANDLE_BOUND;
|
||||
handle->pipe_fname = pipe_fname; /* NULL or a strdup'ed copy. */
|
||||
handle->pipe_fname = pipe_fname; /* NULL or a copy of |name| */
|
||||
handle->io_watcher.fd = sockfd;
|
||||
return 0;
|
||||
|
||||
@ -210,7 +226,22 @@ void uv_pipe_connect(uv_connect_t* req,
|
||||
uv_pipe_t* handle,
|
||||
const char* name,
|
||||
uv_connect_cb cb) {
|
||||
uv_pipe_connect2(req, handle, name, strlen(name), 0, cb);
|
||||
int err;
|
||||
|
||||
err = uv_pipe_connect2(req, handle, name, strlen(name), 0, cb);
|
||||
|
||||
if (err) {
|
||||
handle->delayed_error = err;
|
||||
handle->connect_req = req;
|
||||
|
||||
uv__req_init(handle->loop, req, UV_CONNECT);
|
||||
req->handle = (uv_stream_t*) handle;
|
||||
req->cb = cb;
|
||||
uv__queue_init(&req->queue);
|
||||
|
||||
/* Force callback to run on next tick in case of error. */
|
||||
uv__io_feed(handle->loop, &handle->io_watcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -224,6 +255,7 @@ int uv_pipe_connect2(uv_connect_t* req,
|
||||
int new_sock;
|
||||
int err;
|
||||
int r;
|
||||
socklen_t addrlen;
|
||||
|
||||
if (flags & ~UV_PIPE_NO_TRUNCATE)
|
||||
return UV_EINVAL;
|
||||
@ -234,11 +266,8 @@ int uv_pipe_connect2(uv_connect_t* req,
|
||||
if (namelen == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
#ifndef __linux__
|
||||
/* Abstract socket namespace only works on Linux. */
|
||||
if (*name == '\0')
|
||||
if (includes_nul(name, namelen))
|
||||
return UV_EINVAL;
|
||||
#endif
|
||||
|
||||
if (flags & UV_PIPE_NO_TRUNCATE)
|
||||
if (namelen > sizeof(saddr.sun_path))
|
||||
@ -261,9 +290,13 @@ int uv_pipe_connect2(uv_connect_t* req,
|
||||
memcpy(&saddr.sun_path, name, namelen);
|
||||
saddr.sun_family = AF_UNIX;
|
||||
|
||||
if (*name == '\0')
|
||||
addrlen = offsetof(struct sockaddr_un, sun_path) + namelen;
|
||||
else
|
||||
addrlen = sizeof saddr;
|
||||
|
||||
do {
|
||||
r = connect(uv__stream_fd(handle),
|
||||
(struct sockaddr*)&saddr, sizeof saddr);
|
||||
r = connect(uv__stream_fd(handle), (struct sockaddr*)&saddr, addrlen);
|
||||
}
|
||||
while (r == -1 && errno == EINTR);
|
||||
|
||||
@ -295,7 +328,7 @@ out:
|
||||
handle->connect_req = req;
|
||||
|
||||
uv__req_init(handle->loop, req, UV_CONNECT);
|
||||
req->handle = (uv_stream_t*)handle;
|
||||
req->handle = (uv_stream_t*) handle;
|
||||
req->cb = cb;
|
||||
uv__queue_init(&req->queue);
|
||||
|
||||
|
1
deps/libuv/src/unix/process.c
vendored
1
deps/libuv/src/unix/process.c
vendored
@ -972,6 +972,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
|
||||
UV_PROCESS_SETGID |
|
||||
UV_PROCESS_SETUID |
|
||||
UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME |
|
||||
UV_PROCESS_WINDOWS_HIDE |
|
||||
UV_PROCESS_WINDOWS_HIDE_CONSOLE |
|
||||
UV_PROCESS_WINDOWS_HIDE_GUI |
|
||||
|
117
deps/libuv/src/unix/tcp.c
vendored
117
deps/libuv/src/unix/tcp.c
vendored
@ -30,12 +30,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if defined(__PASE__)
|
||||
#include <as400_protos.h>
|
||||
#define ifaddrs ifaddrs_pase
|
||||
#define getifaddrs Qp2getifaddrs
|
||||
#define freeifaddrs Qp2freeifaddrs
|
||||
#else
|
||||
/* ifaddrs is not implemented on AIX and IBM i PASE */
|
||||
#if !defined(_AIX)
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
@ -225,16 +221,39 @@ static int uv__is_ipv6_link_local(const struct sockaddr* addr) {
|
||||
|
||||
static int uv__ipv6_link_local_scope_id(void) {
|
||||
struct sockaddr_in6* a6;
|
||||
int rv;
|
||||
#if defined(_AIX)
|
||||
/* AIX & IBM i do not have ifaddrs
|
||||
* so fallback to use uv_interface_addresses */
|
||||
uv_interface_address_t* interfaces;
|
||||
uv_interface_address_t* ifa;
|
||||
int count, i;
|
||||
|
||||
if (uv_interface_addresses(&interfaces, &count))
|
||||
return 0;
|
||||
|
||||
rv = 0;
|
||||
|
||||
for (ifa = interfaces; ifa != &interfaces[count]; ifa++) {
|
||||
if (uv__is_ipv6_link_local((struct sockaddr*) &ifa->address)) {
|
||||
rv = ifa->address.address6.sin6_scope_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uv_free_interface_addresses(interfaces, count);
|
||||
|
||||
#else
|
||||
struct ifaddrs* ifa;
|
||||
struct ifaddrs* p;
|
||||
int rv;
|
||||
|
||||
if (getifaddrs(&ifa))
|
||||
return 0;
|
||||
|
||||
for (p = ifa; p != NULL; p = p->ifa_next)
|
||||
if (uv__is_ipv6_link_local(p->ifa_addr))
|
||||
break;
|
||||
if (p->ifa_addr != NULL)
|
||||
if (uv__is_ipv6_link_local(p->ifa_addr))
|
||||
break;
|
||||
|
||||
rv = 0;
|
||||
if (p != NULL) {
|
||||
@ -243,6 +262,8 @@ static int uv__ipv6_link_local_scope_id(void) {
|
||||
}
|
||||
|
||||
freeifaddrs(ifa);
|
||||
#endif /* defined(_AIX) */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -432,26 +453,91 @@ int uv__tcp_nodelay(int fd, int on) {
|
||||
|
||||
|
||||
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
|
||||
int idle;
|
||||
int intvl;
|
||||
int cnt;
|
||||
|
||||
(void) &idle;
|
||||
(void) &intvl;
|
||||
(void) &cnt;
|
||||
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
|
||||
return UV__ERR(errno);
|
||||
|
||||
if (!on)
|
||||
return 0;
|
||||
|
||||
if (delay == 0)
|
||||
return -1;
|
||||
|
||||
#ifdef __sun
|
||||
/* The implementation of TCP keep-alive on Solaris/SmartOS is a bit unusual
|
||||
* compared to other Unix-like systems.
|
||||
* Thus, we need to specialize it on Solaris.
|
||||
*
|
||||
* There are two keep-alive mechanisms on Solaris:
|
||||
* - By default, the first keep-alive probe is sent out after a TCP connection is idle for two hours.
|
||||
* If the peer does not respond to the probe within eight minutes, the TCP connection is aborted.
|
||||
* You can alter the interval for sending out the first probe using the socket option TCP_KEEPALIVE_THRESHOLD
|
||||
* in milliseconds or TCP_KEEPIDLE in seconds.
|
||||
* The system default is controlled by the TCP ndd parameter tcp_keepalive_interval. The minimum value is ten seconds.
|
||||
* The maximum is ten days, while the default is two hours. If you receive no response to the probe,
|
||||
* you can use the TCP_KEEPALIVE_ABORT_THRESHOLD socket option to change the time threshold for aborting a TCP connection.
|
||||
* The option value is an unsigned integer in milliseconds. The value zero indicates that TCP should never time out and
|
||||
* abort the connection when probing. The system default is controlled by the TCP ndd parameter tcp_keepalive_abort_interval.
|
||||
* The default is eight minutes.
|
||||
*
|
||||
* - The second implementation is activated if socket option TCP_KEEPINTVL and/or TCP_KEEPCNT are set.
|
||||
* The time between each consequent probes is set by TCP_KEEPINTVL in seconds.
|
||||
* The minimum value is ten seconds. The maximum is ten days, while the default is two hours.
|
||||
* The TCP connection will be aborted after certain amount of probes, which is set by TCP_KEEPCNT, without receiving response.
|
||||
*/
|
||||
|
||||
idle = delay;
|
||||
/* Kernel expects at least 10 seconds. */
|
||||
if (idle < 10)
|
||||
idle = 10;
|
||||
/* Kernel expects at most 10 days. */
|
||||
if (idle > 10*24*60*60)
|
||||
idle = 10*24*60*60;
|
||||
|
||||
/* `TCP_KEEPIDLE`, `TCP_KEEPINTVL`, and `TCP_KEEPCNT` were not available on Solaris
|
||||
* until version 11.4, but let's take a chance here. */
|
||||
#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT)
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)))
|
||||
return UV__ERR(errno);
|
||||
|
||||
intvl = idle/3;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
|
||||
return UV__ERR(errno);
|
||||
|
||||
cnt = 3;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
|
||||
return UV__ERR(errno);
|
||||
#else
|
||||
/* Fall back to the first implementation of tcp-alive mechanism for older Solaris,
|
||||
* simulate the tcp-alive mechanism on other platforms via `TCP_KEEPALIVE_THRESHOLD` + `TCP_KEEPALIVE_ABORT_THRESHOLD`.
|
||||
*/
|
||||
idle *= 1000; /* kernel expects milliseconds */
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, &idle, sizeof(idle)))
|
||||
return UV__ERR(errno);
|
||||
|
||||
/* Note that the consequent probes will not be sent at equal intervals on Solaris,
|
||||
* but will be sent using the exponential backoff algorithm. */
|
||||
intvl = idle/3;
|
||||
cnt = 3;
|
||||
int time_to_abort = intvl * cnt;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, &time_to_abort, sizeof(time_to_abort)))
|
||||
return UV__ERR(errno);
|
||||
#endif
|
||||
|
||||
#else /* !defined(__sun) */
|
||||
|
||||
#ifdef TCP_KEEPIDLE
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
|
||||
return UV__ERR(errno);
|
||||
/* Solaris/SmartOS, if you don't support keep-alive,
|
||||
* then don't advertise it in your system headers...
|
||||
*/
|
||||
/* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
|
||||
#elif defined(TCP_KEEPALIVE) && !defined(__sun)
|
||||
#elif defined(TCP_KEEPALIVE)
|
||||
/* Darwin/macOS uses TCP_KEEPALIVE in place of TCP_KEEPIDLE. */
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
|
||||
return UV__ERR(errno);
|
||||
#endif
|
||||
@ -468,6 +554,7 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
|
||||
return UV__ERR(errno);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__sun) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
2
deps/libuv/src/win/fs-event.c
vendored
2
deps/libuv/src/win/fs-event.c
vendored
@ -114,7 +114,7 @@ static int uv__split_path(const WCHAR* filename, WCHAR** dir,
|
||||
}
|
||||
}
|
||||
|
||||
*file = wcsdup(filename);
|
||||
*file = _wcsdup(filename);
|
||||
} else {
|
||||
if (dir) {
|
||||
*dir = (WCHAR*)uv__malloc((i + 2) * sizeof(WCHAR));
|
||||
|
4
deps/libuv/src/win/fs.c
vendored
4
deps/libuv/src/win/fs.c
vendored
@ -407,8 +407,8 @@ void fs__open(uv_fs_t* req) {
|
||||
|
||||
/* Obtain the active umask. umask() never fails and returns the previous
|
||||
* umask. */
|
||||
current_umask = umask(0);
|
||||
umask(current_umask);
|
||||
current_umask = _umask(0);
|
||||
_umask(current_umask);
|
||||
|
||||
/* convert flags and mode to CreateFile parameters */
|
||||
switch (flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) {
|
||||
|
105
deps/libuv/src/win/pipe.c
vendored
105
deps/libuv/src/win/pipe.c
vendored
@ -98,6 +98,14 @@ static void eof_timer_destroy(uv_pipe_t* pipe);
|
||||
static void eof_timer_close_cb(uv_handle_t* handle);
|
||||
|
||||
|
||||
/* Does the file path contain embedded nul bytes? */
|
||||
static int includes_nul(const char *s, size_t n) {
|
||||
if (n == 0)
|
||||
return 0;
|
||||
return NULL != memchr(s, '\0', n);
|
||||
}
|
||||
|
||||
|
||||
static void uv__unique_pipe_name(char* ptr, char* name, size_t size) {
|
||||
snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId());
|
||||
}
|
||||
@ -191,7 +199,7 @@ static void close_pipe(uv_pipe_t* pipe) {
|
||||
if (pipe->u.fd == -1)
|
||||
CloseHandle(pipe->handle);
|
||||
else
|
||||
close(pipe->u.fd);
|
||||
_close(pipe->u.fd);
|
||||
|
||||
pipe->u.fd = -1;
|
||||
pipe->handle = INVALID_HANDLE_VALUE;
|
||||
@ -705,6 +713,7 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
uv_loop_t* loop = handle->loop;
|
||||
int i, err;
|
||||
uv_pipe_accept_t* req;
|
||||
char* name_copy;
|
||||
|
||||
if (flags & ~UV_PIPE_NO_TRUNCATE) {
|
||||
return UV_EINVAL;
|
||||
@ -718,16 +727,10 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
if (*name == '\0') {
|
||||
if (includes_nul(name, namelen)) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
if (flags & UV_PIPE_NO_TRUNCATE) {
|
||||
if (namelen > 256) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_BOUND) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
@ -736,14 +739,24 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
name_copy = uv__malloc(namelen + 1);
|
||||
if (name_copy == NULL) {
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(name_copy, name, namelen);
|
||||
name_copy[namelen] = '\0';
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
|
||||
handle->pipe.serv.pending_instances = default_pending_pipe_instances;
|
||||
}
|
||||
|
||||
err = UV_ENOMEM;
|
||||
handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*)
|
||||
uv__malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances);
|
||||
if (!handle->pipe.serv.accept_reqs)
|
||||
return UV_ENOMEM;
|
||||
if (handle->pipe.serv.accept_reqs == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
|
||||
req = &handle->pipe.serv.accept_reqs[i];
|
||||
@ -753,9 +766,14 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
req->next_pending = NULL;
|
||||
}
|
||||
|
||||
err = uv__convert_utf8_to_utf16(name, &handle->name);
|
||||
if (err)
|
||||
return err;
|
||||
/* TODO(bnoordhuis) Add converters that take a |length| parameter. */
|
||||
err = uv__convert_utf8_to_utf16(name_copy, &handle->name);
|
||||
uv__free(name_copy);
|
||||
name_copy = NULL;
|
||||
|
||||
if (err) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
|
||||
@ -767,9 +785,11 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
TRUE)) {
|
||||
err = GetLastError();
|
||||
if (err == ERROR_ACCESS_DENIED) {
|
||||
err = WSAEADDRINUSE; /* Translates to UV_EADDRINUSE. */
|
||||
err = UV_EADDRINUSE;
|
||||
} else if (err == ERROR_PATH_NOT_FOUND || err == ERROR_INVALID_NAME) {
|
||||
err = WSAEACCES; /* Translates to UV_EACCES. */
|
||||
err = UV_EACCES;
|
||||
} else {
|
||||
err = uv_translate_sys_error(err);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
@ -781,10 +801,13 @@ int uv_pipe_bind2(uv_pipe_t* handle,
|
||||
return 0;
|
||||
|
||||
error:
|
||||
uv__free(handle->pipe.serv.accept_reqs);
|
||||
uv__free(handle->name);
|
||||
uv__free(name_copy);
|
||||
handle->pipe.serv.accept_reqs = NULL;
|
||||
handle->name = NULL;
|
||||
|
||||
return uv_translate_sys_error(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -834,7 +857,19 @@ void uv_pipe_connect(uv_connect_t* req,
|
||||
uv_pipe_t* handle,
|
||||
const char* name,
|
||||
uv_connect_cb cb) {
|
||||
uv_pipe_connect2(req, handle, name, strlen(name), 0, cb);
|
||||
uv_loop_t* loop;
|
||||
int err;
|
||||
|
||||
err = uv_pipe_connect2(req, handle, name, strlen(name), 0, cb);
|
||||
|
||||
if (err) {
|
||||
loop = handle->loop;
|
||||
/* Make this req pending reporting an error. */
|
||||
SET_REQ_ERROR(req, err);
|
||||
uv__insert_pending_req(loop, (uv_req_t*) req);
|
||||
handle->reqs_pending++;
|
||||
REGISTER_HANDLE_REQ(loop, handle, req);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -844,11 +879,20 @@ int uv_pipe_connect2(uv_connect_t* req,
|
||||
size_t namelen,
|
||||
unsigned int flags,
|
||||
uv_connect_cb cb) {
|
||||
uv_loop_t* loop = handle->loop;
|
||||
uv_loop_t* loop;
|
||||
int err;
|
||||
size_t nameSize;
|
||||
HANDLE pipeHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD duplex_flags;
|
||||
char* name_copy;
|
||||
|
||||
loop = handle->loop;
|
||||
UV_REQ_INIT(req, UV_CONNECT);
|
||||
req->handle = (uv_stream_t*) handle;
|
||||
req->cb = cb;
|
||||
req->u.connect.pipeHandle = INVALID_HANDLE_VALUE;
|
||||
req->u.connect.duplex_flags = 0;
|
||||
req->u.connect.name = NULL;
|
||||
|
||||
if (flags & ~UV_PIPE_NO_TRUNCATE) {
|
||||
return UV_EINVAL;
|
||||
@ -862,22 +906,17 @@ int uv_pipe_connect2(uv_connect_t* req,
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
if (*name == '\0') {
|
||||
if (includes_nul(name, namelen)) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
if (flags & UV_PIPE_NO_TRUNCATE) {
|
||||
if (namelen > 256) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
name_copy = uv__malloc(namelen + 1);
|
||||
if (name_copy == NULL) {
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
|
||||
UV_REQ_INIT(req, UV_CONNECT);
|
||||
req->handle = (uv_stream_t*) handle;
|
||||
req->cb = cb;
|
||||
req->u.connect.pipeHandle = INVALID_HANDLE_VALUE;
|
||||
req->u.connect.duplex_flags = 0;
|
||||
req->u.connect.name = NULL;
|
||||
memcpy(name_copy, name, namelen);
|
||||
name_copy[namelen] = '\0';
|
||||
|
||||
if (handle->flags & UV_HANDLE_PIPESERVER) {
|
||||
err = ERROR_INVALID_PARAMETER;
|
||||
@ -889,7 +928,11 @@ int uv_pipe_connect2(uv_connect_t* req,
|
||||
}
|
||||
uv__pipe_connection_init(handle);
|
||||
|
||||
err = uv__convert_utf8_to_utf16(name, &handle->name);
|
||||
/* TODO(bnoordhuis) Add converters that take a |length| parameter. */
|
||||
err = uv__convert_utf8_to_utf16(name_copy, &handle->name);
|
||||
uv__free(name_copy);
|
||||
name_copy = NULL;
|
||||
|
||||
if (err) {
|
||||
err = ERROR_NO_UNICODE_TRANSLATION;
|
||||
goto error;
|
||||
@ -935,6 +978,8 @@ int uv_pipe_connect2(uv_connect_t* req,
|
||||
return 0;
|
||||
|
||||
error:
|
||||
uv__free(name_copy);
|
||||
|
||||
if (handle->name) {
|
||||
uv__free(handle->name);
|
||||
handle->name = NULL;
|
||||
|
72
deps/libuv/src/win/process.c
vendored
72
deps/libuv/src/win/process.c
vendored
@ -26,7 +26,7 @@
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#include <wchar.h>
|
||||
#include <malloc.h> /* alloca */
|
||||
#include <malloc.h> /* _alloca */
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
@ -304,8 +304,9 @@ static WCHAR* path_search_walk_ext(const WCHAR *dir,
|
||||
* - If there's really only a filename, check the current directory for file,
|
||||
* then search all path directories.
|
||||
*
|
||||
* - If filename specified has *any* extension, search for the file with the
|
||||
* specified extension first.
|
||||
* - If filename specified has *any* extension, or already contains a path
|
||||
* and the UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME flag is specified,
|
||||
* search for the file with the exact specified filename first.
|
||||
*
|
||||
* - If the literal filename is not found in a directory, try *appending*
|
||||
* (not replacing) .com first and then .exe.
|
||||
@ -331,7 +332,8 @@ static WCHAR* path_search_walk_ext(const WCHAR *dir,
|
||||
*/
|
||||
static WCHAR* search_path(const WCHAR *file,
|
||||
WCHAR *cwd,
|
||||
const WCHAR *path) {
|
||||
const WCHAR *path,
|
||||
unsigned int flags) {
|
||||
int file_has_dir;
|
||||
WCHAR* result = NULL;
|
||||
WCHAR *file_name_start;
|
||||
@ -372,16 +374,18 @@ static WCHAR* search_path(const WCHAR *file,
|
||||
file, file_name_start - file,
|
||||
file_name_start, file_len - (file_name_start - file),
|
||||
cwd, cwd_len,
|
||||
name_has_ext);
|
||||
name_has_ext || (flags & UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME));
|
||||
|
||||
} else {
|
||||
dir_end = path;
|
||||
|
||||
/* The file is really only a name; look in cwd first, then scan path */
|
||||
result = path_search_walk_ext(L"", 0,
|
||||
file, file_len,
|
||||
cwd, cwd_len,
|
||||
name_has_ext);
|
||||
if (NeedCurrentDirectoryForExePathW(L"")) {
|
||||
/* The file is really only a name; look in cwd first, then scan path */
|
||||
result = path_search_walk_ext(L"", 0,
|
||||
file, file_len,
|
||||
cwd, cwd_len,
|
||||
name_has_ext);
|
||||
}
|
||||
|
||||
while (result == NULL) {
|
||||
if (dir_end == NULL || *dir_end == L'\0') {
|
||||
@ -509,7 +513,7 @@ WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) {
|
||||
}
|
||||
}
|
||||
target[0] = L'\0';
|
||||
wcsrev(start);
|
||||
_wcsrev(start);
|
||||
*(target++) = L'"';
|
||||
return target;
|
||||
}
|
||||
@ -613,8 +617,8 @@ int env_strncmp(const wchar_t* a, int na, const wchar_t* b) {
|
||||
assert(b_eq);
|
||||
nb = b_eq - b;
|
||||
|
||||
A = alloca((na+1) * sizeof(wchar_t));
|
||||
B = alloca((nb+1) * sizeof(wchar_t));
|
||||
A = _alloca((na+1) * sizeof(wchar_t));
|
||||
B = _alloca((nb+1) * sizeof(wchar_t));
|
||||
|
||||
r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na);
|
||||
assert(r==na);
|
||||
@ -691,7 +695,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
||||
if (dst_copy == NULL && env_len > 0) {
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
env_copy = alloca(env_block_count * sizeof(WCHAR*));
|
||||
env_copy = _alloca(env_block_count * sizeof(WCHAR*));
|
||||
|
||||
ptr = dst_copy;
|
||||
ptr_copy = env_copy;
|
||||
@ -933,6 +937,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
|
||||
UV_PROCESS_SETGID |
|
||||
UV_PROCESS_SETUID |
|
||||
UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME |
|
||||
UV_PROCESS_WINDOWS_HIDE |
|
||||
UV_PROCESS_WINDOWS_HIDE_CONSOLE |
|
||||
UV_PROCESS_WINDOWS_HIDE_GUI |
|
||||
@ -1012,7 +1017,8 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
application_path = search_path(application,
|
||||
cwd,
|
||||
path);
|
||||
path,
|
||||
options->flags);
|
||||
if (application_path == NULL) {
|
||||
/* Not found. */
|
||||
err = ERROR_FILE_NOT_FOUND;
|
||||
@ -1210,9 +1216,18 @@ static int uv__kill(HANDLE process_handle, int signum) {
|
||||
(PVOID) dump_folder,
|
||||
&dump_folder_len);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
/* Workaround for missing uuid.dll on MinGW. */
|
||||
static const GUID FOLDERID_LocalAppData_libuv = {
|
||||
0xf1b32785, 0x6fba, 0x4fcf,
|
||||
{0x9d, 0x55, 0x7b, 0x8e, 0x7f, 0x15, 0x70, 0x91}
|
||||
};
|
||||
|
||||
/* Default value for `dump_folder` is `%LOCALAPPDATA%\CrashDumps`. */
|
||||
WCHAR* localappdata;
|
||||
SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, NULL, &localappdata);
|
||||
SHGetKnownFolderPath(&FOLDERID_LocalAppData_libuv,
|
||||
0,
|
||||
NULL,
|
||||
&localappdata);
|
||||
_snwprintf_s(dump_folder,
|
||||
sizeof(dump_folder),
|
||||
_TRUNCATE,
|
||||
@ -1292,7 +1307,6 @@ static int uv__kill(HANDLE process_handle, int signum) {
|
||||
case SIGINT: {
|
||||
/* Unconditionally terminate the process. On Windows, killed processes
|
||||
* normally return 1. */
|
||||
DWORD status;
|
||||
int err;
|
||||
|
||||
if (TerminateProcess(process_handle, 1))
|
||||
@ -1302,8 +1316,7 @@ static int uv__kill(HANDLE process_handle, int signum) {
|
||||
* TerminateProcess will fail with ERROR_ACCESS_DENIED. */
|
||||
err = GetLastError();
|
||||
if (err == ERROR_ACCESS_DENIED &&
|
||||
GetExitCodeProcess(process_handle, &status) &&
|
||||
status != STILL_ACTIVE) {
|
||||
WaitForSingleObject(process_handle, 0) == WAIT_OBJECT_0) {
|
||||
return UV_ESRCH;
|
||||
}
|
||||
|
||||
@ -1312,15 +1325,16 @@ static int uv__kill(HANDLE process_handle, int signum) {
|
||||
|
||||
case 0: {
|
||||
/* Health check: is the process still alive? */
|
||||
DWORD status;
|
||||
|
||||
if (!GetExitCodeProcess(process_handle, &status))
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
|
||||
if (status != STILL_ACTIVE)
|
||||
return UV_ESRCH;
|
||||
|
||||
return 0;
|
||||
switch (WaitForSingleObject(process_handle, 0)) {
|
||||
case WAIT_OBJECT_0:
|
||||
return UV_ESRCH;
|
||||
case WAIT_FAILED:
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
case WAIT_TIMEOUT:
|
||||
return 0;
|
||||
default:
|
||||
return UV_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
@ -1355,7 +1369,7 @@ int uv_kill(int pid, int signum) {
|
||||
if (pid == 0) {
|
||||
process_handle = GetCurrentProcess();
|
||||
} else {
|
||||
process_handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
|
||||
process_handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
|
||||
FALSE,
|
||||
pid);
|
||||
}
|
||||
|
4
deps/libuv/src/win/tty.c
vendored
4
deps/libuv/src/win/tty.c
vendored
@ -695,7 +695,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
|
||||
|
||||
DWORD records_left, records_read;
|
||||
uv_buf_t buf;
|
||||
off_t buf_used;
|
||||
_off_t buf_used;
|
||||
|
||||
assert(handle->type == UV_TTY);
|
||||
assert(handle->flags & UV_HANDLE_TTY_READABLE);
|
||||
@ -2246,7 +2246,7 @@ void uv__tty_close(uv_tty_t* handle) {
|
||||
if (handle->u.fd == -1)
|
||||
CloseHandle(handle->handle);
|
||||
else
|
||||
close(handle->u.fd);
|
||||
_close(handle->u.fd);
|
||||
|
||||
handle->u.fd = -1;
|
||||
handle->handle = INVALID_HANDLE_VALUE;
|
||||
|
42
deps/libuv/src/win/util.c
vendored
42
deps/libuv/src/win/util.c
vendored
@ -1466,6 +1466,48 @@ int uv_os_setpriority(uv_pid_t pid, int priority) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int uv_thread_getpriority(uv_thread_t tid, int* priority) {
|
||||
int r;
|
||||
|
||||
if (priority == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
r = GetThreadPriority(tid);
|
||||
if (r == THREAD_PRIORITY_ERROR_RETURN)
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
|
||||
*priority = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uv_thread_setpriority(uv_thread_t tid, int priority) {
|
||||
int r;
|
||||
|
||||
switch (priority) {
|
||||
case UV_THREAD_PRIORITY_HIGHEST:
|
||||
r = SetThreadPriority(tid, THREAD_PRIORITY_HIGHEST);
|
||||
break;
|
||||
case UV_THREAD_PRIORITY_ABOVE_NORMAL:
|
||||
r = SetThreadPriority(tid, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
break;
|
||||
case UV_THREAD_PRIORITY_NORMAL:
|
||||
r = SetThreadPriority(tid, THREAD_PRIORITY_NORMAL);
|
||||
break;
|
||||
case UV_THREAD_PRIORITY_BELOW_NORMAL:
|
||||
r = SetThreadPriority(tid, THREAD_PRIORITY_BELOW_NORMAL);
|
||||
break;
|
||||
case UV_THREAD_PRIORITY_LOWEST:
|
||||
r = SetThreadPriority(tid, THREAD_PRIORITY_LOWEST);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uv_os_uname(uv_utsname_t* buffer) {
|
||||
/* Implementation loosely based on
|
||||
|
Reference in New Issue
Block a user