aboutsummaryrefslogtreecommitdiff
path: root/deps/uv/src/unix
diff options
context:
space:
mode:
authorTimothy J Fontaine <tjfontaine@gmail.com>2014-02-26 18:08:30 -0800
committerTimothy J Fontaine <tjfontaine@gmail.com>2014-02-26 18:08:30 -0800
commitcd08c8a0e5e99ed4933b87fc5e188afcd4299f73 (patch)
treec05e93d47f89df1f7a782ee9c70bb2c97d557cd4 /deps/uv/src/unix
parentf3189ace6b5e31a874df421ac2f74da0e77cb14d (diff)
downloadandroid-node-v8-cd08c8a0e5e99ed4933b87fc5e188afcd4299f73.tar.gz
android-node-v8-cd08c8a0e5e99ed4933b87fc5e188afcd4299f73.tar.bz2
android-node-v8-cd08c8a0e5e99ed4933b87fc5e188afcd4299f73.zip
uv: Upgrade to v0.11.21
Diffstat (limited to 'deps/uv/src/unix')
-rw-r--r--deps/uv/src/unix/core.c32
-rw-r--r--deps/uv/src/unix/fs.c209
-rw-r--r--deps/uv/src/unix/fsevents.c2
-rw-r--r--deps/uv/src/unix/internal.h9
-rw-r--r--deps/uv/src/unix/kqueue.c10
-rw-r--r--deps/uv/src/unix/linux-core.c24
-rw-r--r--deps/uv/src/unix/linux-inotify.c6
-rw-r--r--deps/uv/src/unix/linux-syscalls.c36
-rw-r--r--deps/uv/src/unix/linux-syscalls.h2
-rw-r--r--deps/uv/src/unix/loop.c54
-rw-r--r--deps/uv/src/unix/pipe.c32
-rw-r--r--deps/uv/src/unix/process.c20
-rw-r--r--deps/uv/src/unix/stream.c16
-rw-r--r--deps/uv/src/unix/sunos.c24
-rw-r--r--deps/uv/src/unix/tcp.c4
-rw-r--r--deps/uv/src/unix/timer.c54
-rw-r--r--deps/uv/src/unix/udp.c25
17 files changed, 476 insertions, 83 deletions
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index df2a5f8042..a84304497c 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -37,6 +37,7 @@
#include <arpa/inet.h>
#include <limits.h> /* INT_MAX, PATH_MAX */
#include <sys/uio.h> /* writev */
+#include <sys/resource.h> /* getrusage */
#ifdef __linux__
# include <sys/ioctl.h>
@@ -785,3 +786,34 @@ int uv__io_active(const uv__io_t* w, unsigned int events) {
assert(0 != events);
return 0 != (w->pevents & events);
}
+
+
+int uv_getrusage(uv_rusage_t* rusage) {
+ struct rusage usage;
+
+ if (getrusage(RUSAGE_SELF, &usage))
+ return -errno;
+
+ rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
+ rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec;
+
+ rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec;
+ rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec;
+
+ rusage->ru_maxrss = usage.ru_maxrss;
+ rusage->ru_ixrss = usage.ru_ixrss;
+ rusage->ru_idrss = usage.ru_idrss;
+ rusage->ru_isrss = usage.ru_isrss;
+ rusage->ru_minflt = usage.ru_minflt;
+ rusage->ru_majflt = usage.ru_majflt;
+ rusage->ru_nswap = usage.ru_nswap;
+ rusage->ru_inblock = usage.ru_inblock;
+ rusage->ru_oublock = usage.ru_oublock;
+ rusage->ru_msgsnd = usage.ru_msgsnd;
+ rusage->ru_msgrcv = usage.ru_msgrcv;
+ rusage->ru_nsignals = usage.ru_nsignals;
+ rusage->ru_nvcsw = usage.ru_nvcsw;
+ rusage->ru_nivcsw = usage.ru_nivcsw;
+
+ return 0;
+}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 1aa6539cb4..b06f992dc7 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -44,10 +44,34 @@
#include <utime.h>
#include <poll.h>
+#if defined(__DragonFly__) || \
+ defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || \
+ defined(__NetBSD__)
+# define HAVE_PREADV 1
+#elif defined(__linux__)
+# include <linux/version.h>
+# if defined(__GLIBC_PREREQ)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) && \
+ __GLIBC_PREREQ(2,10)
+# define HAVE_PREADV 1
+# else
+# define HAVE_PREADV 0
+# endif
+# else
+# define HAVE_PREADV 0
+# endif
+#else
+# define HAVE_PREADV 0
+#endif
+
#if defined(__linux__) || defined(__sun)
# include <sys/sendfile.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
# include <sys/socket.h>
+#endif
+
+#if HAVE_PREADV || defined(__APPLE__)
# include <sys/uio.h>
#endif
@@ -191,10 +215,59 @@ skip:
static ssize_t uv__fs_read(uv_fs_t* req) {
+ ssize_t result;
+
if (req->off < 0)
- return read(req->file, req->buf, req->len);
- else
- return pread(req->file, req->buf, req->len, req->off);
+ result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
+ else {
+#if HAVE_PREADV
+ result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
+#else
+# if defined(__linux__)
+ static int no_preadv;
+ if (no_preadv)
+# endif
+ {
+ off_t nread;
+ size_t index;
+
+# if defined(__linux__)
+ retry:
+# endif
+ nread = 0;
+ index = 0;
+ result = 1;
+ do {
+ if (req->bufs[index].len > 0) {
+ result = pread(req->file,
+ req->bufs[index].base,
+ req->bufs[index].len,
+ req->off + nread);
+ if (result > 0)
+ nread += result;
+ }
+ index++;
+ } while (index < req->nbufs && result > 0);
+ if (nread > 0)
+ result = nread;
+ }
+# if defined(__linux__)
+ else {
+ result = uv__preadv(req->file,
+ (struct iovec*)req->bufs,
+ req->nbufs,
+ req->off);
+ if (result == -1 && errno == ENOSYS) {
+ no_preadv = 1;
+ goto retry;
+ }
+ }
+# endif
+#endif
+ }
+ if (req->bufs != req->bufsml)
+ free(req->bufs);
+ return result;
}
@@ -306,7 +379,7 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
int out_fd;
char buf[8192];
- len = req->len;
+ len = req->bufsml[0].len;
in_fd = req->flags;
out_fd = req->file;
offset = req->off;
@@ -419,7 +492,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
ssize_t r;
off = req->off;
- r = sendfile(out_fd, in_fd, &off, req->len);
+ r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);
/* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
* it still writes out data. Fortunately, we can detect it by checking if
@@ -453,11 +526,11 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
#if defined(__FreeBSD__)
len = 0;
- r = sendfile(in_fd, out_fd, req->off, req->len, NULL, &len, 0);
+ r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
#else
/* The darwin sendfile takes len as an input for the length to send,
* so make sure to initialize it with the caller's value. */
- len = req->len;
+ len = req->bufsml[0].len;
r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
#endif
@@ -507,14 +580,61 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
#endif
if (req->off < 0)
- r = write(req->file, req->buf, req->len);
- else
- r = pwrite(req->file, req->buf, req->len, req->off);
+ r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
+ else {
+#if HAVE_PREADV
+ r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
+#else
+# if defined(__linux__)
+ static int no_pwritev;
+ if (no_pwritev)
+# endif
+ {
+ off_t written;
+ size_t index;
+
+# if defined(__linux__)
+ retry:
+# endif
+ written = 0;
+ index = 0;
+ r = 0;
+ do {
+ if (req->bufs[index].len > 0) {
+ r = pwrite(req->file,
+ req->bufs[index].base,
+ req->bufs[index].len,
+ req->off + written);
+ if (r > 0)
+ written += r;
+ }
+ index++;
+ } while (index < req->nbufs && r >= 0);
+ if (written > 0)
+ r = written;
+ }
+# if defined(__linux__)
+ else {
+ r = uv__pwritev(req->file,
+ (struct iovec*) req->bufs,
+ req->nbufs,
+ req->off);
+ if (r == -1 && errno == ENOSYS) {
+ no_pwritev = 1;
+ goto retry;
+ }
+ }
+# endif
+#endif
+ }
#if defined(__APPLE__)
pthread_mutex_unlock(&lock);
#endif
+ if (req->bufs != req->bufsml)
+ free(req->bufs);
+
return r;
}
@@ -608,6 +728,9 @@ static void uv__fs_work(struct uv__work* w) {
int retry_on_eintr;
uv_fs_t* req;
ssize_t r;
+#ifdef O_CLOEXEC
+ static int no_cloexec_support;
+#endif /* O_CLOEXEC */
req = container_of(w, uv_fs_t, work_req);
retry_on_eintr = !(req->fs_type == UV_FS_CLOSE);
@@ -634,7 +757,6 @@ static void uv__fs_work(struct uv__work* w) {
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
X(LINK, link(req->path, req->new_path));
X(MKDIR, mkdir(req->path, req->mode));
- X(OPEN, open(req->path, req->flags, req->mode));
X(READ, uv__fs_read(req));
X(READDIR, uv__fs_readdir(req));
X(READLINK, uv__fs_readlink(req));
@@ -646,6 +768,35 @@ static void uv__fs_work(struct uv__work* w) {
X(UNLINK, unlink(req->path));
X(UTIME, uv__fs_utime(req));
X(WRITE, uv__fs_write(req));
+ case UV_FS_OPEN:
+#ifdef O_CLOEXEC
+ /* Try O_CLOEXEC before entering locks */
+ if (!no_cloexec_support) {
+ r = open(req->path, req->flags | O_CLOEXEC, req->mode);
+ if (r >= 0)
+ break;
+ if (errno != EINVAL)
+ break;
+ no_cloexec_support = 1;
+ }
+#endif /* O_CLOEXEC */
+ if (req->cb != NULL)
+ uv_rwlock_rdlock(&req->loop->cloexec_lock);
+ r = open(req->path, req->flags, req->mode);
+
+ /*
+ * In case of failure `uv__cloexec` will leave error in `errno`,
+ * so it is enough to just set `r` to `-1`.
+ */
+ if (r >= 0 && uv__cloexec(r, 1) != 0) {
+ r = uv__close(r);
+ if (r != 0 && r != -EINPROGRESS)
+ abort();
+ r = -1;
+ }
+ if (req->cb != NULL)
+ uv_rwlock_rdunlock(&req->loop->cloexec_lock);
+ break;
default: abort();
}
@@ -834,14 +985,23 @@ int uv_fs_open(uv_loop_t* loop,
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
uv_file file,
- void* buf,
- size_t len,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
INIT(READ);
req->file = file;
- req->buf = buf;
- req->len = len;
+
+ req->nbufs = nbufs;
+ req->bufs = req->bufsml;
+ if (nbufs > ARRAY_SIZE(req->bufsml))
+ req->bufs = malloc(nbufs * sizeof(*bufs));
+
+ if (req->bufs == NULL)
+ return -ENOMEM;
+
+ memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
+
req->off = off;
POST;
}
@@ -898,7 +1058,7 @@ int uv_fs_sendfile(uv_loop_t* loop,
req->flags = in_fd; /* hack */
req->file = out_fd;
req->off = off;
- req->len = len;
+ req->bufsml[0].len = len;
POST;
}
@@ -947,14 +1107,23 @@ int uv_fs_utime(uv_loop_t* loop,
int uv_fs_write(uv_loop_t* loop,
uv_fs_t* req,
uv_file file,
- const void* buf,
- size_t len,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
INIT(WRITE);
req->file = file;
- req->buf = (void*) buf;
- req->len = len;
+
+ req->nbufs = nbufs;
+ req->bufs = req->bufsml;
+ if (nbufs > ARRAY_SIZE(req->bufsml))
+ req->bufs = malloc(nbufs * sizeof(*bufs));
+
+ if (req->bufs == NULL)
+ return -ENOMEM;
+
+ memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
+
req->off = off;
POST;
}
diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c
index 7faa1562a6..f9c3a400fb 100644
--- a/deps/uv/src/unix/fsevents.c
+++ b/deps/uv/src/unix/fsevents.c
@@ -795,7 +795,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
return err;
/* Get absolute path to file */
- handle->realpath = realpath(handle->filename, NULL);
+ handle->realpath = realpath(handle->path, NULL);
if (handle->realpath == NULL)
return -errno;
handle->realpath_len = strlen(handle->realpath);
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 0ea82b51a0..4a4656a562 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -27,6 +27,7 @@
#include <assert.h>
#include <stdlib.h> /* abort */
#include <string.h> /* strrchr */
+#include <fcntl.h> /* O_CLOEXEC, may be */
#if defined(__STRICT_ANSI__)
# define inline __inline
@@ -111,6 +112,14 @@
# define UV__POLLHUP 8
#endif
+#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
+/*
+ * It may be that we are just missing `__POSIX_VISIBLE >= 200809`.
+ * Try using fixed value const and give up, if it doesn't work
+ */
+# define O_CLOEXEC 0x00100000
+#endif
+
/* handle flags */
enum {
UV_CLOSING = 0x01, /* uv_close() called but not finished. */
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index f86f291fc0..5a25e117c9 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -331,7 +331,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
- const char* filename,
+ const char* path,
unsigned int flags) {
#if defined(__APPLE__)
struct stat statbuf;
@@ -342,13 +342,13 @@ int uv_fs_event_start(uv_fs_event_t* handle,
return -EINVAL;
/* TODO open asynchronously - but how do we report back errors? */
- fd = open(filename, O_RDONLY);
+ fd = open(path, O_RDONLY);
if (fd == -1)
return -errno;
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
- handle->filename = strdup(filename);
+ handle->path = strdup(path);
handle->cb = cb;
#if defined(__APPLE__)
@@ -388,8 +388,8 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN);
#endif /* defined(__APPLE__) */
- free(handle->filename);
- handle->filename = NULL;
+ free(handle->path);
+ handle->path = NULL;
uv__close(handle->event_watcher.fd);
handle->event_watcher.fd = -1;
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index 4f11d88eed..97a5126f6a 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -107,6 +107,7 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct uv__epoll_event* events;
+ struct uv__epoll_event dummy;
uintptr_t i;
uintptr_t nfds;
@@ -114,13 +115,20 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
events = (struct uv__epoll_event*) loop->watchers[loop->nwatchers];
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
- if (events == NULL)
- return;
-
- /* Invalidate events with same file descriptor */
- for (i = 0; i < nfds; i++)
- if ((int) events[i].data == fd)
- events[i].data = -1;
+ if (events != NULL)
+ /* Invalidate events with same file descriptor */
+ for (i = 0; i < nfds; i++)
+ if ((int) events[i].data == fd)
+ events[i].data = -1;
+
+ /* Remove the file descriptor from the epoll.
+ * This avoids a problem where the same file description remains open
+ * in another process, causing repeated junk epoll events.
+ *
+ * We pass in a dummy epoll_event, to work around a bug in old kernels.
+ */
+ if (loop->backend_fd >= 0)
+ uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy);
}
@@ -638,7 +646,7 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
unsigned int n;
int r = sscanf(buf, "cpu%u ", &n);
assert(r == 1);
- (void) r; // silence build warning
+ (void) r; /* silence build warning */
for (len = sizeof("cpu0"); n /= 10; len++);
}
diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c
index 7641f383c4..20bc173554 100644
--- a/deps/uv/src/unix/linux-inotify.c
+++ b/deps/uv/src/unix/linux-inotify.c
@@ -124,7 +124,7 @@ static void uv__inotify_read(uv_loop_t* loop,
const char* path;
ssize_t size;
const char *p;
- /* needs to be large enough for sizeof(inotify_event) + strlen(filename) */
+ /* needs to be large enough for sizeof(inotify_event) + strlen(path) */
char buf[4096];
while (1) {
@@ -219,7 +219,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
no_insert:
uv__handle_start(handle);
QUEUE_INSERT_TAIL(&w->watchers, &handle->watchers);
- handle->filename = w->path;
+ handle->path = w->path;
handle->cb = cb;
handle->wd = wd;
@@ -237,7 +237,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
assert(w != NULL);
handle->wd = -1;
- handle->filename = NULL;
+ handle->path = NULL;
uv__handle_stop(handle);
QUEUE_REMOVE(&handle->watchers);
diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c
index 06cc5943cf..c9cc44d8cd 100644
--- a/deps/uv/src/unix/linux-syscalls.c
+++ b/deps/uv/src/unix/linux-syscalls.c
@@ -199,6 +199,26 @@
# endif
#endif /* __NR_utimensat */
+#ifndef __NR_preadv
+# if defined(__x86_64__)
+# define __NR_preadv 295
+# elif defined(__i386__)
+# define __NR_preadv 333
+# elif defined(__arm__)
+# define __NR_preadv (UV_SYSCALL_BASE + 361)
+# endif
+#endif /* __NR_preadv */
+
+#ifndef __NR_pwritev
+# if defined(__x86_64__)
+# define __NR_pwritev 296
+# elif defined(__i386__)
+# define __NR_pwritev 334
+# elif defined(__arm__)
+# define __NR_pwritev (UV_SYSCALL_BASE + 362)
+# endif
+#endif /* __NR_pwritev */
+
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
#if defined(__i386__)
@@ -386,3 +406,19 @@ int uv__utimesat(int dirfd,
return errno = ENOSYS, -1;
#endif
}
+
+ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
+#if defined(__NR_preadv)
+ return syscall(__NR_preadv, fd, iov, iovcnt, offset);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
+#if defined(__NR_pwritev)
+ return syscall(__NR_pwritev, fd, iov, iovcnt, offset);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h
index 1ad9518548..6d9ec9f22c 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -147,5 +147,7 @@ int uv__utimesat(int dirfd,
const char* path,
const struct timespec times[2],
int flags);
+ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
#endif /* UV_LINUX_SYSCALL_H_ */
diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c
index 94a5c03819..52c9328e75 100644
--- a/deps/uv/src/unix/loop.c
+++ b/deps/uv/src/unix/loop.c
@@ -22,12 +22,13 @@
#include "uv.h"
#include "tree.h"
#include "internal.h"
+#include "heap-inl.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int uv__loop_init(uv_loop_t* loop, int default_loop);
-static void uv__loop_delete(uv_loop_t* loop);
+static void uv__loop_close(uv_loop_t* loop);
static uv_loop_t default_loop_struct;
static uv_loop_t* default_loop_ptr;
@@ -45,6 +46,31 @@ uv_loop_t* uv_default_loop(void) {
}
+int uv_loop_init(uv_loop_t* loop) {
+ return uv__loop_init(loop, /* default_loop? */ 0);
+}
+
+
+int uv_loop_close(uv_loop_t* loop) {
+ QUEUE* q;
+ uv_handle_t* h;
+ if (!QUEUE_EMPTY(&(loop)->active_reqs))
+ return -EBUSY;
+ QUEUE_FOREACH(q, &loop->handle_queue) {
+ h = QUEUE_DATA(q, uv_handle_t, handle_queue);
+ if (!(h->flags & UV__HANDLE_INTERNAL))
+ return -EBUSY;
+ }
+ uv__loop_close(loop);
+#ifndef NDEBUG
+ memset(loop, -1, sizeof(*loop));
+#endif
+ if (loop == default_loop_ptr)
+ default_loop_ptr = NULL;
+ return 0;
+}
+
+
uv_loop_t* uv_loop_new(void) {
uv_loop_t* loop;
@@ -52,7 +78,7 @@ uv_loop_t* uv_loop_new(void) {
if (loop == NULL)
return NULL;
- if (uv__loop_init(loop, /* default_loop? */ 0)) {
+ if (uv_loop_init(loop)) {
free(loop);
return NULL;
}
@@ -62,13 +88,10 @@ uv_loop_t* uv_loop_new(void) {
void uv_loop_delete(uv_loop_t* loop) {
- uv__loop_delete(loop);
-#ifndef NDEBUG
- memset(loop, -1, sizeof(*loop));
-#endif
- if (loop == default_loop_ptr)
- default_loop_ptr = NULL;
- else
+ uv_loop_t* default_loop;
+ default_loop = default_loop_ptr;
+ assert(uv_loop_close(loop) == 0);
+ if (loop != default_loop)
free(loop);
}
@@ -80,7 +103,7 @@ static int uv__loop_init(uv_loop_t* loop, int default_loop) {
uv__signal_global_once_init();
memset(loop, 0, sizeof(*loop));
- RB_INIT(&loop->timer_handles);
+ heap_init((struct heap*) &loop->timer_heap);
QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->active_reqs);
QUEUE_INIT(&loop->idle_handles);
@@ -117,6 +140,9 @@ static int uv__loop_init(uv_loop_t* loop, int default_loop) {
for (i = 0; i < ARRAY_SIZE(loop->process_handles); i++)
QUEUE_INIT(loop->process_handles + i);
+ if (uv_rwlock_init(&loop->cloexec_lock))
+ abort();
+
if (uv_mutex_init(&loop->wq_mutex))
abort();
@@ -130,7 +156,7 @@ static int uv__loop_init(uv_loop_t* loop, int default_loop) {
}
-static void uv__loop_delete(uv_loop_t* loop) {
+static 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);
@@ -151,6 +177,12 @@ static void uv__loop_delete(uv_loop_t* loop) {
uv_mutex_unlock(&loop->wq_mutex);
uv_mutex_destroy(&loop->wq_mutex);
+ /*
+ * Note that all thread pool stuff is finished at this point and
+ * it is safe to just destroy rw lock
+ */
+ uv_rwlock_destroy(&loop->cloexec_lock);
+
#if 0
assert(QUEUE_EMPTY(&loop->pending_queue));
assert(QUEUE_EMPTY(&loop->watcher_queue));
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index fd4afb6370..34c118b773 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -212,5 +212,37 @@ out:
}
+int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) {
+ struct sockaddr_un sa;
+ socklen_t addrlen;
+ int err;
+
+ addrlen = sizeof(sa);
+ memset(&sa, 0, addrlen);
+ err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
+ if (err < 0) {
+ *len = 0;
+ return -errno;
+ }
+
+ if (sa.sun_path[0] == 0)
+ /* Linux abstract namespace */
+ addrlen -= offsetof(struct sockaddr_un, sun_path);
+ else
+ addrlen = strlen(sa.sun_path) + 1;
+
+
+ if (addrlen > *len) {
+ *len = addrlen;
+ return UV_ENOBUFS;
+ }
+
+ memcpy(buf, sa.sun_path, addrlen);
+ *len = addrlen;
+
+ return 0;
+}
+
+
void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
}
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
index 6f96b754d8..55f6ac5806 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -40,6 +40,10 @@
extern char **environ;
#endif
+#ifdef __linux__
+# include <grp.h>
+#endif
+
static QUEUE* uv__process_queue(uv_loop_t* loop, int pid) {
assert(pid > 0);
@@ -330,6 +334,17 @@ static void uv__process_child_init(const uv_process_options_t* options,
_exit(127);
}
+ if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
+ /* When dropping privileges from root, the `setgroups` call will
+ * remove any extraneous groups. If we don't call this, then
+ * even though our uid has dropped, we may still have groups
+ * that enable us to do super-user things. This will fail if we
+ * aren't root, so don't bother checking the return value, this
+ * is just done as an optimistic privilege dropping function.
+ */
+ SAVE_ERRNO(setgroups(0, NULL));
+ }
+
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
uv__write_int(error_fd, -errno);
perror("setgid()");
@@ -422,10 +437,13 @@ int uv_spawn(uv_loop_t* loop,
uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
+ /* Acquire write lock to prevent opening new fds in worker threads */
+ uv_rwlock_wrlock(&loop->cloexec_lock);
pid = fork();
if (pid == -1) {
err = -errno;
+ uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[0]);
uv__close(signal_pipe[1]);
goto error;
@@ -436,6 +454,8 @@ int uv_spawn(uv_loop_t* loop,
abort();
}
+ /* Release lock in parent process */
+ uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[1]);
process->status = 0;
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 9f5d40cf4b..ad6856b4b7 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -301,6 +301,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
int err;
int ret;
int kq;
+ int old_fd;
kq = kqueue();
if (kq == -1) {
@@ -353,16 +354,20 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
s->fake_fd = fds[0];
s->int_fd = fds[1];
- if (uv_thread_create(&s->thread, uv__stream_osx_select, stream))
- goto fatal4;
-
+ old_fd = *fd;
s->stream = stream;
stream->select = s;
*fd = s->fake_fd;
+ if (uv_thread_create(&s->thread, uv__stream_osx_select, stream))
+ goto fatal4;
+
return 0;
fatal4:
+ s->stream = NULL;
+ stream->select = NULL;
+ *fd = old_fd;
uv__close(s->fake_fd);
uv__close(s->int_fd);
s->fake_fd = -1;
@@ -1103,6 +1108,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
if (!(stream->flags & UV_STREAM_WRITABLE) ||
stream->flags & UV_STREAM_SHUT ||
+ stream->flags & UV_STREAM_SHUTTING ||
stream->flags & UV_CLOSED ||
stream->flags & UV_CLOSING) {
return -ENOTCONN;
@@ -1505,7 +1511,5 @@ void uv__stream_close(uv_stream_t* handle) {
int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
- assert(0 && "implement me");
- abort();
- return 0;
+ return UV_ENOSYS;
}
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index f31a23fb3c..b8a39c7017 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -372,11 +372,14 @@ static void uv__fs_event_read(uv_loop_t* loop,
assert(events != 0);
handle->fd = PORT_FIRED;
handle->cb(handle, NULL, events, 0);
+
+ if (handle->fd != PORT_DELETED) {
+ r = uv__fs_event_rearm(handle);
+ if (r != 0)
+ handle->cb(handle, NULL, 0, r);
+ }
}
while (handle->fd != PORT_DELETED);
-
- if (handle != NULL && handle->fd != PORT_DELETED)
- uv__fs_event_rearm(handle); /* FIXME(bnoordhuis) Check return code. */
}
@@ -388,10 +391,11 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
- const char* filename,
+ const char* path,
unsigned int flags) {
int portfd;
int first_run;
+ int err;
if (uv__is_active(handle))
return -EINVAL;
@@ -406,13 +410,15 @@ int uv_fs_event_start(uv_fs_event_t* handle,
}
uv__handle_start(handle);
- handle->filename = strdup(filename);
+ handle->path = strdup(path);
handle->fd = PORT_UNUSED;
handle->cb = cb;
memset(&handle->fo, 0, sizeof handle->fo);
- handle->fo.fo_name = handle->filename;
- uv__fs_event_rearm(handle); /* FIXME(bnoordhuis) Check return code. */
+ handle->fo.fo_name = handle->path;
+ err = uv__fs_event_rearm(handle);
+ if (err != 0)
+ return err;
if (first_run) {
uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd);
@@ -434,8 +440,8 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
}
handle->fd = PORT_DELETED;
- free(handle->filename);
- handle->filename = NULL;
+ free(handle->path);
+ handle->path = NULL;
handle->fo.fo_name = NULL;
uv__handle_stop(handle);
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index 2c36dc3ffc..9c50b2d8a1 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -232,7 +232,9 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
int uv__tcp_nodelay(int fd, int on) {
- return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
+ return -errno;
+ return 0;
}
diff --git a/deps/uv/src/unix/timer.c b/deps/uv/src/unix/timer.c
index 240efad503..b373f4db87 100644
--- a/deps/uv/src/unix/timer.c
+++ b/deps/uv/src/unix/timer.c
@@ -20,35 +20,41 @@
#include "uv.h"
#include "internal.h"
+#include "heap-inl.h"
+
#include <assert.h>
#include <limits.h>
-static int uv__timer_cmp(const uv_timer_t* a, const uv_timer_t* b) {
+static int timer_less_than(const struct heap_node* ha,
+ const struct heap_node* hb) {
+ const uv_timer_t* a;
+ const uv_timer_t* b;
+
+ a = container_of(ha, const uv_timer_t, heap_node);
+ b = container_of(hb, const uv_timer_t, heap_node);
+
if (a->timeout < b->timeout)
- return -1;
- if (a->timeout > b->timeout)
return 1;
- /*
- * compare start_id when both has the same timeout. start_id is
- * allocated with loop->timer_counter in uv_timer_start().
+ if (b->timeout < a->timeout)
+ return 0;
+
+ /* Compare start_id when both have the same timeout. start_id is
+ * allocated with loop->timer_counter in uv_timer_start().
*/
if (a->start_id < b->start_id)
- return -1;
- if (a->start_id > b->start_id)
return 1;
+ if (b->start_id < a->start_id)
+ return 0;
+
return 0;
}
-RB_GENERATE_STATIC(uv__timers, uv_timer_s, tree_entry, uv__timer_cmp)
-
-
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
handle->timer_cb = NULL;
handle->repeat = 0;
-
return 0;
}
@@ -72,7 +78,9 @@ int uv_timer_start(uv_timer_t* handle,
/* start_id is the second index to be compared in uv__timer_cmp() */
handle->start_id = handle->loop->timer_counter++;
- RB_INSERT(uv__timers, &handle->loop->timer_handles, handle);
+ heap_insert((struct heap*) &handle->loop->timer_heap,
+ (struct heap_node*) &handle->heap_node,
+ timer_less_than);
uv__handle_start(handle);
return 0;
@@ -83,7 +91,9 @@ int uv_timer_stop(uv_timer_t* handle) {
if (!uv__is_active(handle))
return 0;
- RB_REMOVE(uv__timers, &handle->loop->timer_handles, handle);
+ heap_remove((struct heap*) &handle->loop->timer_heap,
+ (struct heap_node*) &handle->heap_node,
+ timer_less_than);
uv__handle_stop(handle);
return 0;
@@ -114,15 +124,15 @@ uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
int uv__next_timeout(const uv_loop_t* loop) {
+ const struct heap_node* heap_node;
const uv_timer_t* handle;
uint64_t diff;
- /* RB_MIN expects a non-const tree root. That's okay, it doesn't modify it. */
- handle = RB_MIN(uv__timers, (struct uv__timers*) &loop->timer_handles);
-
- if (handle == NULL)
+ heap_node = heap_min((const struct heap*) &loop->timer_heap);
+ if (heap_node == NULL)
return -1; /* block indefinitely */
+ handle = container_of(heap_node, const uv_timer_t, heap_node);
if (handle->timeout <= loop->time)
return 0;
@@ -135,9 +145,15 @@ 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;
- while ((handle = RB_MIN(uv__timers, &loop->timer_handles))) {
+ for (;;) {
+ heap_node = heap_min((struct heap*) &loop->timer_heap);
+ if (heap_node == NULL)
+ break;
+
+ handle = container_of(heap_node, uv_timer_t, heap_node);
if (handle->timeout > loop->time)
break;
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index a2b3dc3298..ae3cc8dc65 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -539,6 +539,31 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, on);
}
+int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
+ struct in_addr addr;
+ int err;
+
+ memset(&addr, 0, sizeof addr);
+
+ if (interface_addr) {
+ err = uv_inet_pton(AF_INET, interface_addr, &addr.s_addr);
+ if (err)
+ return err;
+ } else {
+ addr.s_addr = htonl(INADDR_ANY);
+ }
+
+ if (setsockopt(handle->io_watcher.fd,
+ IPPROTO_IP,
+ IP_MULTICAST_IF,
+ (void*) &addr,
+ sizeof addr) == -1) {
+ return -errno;
+ }
+
+ return 0;
+}
+
int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen) {
socklen_t socklen;