diff options
author | Timothy J Fontaine <tjfontaine@gmail.com> | 2014-02-26 18:08:30 -0800 |
---|---|---|
committer | Timothy J Fontaine <tjfontaine@gmail.com> | 2014-02-26 18:08:30 -0800 |
commit | cd08c8a0e5e99ed4933b87fc5e188afcd4299f73 (patch) | |
tree | c05e93d47f89df1f7a782ee9c70bb2c97d557cd4 /deps/uv/src/unix | |
parent | f3189ace6b5e31a874df421ac2f74da0e77cb14d (diff) | |
download | android-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.c | 32 | ||||
-rw-r--r-- | deps/uv/src/unix/fs.c | 209 | ||||
-rw-r--r-- | deps/uv/src/unix/fsevents.c | 2 | ||||
-rw-r--r-- | deps/uv/src/unix/internal.h | 9 | ||||
-rw-r--r-- | deps/uv/src/unix/kqueue.c | 10 | ||||
-rw-r--r-- | deps/uv/src/unix/linux-core.c | 24 | ||||
-rw-r--r-- | deps/uv/src/unix/linux-inotify.c | 6 | ||||
-rw-r--r-- | deps/uv/src/unix/linux-syscalls.c | 36 | ||||
-rw-r--r-- | deps/uv/src/unix/linux-syscalls.h | 2 | ||||
-rw-r--r-- | deps/uv/src/unix/loop.c | 54 | ||||
-rw-r--r-- | deps/uv/src/unix/pipe.c | 32 | ||||
-rw-r--r-- | deps/uv/src/unix/process.c | 20 | ||||
-rw-r--r-- | deps/uv/src/unix/stream.c | 16 | ||||
-rw-r--r-- | deps/uv/src/unix/sunos.c | 24 | ||||
-rw-r--r-- | deps/uv/src/unix/tcp.c | 4 | ||||
-rw-r--r-- | deps/uv/src/unix/timer.c | 54 | ||||
-rw-r--r-- | deps/uv/src/unix/udp.c | 25 |
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; |