diff options
Diffstat (limited to '3rdparty/libuv/src/unix')
-rw-r--r-- | 3rdparty/libuv/src/unix/aix.c | 63 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/core.c | 194 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/fs.c | 17 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/internal.h | 31 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/kqueue.c | 21 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/linux-core.c | 77 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/linux-syscalls.h | 1 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/pipe.c | 11 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/poll.c | 16 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/process.c | 6 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/stream.c | 22 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/sunos.c | 11 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/thread.c | 33 | ||||
-rw-r--r-- | 3rdparty/libuv/src/unix/tty.c | 36 |
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; |