summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/libuv/src/unix
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/libuv/src/unix')
-rw-r--r--3rdparty/libuv/src/unix/aix.c63
-rw-r--r--3rdparty/libuv/src/unix/core.c194
-rw-r--r--3rdparty/libuv/src/unix/fs.c17
-rw-r--r--3rdparty/libuv/src/unix/internal.h31
-rw-r--r--3rdparty/libuv/src/unix/kqueue.c21
-rw-r--r--3rdparty/libuv/src/unix/linux-core.c77
-rw-r--r--3rdparty/libuv/src/unix/linux-syscalls.h1
-rw-r--r--3rdparty/libuv/src/unix/pipe.c11
-rw-r--r--3rdparty/libuv/src/unix/poll.c16
-rw-r--r--3rdparty/libuv/src/unix/process.c6
-rw-r--r--3rdparty/libuv/src/unix/stream.c22
-rw-r--r--3rdparty/libuv/src/unix/sunos.c11
-rw-r--r--3rdparty/libuv/src/unix/thread.c33
-rw-r--r--3rdparty/libuv/src/unix/tty.c36
14 files changed, 438 insertions, 101 deletions
diff --git a/3rdparty/libuv/src/unix/aix.c b/3rdparty/libuv/src/unix/aix.c
index c90b7e5cb9b..bcaa5ee50bc 100644
--- a/3rdparty/libuv/src/unix/aix.c
+++ b/3rdparty/libuv/src/unix/aix.c
@@ -91,6 +91,24 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ struct poll_ctl pc;
+
+ pc.events = POLLIN;
+ pc.cmd = PS_MOD; /* Equivalent to PS_ADD if the fd is not in the pollset. */
+ pc.fd = fd;
+
+ if (pollset_ctl(loop->backend_fd, &pc, 1))
+ return -errno;
+
+ pc.cmd = PS_DELETE;
+ if (pollset_ctl(loop->backend_fd, &pc, 1))
+ abort();
+
+ return 0;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
struct pollfd events[1024];
struct pollfd pqry;
@@ -506,7 +524,7 @@ static int uv__makedir_p(const char *dir) {
if (*p == '/') {
*p = 0;
err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
- if(err != 0)
+ if (err != 0 && errno != EEXIST)
return err;
*p = '/';
}
@@ -707,59 +725,44 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int
int bytes, rc = 0;
uv_fs_event_t* handle;
int events = 0;
- int i = 0;
char fname[PATH_MAX];
char *p;
handle = container_of(event_watch, uv_fs_event_t, event_watcher);
- /* Clean all the buffers*/
- for(i = 0; i < PATH_MAX; i++) {
- fname[i] = 0;
- }
- i = 0;
-
/* At this point, we assume that polling has been done on the
* file descriptor, so we can just read the AHAFS event occurrence
* data and parse its results without having to block anything
*/
bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0);
- assert((bytes <= 0) && "uv__ahafs_event - Error reading monitor file");
+ assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file");
/* Parse the data */
if(bytes > 0)
rc = uv__parse_data(result_data, &events, handle);
+ /* Unrecoverable error */
+ if (rc == -1)
+ return;
+
/* For directory changes, the name of the files that triggered the change
* are never absolute pathnames
*/
if (uv__path_is_a_directory(handle->path) == 0) {
p = handle->dir_filename;
- while(*p != NULL){
- fname[i]= *p;
- i++;
- p++;
- }
} else {
- /* For file changes, figure out whether filename is absolute or not */
- if (handle->path[0] == '/') {
- p = strrchr(handle->path, '/');
+ p = strrchr(handle->path, '/');
+ if (p == NULL)
+ p = handle->path;
+ else
p++;
-
- while(*p != NULL) {
- fname[i]= *p;
- i++;
- p++;
- }
- }
}
+ strncpy(fname, p, sizeof(fname) - 1);
+ /* Just in case */
+ fname[sizeof(fname) - 1] = '\0';
- /* Unrecoverable error */
- if (rc == -1)
- return;
- else /* Call the actual JavaScript callback function */
- handle->cb(handle, (const char*)&fname, events, 0);
+ handle->cb(handle, fname, events, 0);
}
#endif
@@ -839,7 +842,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
/* Setup/Initialize all the libuv routines */
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
- handle->path = uv__strdup((const char*)&absolute_path);
+ handle->path = uv__strdup(filename);
handle->cb = cb;
uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN);
diff --git a/3rdparty/libuv/src/unix/core.c b/3rdparty/libuv/src/unix/core.c
index cedd86ed34a..9aaca841870 100644
--- a/3rdparty/libuv/src/unix/core.c
+++ b/3rdparty/libuv/src/unix/core.c
@@ -53,6 +53,9 @@
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
# include <sys/filio.h>
# include <sys/ioctl.h>
+# if defined(O_CLOEXEC)
+# define UV__O_CLOEXEC O_CLOEXEC
+# endif
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
@@ -427,6 +430,22 @@ int uv__socket(int domain, int type, int protocol) {
return sockfd;
}
+/* get a file pointer to a file in read-only and close-on-exec mode */
+FILE* uv__open_file(const char* path) {
+ int fd;
+ FILE* fp;
+
+ fd = uv__open_cloexec(path, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ fp = fdopen(fd, "r");
+ if (fp == NULL)
+ uv__close(fd);
+
+ return fp;
+}
+
int uv__accept(int sockfd) {
int peerfd;
@@ -435,7 +454,7 @@ int uv__accept(int sockfd) {
assert(sockfd >= 0);
while (1) {
-#if defined(__linux__) || __FreeBSD__ >= 10
+#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10)
static int no_accept4;
if (no_accept4)
@@ -479,12 +498,11 @@ skip:
}
-int uv__close(int fd) {
+int uv__close_nocheckstdio(int fd) {
int saved_errno;
int rc;
assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */
- assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
saved_errno = errno;
rc = close(fd);
@@ -499,6 +517,12 @@ int uv__close(int fd) {
}
+int uv__close(int fd) {
+ assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
+ return uv__close_nocheckstdio(fd);
+}
+
+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
defined(_AIX) || defined(__DragonFly__)
@@ -809,7 +833,7 @@ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
+ assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
assert(w->fd >= 0);
assert(w->fd < INT_MAX);
@@ -842,7 +866,7 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
+ assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
if (w->fd == -1)
@@ -874,7 +898,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
- uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT);
+ uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
QUEUE_REMOVE(&w->pending_queue);
/* Remove stale events for this file descriptor */
@@ -889,7 +913,7 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
int uv__io_active(const uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
+ assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
return 0 != (w->pevents & events);
}
@@ -930,8 +954,7 @@ int uv__open_cloexec(const char* path, int flags) {
int err;
int fd;
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 9) || \
- defined(__DragonFly__)
+#if defined(UV__O_CLOEXEC)
static int no_cloexec;
if (!no_cloexec) {
@@ -1014,17 +1037,10 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
int uv_os_homedir(char* buffer, size_t* size) {
- struct passwd pw;
- struct passwd* result;
+ uv_passwd_t pwd;
char* buf;
- uid_t uid;
- size_t bufsize;
size_t len;
- long initsize;
int r;
-#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
- int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**);
-#endif
if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
@@ -1036,7 +1052,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
len = strlen(buf);
if (len >= *size) {
- *size = len;
+ *size = len + 1;
return -ENOBUFS;
}
@@ -1046,13 +1062,102 @@ int uv_os_homedir(char* buffer, size_t* size) {
return 0;
}
+ /* HOME is not set, so call uv__getpwuid_r() */
+ r = uv__getpwuid_r(&pwd);
+
+ if (r != 0) {
+ return r;
+ }
+
+ len = strlen(pwd.homedir);
+
+ if (len >= *size) {
+ *size = len + 1;
+ uv_os_free_passwd(&pwd);
+ return -ENOBUFS;
+ }
+
+ memcpy(buffer, pwd.homedir, len + 1);
+ *size = len;
+ uv_os_free_passwd(&pwd);
+
+ return 0;
+}
+
+
+int uv_os_tmpdir(char* buffer, size_t* size) {
+ const char* buf;
+ size_t len;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return -EINVAL;
+
+#define CHECK_ENV_VAR(name) \
+ do { \
+ buf = getenv(name); \
+ if (buf != NULL) \
+ goto return_buffer; \
+ } \
+ while (0)
+
+ /* Check the TMPDIR, TMP, TEMP, and TEMPDIR environment variables in order */
+ CHECK_ENV_VAR("TMPDIR");
+ CHECK_ENV_VAR("TMP");
+ CHECK_ENV_VAR("TEMP");
+ CHECK_ENV_VAR("TEMPDIR");
+
+#undef CHECK_ENV_VAR
+
+ /* No temp environment variables defined */
+ #if defined(__ANDROID__)
+ buf = "/data/local/tmp";
+ #else
+ buf = "/tmp";
+ #endif
+
+return_buffer:
+ len = strlen(buf);
+
+ if (len >= *size) {
+ *size = len + 1;
+ return -ENOBUFS;
+ }
+
+ /* The returned directory should not have a trailing slash. */
+ if (len > 1 && buf[len - 1] == '/') {
+ len--;
+ }
+
+ memcpy(buffer, buf, len + 1);
+ buffer[len] = '\0';
+ *size = len;
+
+ return 0;
+}
+
+
+int uv__getpwuid_r(uv_passwd_t* pwd) {
+ struct passwd pw;
+ struct passwd* result;
+ char* buf;
+ uid_t uid;
+ size_t bufsize;
+ size_t name_size;
+ size_t homedir_size;
+ size_t shell_size;
+ long initsize;
+ int r;
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
+ int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**);
+
getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
if (getpwuid_r == NULL)
return -ENOSYS;
#endif
- /* HOME is not set, so call getpwuid() */
+ if (pwd == NULL)
+ return -EINVAL;
+
initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (initsize <= 0)
@@ -1060,7 +1165,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
else
bufsize = (size_t) initsize;
- uid = getuid();
+ uid = geteuid();
buf = NULL;
for (;;) {
@@ -1088,17 +1193,54 @@ int uv_os_homedir(char* buffer, size_t* size) {
return -ENOENT;
}
- len = strlen(pw.pw_dir);
+ /* Allocate memory for the username, shell, and home directory */
+ name_size = strlen(pw.pw_name) + 1;
+ homedir_size = strlen(pw.pw_dir) + 1;
+ shell_size = strlen(pw.pw_shell) + 1;
+ pwd->username = uv__malloc(name_size + homedir_size + shell_size);
- if (len >= *size) {
- *size = len;
+ if (pwd->username == NULL) {
uv__free(buf);
- return -ENOBUFS;
+ return -ENOMEM;
}
- memcpy(buffer, pw.pw_dir, len + 1);
- *size = len;
+ /* Copy the username */
+ memcpy(pwd->username, pw.pw_name, name_size);
+
+ /* Copy the home directory */
+ pwd->homedir = pwd->username + name_size;
+ memcpy(pwd->homedir, pw.pw_dir, homedir_size);
+
+ /* Copy the shell */
+ pwd->shell = pwd->homedir + homedir_size;
+ memcpy(pwd->shell, pw.pw_shell, shell_size);
+
+ /* Copy the uid and gid */
+ pwd->uid = pw.pw_uid;
+ pwd->gid = pw.pw_gid;
+
uv__free(buf);
return 0;
}
+
+
+void uv_os_free_passwd(uv_passwd_t* pwd) {
+ if (pwd == NULL)
+ return;
+
+ /*
+ The memory for name, shell, and homedir are allocated in a single
+ uv__malloc() call. The base of the pointer is stored in pwd->username, so
+ that is the field that needs to be freed.
+ */
+ uv__free(pwd->username);
+ pwd->username = NULL;
+ pwd->shell = NULL;
+ pwd->homedir = NULL;
+}
+
+
+int uv_os_get_passwd(uv_passwd_t* pwd) {
+ return uv__getpwuid_r(pwd);
+}
diff --git a/3rdparty/libuv/src/unix/fs.c b/3rdparty/libuv/src/unix/fs.c
index 57b65be25a8..8936ad9d837 100644
--- a/3rdparty/libuv/src/unix/fs.c
+++ b/3rdparty/libuv/src/unix/fs.c
@@ -127,8 +127,8 @@
static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
return fdatasync(req->file);
-#elif defined(__APPLE__) && defined(F_FULLFSYNC)
- return fcntl(req->file, F_FULLFSYNC);
+#elif defined(__APPLE__) && defined(SYS_fdatasync)
+ return syscall(SYS_fdatasync, req->file);
#else
return fsync(req->file);
#endif
@@ -749,13 +749,13 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
dst->st_gen = src->st_gen;
#elif defined(__ANDROID__)
dst->st_atim.tv_sec = src->st_atime;
- dst->st_atim.tv_nsec = src->st_atime_nsec;
+ dst->st_atim.tv_nsec = src->st_atimensec;
dst->st_mtim.tv_sec = src->st_mtime;
- dst->st_mtim.tv_nsec = src->st_mtime_nsec;
+ dst->st_mtim.tv_nsec = src->st_mtimensec;
dst->st_ctim.tv_sec = src->st_ctime;
- dst->st_ctim.tv_nsec = src->st_ctime_nsec;
+ dst->st_ctim.tv_nsec = src->st_ctimensec;
dst->st_birthtim.tv_sec = src->st_ctime;
- dst->st_birthtim.tv_nsec = src->st_ctime_nsec;
+ dst->st_birthtim.tv_nsec = src->st_ctimensec;
dst->st_flags = 0;
dst->st_gen = 0;
#elif !defined(_AIX) && ( \
@@ -858,9 +858,14 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process)
total += result;
}
+ if (errno == EINTR && total == -1)
+ return total;
+
if (bufs != req->bufsml)
uv__free(bufs);
+
req->bufs = NULL;
+ req->nbufs = 0;
return total;
}
diff --git a/3rdparty/libuv/src/unix/internal.h b/3rdparty/libuv/src/unix/internal.h
index 741fa57d69c..938e76f1d18 100644
--- a/3rdparty/libuv/src/unix/internal.h
+++ b/3rdparty/libuv/src/unix/internal.h
@@ -28,6 +28,7 @@
#include <stdlib.h> /* abort */
#include <string.h> /* strrchr */
#include <fcntl.h> /* O_CLOEXEC, may be */
+#include <stdio.h>
#if defined(__STRICT_ANSI__)
# define inline __inline
@@ -89,17 +90,18 @@
#endif
#if defined(__linux__)
-# define UV__POLLIN UV__EPOLLIN
-# define UV__POLLOUT UV__EPOLLOUT
-# define UV__POLLERR UV__EPOLLERR
-# define UV__POLLHUP UV__EPOLLHUP
+# define UV__POLLIN UV__EPOLLIN
+# define UV__POLLOUT UV__EPOLLOUT
+# define UV__POLLERR UV__EPOLLERR
+# define UV__POLLHUP UV__EPOLLHUP
+# define UV__POLLRDHUP UV__EPOLLRDHUP
#endif
#if defined(__sun) || defined(_AIX)
-# define UV__POLLIN POLLIN
-# define UV__POLLOUT POLLOUT
-# define UV__POLLERR POLLERR
-# define UV__POLLHUP POLLHUP
+# define UV__POLLIN POLLIN
+# define UV__POLLOUT POLLOUT
+# define UV__POLLERR POLLERR
+# define UV__POLLHUP POLLHUP
#endif
#ifndef UV__POLLIN
@@ -118,6 +120,14 @@
# define UV__POLLHUP 8
#endif
+#ifndef UV__POLLRDHUP
+# ifdef POLLRDHUP
+# define UV__POLLRDHUP POLLRDHUP
+# else
+# define UV__POLLRDHUP 0x200
+# endif
+#endif
+
#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
/*
* It may be that we are just missing `__POSIX_VISIBLE >= 200809`.
@@ -167,6 +177,7 @@ struct uv__stream_queued_fds_s {
/* core */
int uv__nonblock(int fd, int set);
int uv__close(int fd);
+int uv__close_nocheckstdio(int fd);
int uv__cloexec(int fd, int set);
int uv__socket(int domain, int type, int protocol);
int uv__dup(int fd);
@@ -180,6 +191,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events);
void uv__io_close(uv_loop_t* loop, uv__io_t* w);
void uv__io_feed(uv_loop_t* loop, uv__io_t* w);
int uv__io_active(const uv__io_t* w, unsigned int events);
+int uv__io_check_fd(uv_loop_t* loop, int fd);
void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
/* async */
@@ -245,6 +257,9 @@ void uv__timer_close(uv_timer_t* handle);
void uv__udp_close(uv_udp_t* handle);
void uv__udp_finish_close(uv_udp_t* handle);
uv_handle_type uv__handle_type(int fd);
+FILE* uv__open_file(const char* path);
+int uv__getpwuid_r(uv_passwd_t* pwd);
+
#if defined(__APPLE__)
int uv___stream_fd(const uv_stream_t* handle);
diff --git a/3rdparty/libuv/src/unix/kqueue.c b/3rdparty/libuv/src/unix/kqueue.c
index 495f20d285f..400b4a4b7c6 100644
--- a/3rdparty/libuv/src/unix/kqueue.c
+++ b/3rdparty/libuv/src/unix/kqueue.c
@@ -48,6 +48,24 @@ int uv__kqueue_init(uv_loop_t* loop) {
}
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ struct kevent ev;
+ int rc;
+
+ rc = 0;
+ EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
+ if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
+ rc = -errno;
+
+ EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
+ if (rc == 0)
+ if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
+ abort();
+
+ return rc;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
struct kevent events[1024];
struct kevent* ev;
@@ -241,6 +259,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (ev->flags & EV_ERROR)
revents |= UV__POLLERR;
+ if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP))
+ revents |= UV__POLLRDHUP;
+
if (revents == 0)
continue;
diff --git a/3rdparty/libuv/src/unix/linux-core.c b/3rdparty/libuv/src/unix/linux-core.c
index 3ff6fb15e93..fb8ac3f2379 100644
--- a/3rdparty/libuv/src/unix/linux-core.c
+++ b/3rdparty/libuv/src/unix/linux-core.c
@@ -39,7 +39,7 @@
#define HAVE_IFADDRS_H 1
#ifdef __UCLIBC__
-# if __UCLIBC_MAJOR__ < 0 || __UCLIBC_MINOR__ < 9 || __UCLIBC_SUBLEVEL__ < 32
+# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
# undef HAVE_IFADDRS_H
# endif
#endif
@@ -52,7 +52,7 @@
# endif
# include <sys/socket.h>
# include <net/ethernet.h>
-# include <linux/if_packet.h>
+# include <netpacket/packet.h>
#endif /* HAVE_IFADDRS_H */
/* Available from 2.6.32 onwards. */
@@ -69,7 +69,7 @@
#endif
static int read_models(unsigned int numcpus, uv_cpu_info_t* ci);
-static int read_times(unsigned int numcpus, uv_cpu_info_t* ci);
+static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci);
static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
static unsigned long read_cpufreq(unsigned int cpunum);
@@ -140,6 +140,26 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
}
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ struct uv__epoll_event e;
+ int rc;
+
+ e.events = UV__EPOLLIN;
+ e.data = -1;
+
+ rc = 0;
+ if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e))
+ if (errno != EEXIST)
+ rc = -errno;
+
+ if (rc == 0)
+ if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e))
+ abort();
+
+ return rc;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
/* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
* effectively infinite on 32 bits architectures. To avoid blocking
@@ -532,15 +552,42 @@ int uv_uptime(double* uptime) {
}
+static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
+ unsigned int num;
+ char buf[1024];
+
+ if (!fgets(buf, sizeof(buf), statfile_fp))
+ abort();
+
+ num = 0;
+ while (fgets(buf, sizeof(buf), statfile_fp)) {
+ if (strncmp(buf, "cpu", 3))
+ break;
+ num++;
+ }
+
+ *numcpus = num;
+ return 0;
+}
+
+
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
unsigned int numcpus;
uv_cpu_info_t* ci;
int err;
+ FILE* statfile_fp;
*cpu_infos = NULL;
*count = 0;
- numcpus = sysconf(_SC_NPROCESSORS_ONLN);
+ statfile_fp = uv__open_file("/proc/stat");
+ if (statfile_fp == NULL)
+ return -errno;
+
+ err = uv__cpu_num(statfile_fp, &numcpus);
+ if (err < 0)
+ return err;
+
assert(numcpus != (unsigned int) -1);
assert(numcpus != 0);
@@ -550,7 +597,11 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
err = read_models(numcpus, ci);
if (err == 0)
- err = read_times(numcpus, ci);
+ err = read_times(statfile_fp, numcpus, ci);
+
+ if (fclose(statfile_fp))
+ if (errno != EINTR && errno != EINPROGRESS)
+ abort();
if (err) {
uv_free_cpu_info(ci, numcpus);
@@ -608,7 +659,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
defined(__i386__) || \
defined(__mips__) || \
defined(__x86_64__)
- fp = fopen("/proc/cpuinfo", "r");
+ fp = uv__open_file("/proc/cpuinfo");
if (fp == NULL)
return -errno;
@@ -676,7 +727,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
}
-static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
+static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci) {
unsigned long clock_ticks;
struct uv_cpu_times_s ts;
unsigned long user;
@@ -688,22 +739,19 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
unsigned int num;
unsigned int len;
char buf[1024];
- FILE* fp;
clock_ticks = sysconf(_SC_CLK_TCK);
assert(clock_ticks != (unsigned long) -1);
assert(clock_ticks != 0);
- fp = fopen("/proc/stat", "r");
- if (fp == NULL)
- return -errno;
+ rewind(statfile_fp);
- if (!fgets(buf, sizeof(buf), fp))
+ if (!fgets(buf, sizeof(buf), statfile_fp))
abort();
num = 0;
- while (fgets(buf, sizeof(buf), fp)) {
+ while (fgets(buf, sizeof(buf), statfile_fp)) {
if (num >= numcpus)
break;
@@ -742,7 +790,6 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
ts.irq = clock_ticks * irq;
ci[num++].cpu_times = ts;
}
- fclose(fp);
assert(num == numcpus);
return 0;
@@ -759,7 +806,7 @@ static unsigned long read_cpufreq(unsigned int cpunum) {
"/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq",
cpunum);
- fp = fopen(buf, "r");
+ fp = uv__open_file(buf);
if (fp == NULL)
return 0;
diff --git a/3rdparty/libuv/src/unix/linux-syscalls.h b/3rdparty/libuv/src/unix/linux-syscalls.h
index 96e79439cf0..4260df111f3 100644
--- a/3rdparty/libuv/src/unix/linux-syscalls.h
+++ b/3rdparty/libuv/src/unix/linux-syscalls.h
@@ -76,6 +76,7 @@
#define UV__EPOLLOUT 4
#define UV__EPOLLERR 8
#define UV__EPOLLHUP 16
+#define UV__EPOLLRDHUP 0x2000
#define UV__EPOLLONESHOT 0x40000000
#define UV__EPOLLET 0x80000000
diff --git a/3rdparty/libuv/src/unix/pipe.c b/3rdparty/libuv/src/unix/pipe.c
index 7f87a713bf4..d4fdfa9d5a5 100644
--- a/3rdparty/libuv/src/unix/pipe.c
+++ b/3rdparty/libuv/src/unix/pipe.c
@@ -200,9 +200,6 @@ out:
if (err)
uv__io_feed(handle->loop, &handle->io_watcher);
- /* Mimic the Windows pipe implementation, always
- * return 0 and let the callback handle errors.
- */
}
@@ -234,14 +231,18 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
addrlen = strlen(sa.sun_path);
- if (addrlen > *size) {
- *size = addrlen;
+ if (addrlen >= *size) {
+ *size = addrlen + 1;
return UV_ENOBUFS;
}
memcpy(buffer, sa.sun_path, addrlen);
*size = addrlen;
+ /* only null-terminate if it's not an abstract socket */
+ if (buffer[0] != '\0')
+ buffer[addrlen] = '\0';
+
return 0;
}
diff --git a/3rdparty/libuv/src/unix/poll.c b/3rdparty/libuv/src/unix/poll.c
index 37da3b95851..e5efb17160f 100644
--- a/3rdparty/libuv/src/unix/poll.c
+++ b/3rdparty/libuv/src/unix/poll.c
@@ -34,7 +34,7 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
handle = container_of(w, uv_poll_t, io_watcher);
if (events & UV__POLLERR) {
- uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT);
+ uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
uv__handle_stop(handle);
handle->poll_cb(handle, -EBADF, 0);
return;
@@ -45,6 +45,8 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
pevents |= UV_READABLE;
if (events & UV__POLLOUT)
pevents |= UV_WRITABLE;
+ if (events & UV__POLLRDHUP)
+ pevents |= UV_DISCONNECT;
handle->poll_cb(handle, 0, pevents);
}
@@ -53,6 +55,10 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
int err;
+ err = uv__io_check_fd(loop, fd);
+ if (err)
+ return err;
+
err = uv__nonblock(fd, 1);
if (err)
return err;
@@ -71,7 +77,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
static void uv__poll_stop(uv_poll_t* handle) {
- uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLIN | UV__POLLOUT);
+ uv__io_stop(handle->loop,
+ &handle->io_watcher,
+ UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
uv__handle_stop(handle);
}
@@ -86,7 +94,7 @@ int uv_poll_stop(uv_poll_t* handle) {
int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
int events;
- assert((pevents & ~(UV_READABLE | UV_WRITABLE)) == 0);
+ assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
uv__poll_stop(handle);
@@ -99,6 +107,8 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
events |= UV__POLLIN;
if (pevents & UV_WRITABLE)
events |= UV__POLLOUT;
+ if (pevents & UV_DISCONNECT)
+ events |= UV__POLLRDHUP;
uv__io_start(handle->loop, &handle->io_watcher, events);
uv__handle_start(handle);
diff --git a/3rdparty/libuv/src/unix/process.c b/3rdparty/libuv/src/unix/process.c
index 571f8cd778c..ef10a3422dc 100644
--- a/3rdparty/libuv/src/unix/process.c
+++ b/3rdparty/libuv/src/unix/process.c
@@ -498,7 +498,7 @@ int uv_spawn(uv_loop_t* loop,
} else
abort();
- uv__close(signal_pipe[0]);
+ uv__close_nocheckstdio(signal_pipe[0]);
for (i = 0; i < options->stdio_count; i++) {
err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0);
@@ -530,9 +530,9 @@ error:
if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM))
continue;
if (pipes[i][0] != -1)
- close(pipes[i][0]);
+ uv__close_nocheckstdio(pipes[i][0]);
if (pipes[i][1] != -1)
- close(pipes[i][1]);
+ uv__close_nocheckstdio(pipes[i][1]);
}
uv__free(pipes);
}
diff --git a/3rdparty/libuv/src/unix/stream.c b/3rdparty/libuv/src/unix/stream.c
index 7d7ab2633b6..9043664dfca 100644
--- a/3rdparty/libuv/src/unix/stream.c
+++ b/3rdparty/libuv/src/unix/stream.c
@@ -946,13 +946,14 @@ static void uv__write_callbacks(uv_stream_t* stream) {
uv_handle_type uv__handle_type(int fd) {
struct sockaddr_storage ss;
+ socklen_t sslen;
socklen_t len;
int type;
memset(&ss, 0, sizeof(ss));
- len = sizeof(ss);
+ sslen = sizeof(ss);
- if (getsockname(fd, (struct sockaddr*)&ss, &len))
+ if (getsockname(fd, (struct sockaddr*)&ss, &sslen))
return UV_UNKNOWN_HANDLE;
len = sizeof type;
@@ -961,6 +962,14 @@ uv_handle_type uv__handle_type(int fd) {
return UV_UNKNOWN_HANDLE;
if (type == SOCK_STREAM) {
+#if defined(_AIX)
+ /* on AIX the getsockname call returns an empty sa structure
+ * for sockets of type AF_UNIX. For all other types it will
+ * return a properly filled in structure.
+ */
+ if (sslen == 0)
+ return UV_NAMED_PIPE;
+#endif
switch (ss.ss_family) {
case AF_UNIX:
return UV_NAMED_PIPE;
@@ -1082,6 +1091,11 @@ static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) {
}
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wgnu-folding-constant"
+#endif
+
static void uv__read(uv_stream_t* stream) {
uv_buf_t buf;
ssize_t nread;
@@ -1187,6 +1201,10 @@ static void uv__read(uv_stream_t* stream) {
}
+#ifdef __clang__
+# pragma clang diagnostic pop
+#endif
+
#undef UV__CMSG_FD_COUNT
#undef UV__CMSG_FD_SIZE
diff --git a/3rdparty/libuv/src/unix/sunos.c b/3rdparty/libuv/src/unix/sunos.c
index 0c46817b446..9a6cc42b5bf 100644
--- a/3rdparty/libuv/src/unix/sunos.c
+++ b/3rdparty/libuv/src/unix/sunos.c
@@ -116,6 +116,17 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
}
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
+ return -errno;
+
+ if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
+ abort();
+
+ return 0;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
struct port_event events[1024];
struct port_event* pe;
diff --git a/3rdparty/libuv/src/unix/thread.c b/3rdparty/libuv/src/unix/thread.c
index c56a3170259..c35bc926bf0 100644
--- a/3rdparty/libuv/src/unix/thread.c
+++ b/3rdparty/libuv/src/unix/thread.c
@@ -27,6 +27,9 @@
#include <errno.h>
#include <sys/time.h>
+#include <sys/resource.h> /* getrlimit() */
+
+#include <limits.h>
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
@@ -55,6 +58,11 @@ static void* uv__thread_start(void *arg)
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
struct thread_ctx* ctx;
int err;
+ pthread_attr_t* attr;
+#if defined(__APPLE__)
+ pthread_attr_t attr_storage;
+ struct rlimit lim;
+#endif
ctx = uv__malloc(sizeof(*ctx));
if (ctx == NULL)
@@ -63,7 +71,30 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
ctx->entry = entry;
ctx->arg = arg;
- err = pthread_create(tid, NULL, uv__thread_start, ctx);
+ /* On OSX threads other than the main thread are created with a reduced stack
+ * size by default, adjust it to RLIMIT_STACK.
+ */
+#if defined(__APPLE__)
+ if (getrlimit(RLIMIT_STACK, &lim))
+ abort();
+
+ attr = &attr_storage;
+ if (pthread_attr_init(attr))
+ abort();
+
+ if (lim.rlim_cur != RLIM_INFINITY &&
+ lim.rlim_cur >= PTHREAD_STACK_MIN) {
+ if (pthread_attr_setstacksize(attr, lim.rlim_cur))
+ abort();
+ }
+#else
+ attr = NULL;
+#endif
+
+ err = pthread_create(tid, attr, uv__thread_start, ctx);
+
+ if (attr != NULL)
+ pthread_attr_destroy(attr);
if (err)
uv__free(ctx);
diff --git a/3rdparty/libuv/src/unix/tty.c b/3rdparty/libuv/src/unix/tty.c
index 7cc5b714ed3..32fa37eac96 100644
--- a/3rdparty/libuv/src/unix/tty.c
+++ b/3rdparty/libuv/src/unix/tty.c
@@ -23,6 +23,7 @@
#include "internal.h"
#include "spinlock.h"
+#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <termios.h>
@@ -33,12 +34,30 @@ static int orig_termios_fd = -1;
static struct termios orig_termios;
static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER;
+static int uv__tty_is_slave(const int fd) {
+ int result;
+#if defined(__linux__) || defined(__FreeBSD__)
+ int dummy;
+
+ result = ioctl(fd, TIOCGPTN, &dummy) != 0;
+#elif defined(__APPLE__)
+ char dummy[256];
+
+ result = ioctl(fd, TIOCPTYGNAME, &dummy) != 0;
+#else
+ /* Fallback to ptsname
+ */
+ result = ptsname(fd) == NULL;
+#endif
+ return result;
+}
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
uv_handle_type type;
int flags;
int newfd;
int r;
+ char path[256];
/* File descriptors that refer to files cannot be monitored with epoll.
* That restriction also applies to character devices like /dev/random
@@ -62,7 +81,15 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
* other processes.
*/
if (type == UV_TTY) {
- r = uv__open_cloexec("/dev/tty", O_RDWR);
+ /* Reopening a pty in master mode won't work either because the reopened
+ * pty will be in slave mode (*BSD) or reopening will allocate a new
+ * master/slave pair (Linux). Therefore check if the fd points to a
+ * slave device.
+ */
+ if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0)
+ r = uv__open_cloexec(path, O_RDWR);
+ else
+ r = -1;
if (r < 0) {
/* fallback to using blocking writes */
@@ -185,8 +212,13 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
struct winsize ws;
+ int err;
+
+ do
+ err = ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws);
+ while (err == -1 && errno == EINTR);
- if (ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws))
+ if (err == -1)
return -errno;
*width = ws.ws_col;