summaryrefslogtreecommitdiff
path: root/deps/uv/src/unix
diff options
context:
space:
mode:
authorTimothy J Fontaine <tjfontaine@gmail.com>2014-03-10 17:01:21 -0700
committerTimothy J Fontaine <tjfontaine@gmail.com>2014-03-10 17:01:21 -0700
commite92d35d80be6e193cb547e94c6fbf3654542dbaa (patch)
treebede6f090b8cca1397728634b03b31cfa7a4334c /deps/uv/src/unix
parentb444392a98e66b49dfee8c7e36c59d4e7c6ea1ac (diff)
downloadandroid-node-v8-e92d35d80be6e193cb547e94c6fbf3654542dbaa.tar.gz
android-node-v8-e92d35d80be6e193cb547e94c6fbf3654542dbaa.tar.bz2
android-node-v8-e92d35d80be6e193cb547e94c6fbf3654542dbaa.zip
uv: Upgrade to v0.11.22
Diffstat (limited to 'deps/uv/src/unix')
-rw-r--r--deps/uv/src/unix/core.c111
-rw-r--r--deps/uv/src/unix/fs.c4
-rw-r--r--deps/uv/src/unix/internal.h12
-rw-r--r--deps/uv/src/unix/kqueue.c6
-rw-r--r--deps/uv/src/unix/linux-syscalls.c21
-rw-r--r--deps/uv/src/unix/linux-syscalls.h1
-rw-r--r--deps/uv/src/unix/pipe.c28
-rw-r--r--deps/uv/src/unix/process.c7
-rw-r--r--deps/uv/src/unix/pthread-fixes.c23
-rw-r--r--deps/uv/src/unix/stream.c290
-rw-r--r--deps/uv/src/unix/tty.c65
11 files changed, 413 insertions, 155 deletions
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index a84304497c..b393097fd2 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -59,6 +59,15 @@
# include <sys/filio.h>
# include <sys/ioctl.h>
# include <sys/wait.h>
+# define UV__O_CLOEXEC O_CLOEXEC
+# if __FreeBSD__ >= 10
+# define uv__accept4 accept4
+# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
+# define UV__SOCK_CLOEXEC SOCK_CLOEXEC
+# endif
+# if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC)
+# define F_DUP2FD_CLOEXEC _F_DUP2FD_CLOEXEC
+# endif
#endif
static void uv__run_pending(uv_loop_t* loop);
@@ -371,7 +380,7 @@ int uv__accept(int sockfd) {
assert(sockfd >= 0);
while (1) {
-#if defined(__linux__)
+#if defined(__linux__) || __FreeBSD__ >= 10
static int no_accept4;
if (no_accept4)
@@ -589,16 +598,14 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
}
-int uv_cwd(char* buffer, size_t size) {
- if (buffer == NULL)
- return -EINVAL;
-
- if (size == 0)
+int uv_cwd(char* buffer, size_t* size) {
+ if (buffer == NULL || size == NULL)
return -EINVAL;
- if (getcwd(buffer, size) == NULL)
+ if (getcwd(buffer, *size) == NULL)
return -errno;
+ *size = strlen(buffer);
return 0;
}
@@ -817,3 +824,93 @@ int uv_getrusage(uv_rusage_t* rusage) {
return 0;
}
+
+
+int uv__open_cloexec(const char* path, int flags) {
+ int err;
+ int fd;
+
+#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 9)
+ static int no_cloexec;
+
+ if (!no_cloexec) {
+ fd = open(path, flags | UV__O_CLOEXEC);
+ if (fd != -1)
+ return fd;
+
+ if (errno != EINVAL)
+ return -errno;
+
+ /* O_CLOEXEC not supported. */
+ no_cloexec = 1;
+ }
+#endif
+
+ fd = open(path, flags);
+ if (fd == -1)
+ return -errno;
+
+ err = uv__cloexec(fd, 1);
+ if (err) {
+ uv__close(fd);
+ return err;
+ }
+
+ return fd;
+}
+
+
+int uv__dup2_cloexec(int oldfd, int newfd) {
+ int r;
+#if defined(__FreeBSD__) && __FreeBSD__ >= 10
+ do
+ r = dup3(oldfd, newfd, O_CLOEXEC);
+ while (r == -1 && errno == EINTR);
+ if (r == -1)
+ return -errno;
+ return r;
+#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
+ do
+ r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
+ while (r == -1 && errno == EINTR);
+ if (r != -1)
+ return r;
+ if (errno != EINVAL)
+ return -errno;
+ /* Fall through. */
+#elif defined(__linux__)
+ static int no_dup3;
+ if (!no_dup3) {
+ do
+ r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
+ while (r == -1 && (errno == EINTR || errno == EBUSY));
+ if (r != -1)
+ return r;
+ if (errno != ENOSYS)
+ return -errno;
+ /* Fall through. */
+ no_dup3 = 1;
+ }
+#endif
+ {
+ int err;
+ do
+ r = dup2(oldfd, newfd);
+#if defined(__linux__)
+ while (r == -1 && (errno == EINTR || errno == EBUSY));
+#else
+ while (r == -1 && errno == EINTR);
+#endif
+
+ if (r == -1)
+ return -errno;
+
+ err = uv__cloexec(newfd, 1);
+ if (err) {
+ uv__close(newfd);
+ return err;
+ }
+
+ return r;
+ }
+}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index b06f992dc7..cf45669cd9 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -271,7 +271,11 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
}
+#if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8))
+static int uv__fs_readdir_filter(struct dirent* dent) {
+#else
static int uv__fs_readdir_filter(const struct dirent* dent) {
+#endif
return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
}
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 4a4656a562..61f5f6aa2f 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -120,6 +120,8 @@
# define O_CLOEXEC 0x00100000
#endif
+typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
+
/* handle flags */
enum {
UV_CLOSING = 0x01, /* uv_close() called but not finished. */
@@ -142,6 +144,13 @@ typedef enum {
UV_CLOCK_FAST = 1 /* Use the fastest clock with <= 1ms granularity. */
} uv_clocktype_t;
+struct uv__stream_queued_fds_s {
+ unsigned int size;
+ unsigned int offset;
+ int fds[1];
+};
+
+
/* core */
int uv__nonblock(int fd, int set);
int uv__close(int fd);
@@ -180,6 +189,8 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd);
#endif /* defined(__APPLE__) */
void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
int uv__accept(int sockfd);
+int uv__dup2_cloexec(int oldfd, int newfd);
+int uv__open_cloexec(const char* path, int flags);
/* tcp */
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
@@ -226,6 +237,7 @@ void uv__tcp_close(uv_tcp_t* handle);
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);
#if defined(__APPLE__)
int uv___stream_fd(uv_stream_t* handle);
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index 5a25e117c9..77064175d6 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -383,10 +383,10 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
#if defined(__APPLE__)
if (uv__fsevents_close(handle))
- uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN);
-#else
- uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN);
#endif /* defined(__APPLE__) */
+ {
+ uv__io_close(handle->loop, &handle->event_watcher);
+ }
free(handle->path);
handle->path = NULL;
diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c
index c9cc44d8cd..1ff8abd197 100644
--- a/deps/uv/src/unix/linux-syscalls.c
+++ b/deps/uv/src/unix/linux-syscalls.c
@@ -219,6 +219,16 @@
# endif
#endif /* __NR_pwritev */
+#ifndef __NR_dup3
+# if defined(__x86_64__)
+# define __NR_dup3 292
+# elif defined(__i386__)
+# define __NR_dup3 330
+# elif defined(__arm__)
+# define __NR_dup3 (UV_SYSCALL_BASE + 358)
+# endif
+#endif /* __NR_pwritev */
+
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
#if defined(__i386__)
@@ -407,6 +417,7 @@ int uv__utimesat(int dirfd,
#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);
@@ -415,6 +426,7 @@ ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
#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);
@@ -422,3 +434,12 @@ ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
return errno = ENOSYS, -1;
#endif
}
+
+
+int uv__dup3(int oldfd, int newfd, int flags) {
+#if defined(__NR_dup3)
+ return syscall(__NR_dup3, oldfd, newfd, flags);
+#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 6d9ec9f22c..0f0b34b1ed 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -149,5 +149,6 @@ int uv__utimesat(int dirfd,
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);
+int uv__dup3(int oldfd, int newfd, int flags);
#endif /* UV_LINUX_SYSCALL_H_ */
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index 34c118b773..a26c3dbc13 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -246,3 +246,31 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) {
void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
}
+
+
+int uv_pipe_pending_count(uv_pipe_t* handle) {
+ uv__stream_queued_fds_t* queued_fds;
+
+ if (!handle->ipc)
+ return 0;
+
+ if (handle->accepted_fd == -1)
+ return 0;
+
+ if (handle->queued_fds == NULL)
+ return 1;
+
+ queued_fds = handle->queued_fds;
+ return queued_fds->offset + 1;
+}
+
+
+uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
+ if (!handle->ipc)
+ return UV_UNKNOWN_HANDLE;
+
+ if (handle->accepted_fd == -1)
+ return UV_UNKNOWN_HANDLE;
+ else
+ return uv__handle_type(handle->accepted_fd);
+}
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
index 55f6ac5806..53fef8436b 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -302,8 +302,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
close_fd = use_fd;
if (use_fd == -1) {
- uv__write_int(error_fd, -errno);
- perror("failed to open stdio");
+ uv__write_int(error_fd, -errno);
_exit(127);
}
}
@@ -330,7 +329,6 @@ static void uv__process_child_init(const uv_process_options_t* options,
if (options->cwd != NULL && chdir(options->cwd)) {
uv__write_int(error_fd, -errno);
- perror("chdir()");
_exit(127);
}
@@ -347,13 +345,11 @@ static void uv__process_child_init(const uv_process_options_t* options,
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
uv__write_int(error_fd, -errno);
- perror("setgid()");
_exit(127);
}
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
uv__write_int(error_fd, -errno);
- perror("setuid()");
_exit(127);
}
@@ -363,7 +359,6 @@ static void uv__process_child_init(const uv_process_options_t* options,
execvp(options->file, options->args);
uv__write_int(error_fd, -errno);
- perror("execvp()");
_exit(127);
}
diff --git a/deps/uv/src/unix/pthread-fixes.c b/deps/uv/src/unix/pthread-fixes.c
index 2e4c542bc2..dc54f35d60 100644
--- a/deps/uv/src/unix/pthread-fixes.c
+++ b/deps/uv/src/unix/pthread-fixes.c
@@ -29,6 +29,29 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/* Android versions < 4.1 have a broken pthread_sigmask.
+ * Note that this block of code must come before any inclusion of
+ * pthread-fixes.h so that the real pthread_sigmask can be referenced.
+ * */
+#include <errno.h>
+#include <pthread.h>
+
+int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) {
+ static int workaround;
+
+ if (workaround) {
+ return sigprocmask(how, set, oset);
+ } else if (pthread_sigmask(how, set, oset)) {
+ if (errno == EINVAL && sigprocmask(how, set, oset) == 0) {
+ workaround = 1;
+ return 0;
+ } else {
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+}
/*Android doesn't provide pthread_barrier_t for now.*/
#ifndef PTHREAD_BARRIER_SERIAL_THREAD
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index ad6856b4b7..370894bfd6 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -63,36 +63,6 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
static size_t uv__write_req_size(uv_write_t* req);
-/* Used by the accept() EMFILE party trick. */
-static int uv__open_cloexec(const char* path, int flags) {
- int err;
- int fd;
-
-#if defined(__linux__)
- fd = open(path, flags | UV__O_CLOEXEC);
- if (fd != -1)
- return fd;
-
- if (errno != EINVAL)
- return -errno;
-
- /* O_CLOEXEC not supported. */
-#endif
-
- fd = open(path, flags);
- if (fd == -1)
- return -errno;
-
- err = uv__cloexec(fd, 1);
- if (err) {
- uv__close(fd);
- return err;
- }
-
- return fd;
-}
-
-
static size_t uv_count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
unsigned int i;
size_t bytes;
@@ -112,13 +82,13 @@ void uv__stream_init(uv_loop_t* loop,
uv__handle_init(loop, (uv_handle_t*)stream, type);
stream->read_cb = NULL;
- stream->read2_cb = NULL;
stream->alloc_cb = NULL;
stream->close_cb = NULL;
stream->connection_cb = NULL;
stream->connect_req = NULL;
stream->shutdown_req = NULL;
stream->accepted_fd = -1;
+ stream->queued_fds = NULL;
stream->delayed_error = 0;
QUEUE_INIT(&stream->write_queue);
QUEUE_INIT(&stream->write_completed_queue);
@@ -570,6 +540,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
if (server->accepted_fd == -1)
return -EAGAIN;
+ err = 0;
switch (client->type) {
case UV_NAMED_PIPE:
case UV_TCP:
@@ -579,8 +550,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
if (err) {
/* TODO handle error */
uv__close(server->accepted_fd);
- server->accepted_fd = -1;
- return err;
+ goto done;
}
break;
@@ -588,8 +558,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
err = uv_udp_open((uv_udp_t*) client, server->accepted_fd);
if (err) {
uv__close(server->accepted_fd);
- server->accepted_fd = -1;
- return err;
+ goto done;
}
break;
@@ -597,9 +566,33 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
assert(0);
}
- uv__io_start(server->loop, &server->io_watcher, UV__POLLIN);
- server->accepted_fd = -1;
- return 0;
+done:
+ /* Process queued fds */
+ if (server->queued_fds != NULL) {
+ uv__stream_queued_fds_t* queued_fds;
+
+ queued_fds = server->queued_fds;
+
+ /* Read first */
+ server->accepted_fd = queued_fds->fds[0];
+
+ /* All read, free */
+ assert(queued_fds->offset > 0);
+ if (--queued_fds->offset == 0) {
+ free(queued_fds);
+ server->queued_fds = NULL;
+ } else {
+ /* Shift rest */
+ memmove(queued_fds->fds,
+ queued_fds->fds + 1,
+ queued_fds->offset * sizeof(*queued_fds->fds));
+ }
+ } else {
+ server->accepted_fd = -1;
+ if (err == 0)
+ uv__io_start(server->loop, &server->io_watcher, UV__POLLIN);
+ }
+ return err;
}
@@ -777,12 +770,12 @@ start:
msg.msg_flags = 0;
msg.msg_control = (void*) scratch;
- msg.msg_controllen = CMSG_LEN(sizeof(fd_to_send));
+ msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = msg.msg_controllen;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send));
/* silence aliasing warning */
{
@@ -913,7 +906,7 @@ static void uv__write_callbacks(uv_stream_t* stream) {
}
-static uv_handle_type uv__handle_type(int fd) {
+uv_handle_type uv__handle_type(int fd) {
struct sockaddr_storage ss;
socklen_t len;
int type;
@@ -947,24 +940,106 @@ static uv_handle_type uv__handle_type(int fd) {
}
-static void uv__stream_read_cb(uv_stream_t* stream,
- int status,
- const uv_buf_t* buf,
- uv_handle_type type) {
- if (stream->read_cb != NULL)
- stream->read_cb(stream, status, buf);
- else
- stream->read2_cb((uv_pipe_t*) stream, status, buf, type);
-}
-
-
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_STREAM_READ_EOF;
uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
- uv__stream_read_cb(stream, UV_EOF, buf, UV_UNKNOWN_HANDLE);
+ stream->read_cb(stream, UV_EOF, buf);
+}
+
+
+static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
+ uv__stream_queued_fds_t* queued_fds;
+ unsigned int queue_size;
+
+ queued_fds = stream->queued_fds;
+ if (queued_fds == NULL) {
+ queue_size = 8;
+ queued_fds = malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
+ sizeof(*queued_fds));
+ if (queued_fds == NULL)
+ return -ENOMEM;
+ queued_fds->size = queue_size;
+ queued_fds->offset = 0;
+ stream->queued_fds = queued_fds;
+
+ /* Grow */
+ } else if (queued_fds->size == queued_fds->offset) {
+ queue_size = queued_fds->size + 8;
+ queued_fds = realloc(queued_fds,
+ (queue_size - 1) * sizeof(*queued_fds->fds) +
+ sizeof(*queued_fds));
+
+ /*
+ * Allocation failure, report back.
+ * NOTE: if it is fatal - sockets will be closed in uv__stream_close
+ */
+ if (queued_fds == NULL)
+ return -ENOMEM;
+ queued_fds->size = queue_size;
+ stream->queued_fds = queued_fds;
+ }
+
+ /* Put fd in a queue */
+ queued_fds->fds[queued_fds->offset++] = fd;
+
+ return 0;
+}
+
+
+#define UV__CMSG_FD_COUNT 64
+#define UV__CMSG_FD_SIZE (UV__CMSG_FD_COUNT * sizeof(int))
+
+
+static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) {
+ struct cmsghdr* cmsg;
+
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ char* start;
+ char* end;
+ int err;
+ void* pv;
+ int* pi;
+ unsigned int i;
+ unsigned int count;
+
+ if (cmsg->cmsg_type != SCM_RIGHTS) {
+ fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n",
+ cmsg->cmsg_type);
+ continue;
+ }
+
+ /* silence aliasing warning */
+ pv = CMSG_DATA(cmsg);
+ pi = pv;
+
+ /* Count available fds */
+ start = (char*) cmsg;
+ end = (char*) cmsg + cmsg->cmsg_len;
+ count = 0;
+ while (start + CMSG_LEN(count * sizeof(*pi)) < end)
+ count++;
+ assert(start + CMSG_LEN(count * sizeof(*pi)) == end);
+
+ for (i = 0; i < count; i++) {
+ /* Already has accepted fd, queue now */
+ if (stream->accepted_fd != -1) {
+ err = uv__stream_queue_fd(stream, pi[i]);
+ if (err != 0) {
+ /* Close rest */
+ for (; i < count; i++)
+ uv__close(pi[i]);
+ return err;
+ }
+ } else {
+ stream->accepted_fd = pi[i];
+ }
+ }
+ }
+
+ return 0;
}
@@ -972,9 +1047,10 @@ static void uv__read(uv_stream_t* stream) {
uv_buf_t buf;
ssize_t nread;
struct msghdr msg;
- struct cmsghdr* cmsg;
- char cmsg_space[64];
+ char cmsg_space[CMSG_SPACE(UV__CMSG_FD_SIZE)];
int count;
+ int err;
+ int is_ipc;
stream->flags &= ~UV_STREAM_READ_PARTIAL;
@@ -983,10 +1059,12 @@ static void uv__read(uv_stream_t* stream) {
*/
count = 32;
+ is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc;
+
/* XXX: Maybe instead of having UV_STREAM_READING we just test if
* tcp->read_cb is NULL or not?
*/
- while ((stream->read_cb || stream->read2_cb)
+ while (stream->read_cb
&& (stream->flags & UV_STREAM_READING)
&& (count-- > 0)) {
assert(stream->alloc_cb != NULL);
@@ -994,29 +1072,28 @@ static void uv__read(uv_stream_t* stream) {
stream->alloc_cb((uv_handle_t*)stream, 64 * 1024, &buf);
if (buf.len == 0) {
/* User indicates it can't or won't handle the read. */
- uv__stream_read_cb(stream, UV_ENOBUFS, &buf, UV_UNKNOWN_HANDLE);
+ stream->read_cb(stream, UV_ENOBUFS, &buf);
return;
}
assert(buf.base != NULL);
assert(uv__stream_fd(stream) >= 0);
- if (stream->read_cb) {
+ if (!is_ipc) {
do {
nread = read(uv__stream_fd(stream), buf.base, buf.len);
}
while (nread < 0 && errno == EINTR);
} else {
- assert(stream->read2_cb);
- /* read2_cb uses recvmsg */
+ /* ipc uses recvmsg */
msg.msg_flags = 0;
msg.msg_iov = (struct iovec*) &buf;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
/* Set up to receive a descriptor even if one isn't in the message */
- msg.msg_controllen = 64;
- msg.msg_control = (void*) cmsg_space;
+ msg.msg_controllen = sizeof(cmsg_space);
+ msg.msg_control = cmsg_space;
do {
nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
@@ -1032,10 +1109,10 @@ static void uv__read(uv_stream_t* stream) {
uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
uv__stream_osx_interrupt_select(stream);
}
- uv__stream_read_cb(stream, 0, &buf, UV_UNKNOWN_HANDLE);
+ stream->read_cb(stream, 0, &buf);
} else {
/* Error. User should call uv_close(). */
- uv__stream_read_cb(stream, -errno, &buf, UV_UNKNOWN_HANDLE);
+ stream->read_cb(stream, -errno, &buf);
assert(!uv__io_active(&stream->io_watcher, UV__POLLIN) &&
"stream->read_cb(status=-1) did not call uv_close()");
}
@@ -1047,50 +1124,14 @@ static void uv__read(uv_stream_t* stream) {
/* Successful read */
ssize_t buflen = buf.len;
- if (stream->read_cb) {
- stream->read_cb(stream, nread, &buf);
- } else {
- assert(stream->read2_cb);
-
- /*
- * XXX: Some implementations can send multiple file descriptors in a
- * single message. We should be using CMSG_NXTHDR() to walk the
- * chain to get at them all. This would require changing the API to
- * hand these back up the caller, is a pain.
- */
-
- for (cmsg = CMSG_FIRSTHDR(&msg);
- msg.msg_controllen > 0 && cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
-
- if (cmsg->cmsg_type == SCM_RIGHTS) {
- if (stream->accepted_fd != -1) {
- fprintf(stderr, "(libuv) ignoring extra FD received\n");
- }
-
- /* silence aliasing warning */
- {
- void* pv = CMSG_DATA(cmsg);
- int* pi = pv;
- stream->accepted_fd = *pi;
- }
-
- } else {
- fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n",
- cmsg->cmsg_type);
- }
- }
-
-
- if (stream->accepted_fd >= 0) {
- stream->read2_cb((uv_pipe_t*) stream,
- nread,
- &buf,
- uv__handle_type(stream->accepted_fd));
- } else {
- stream->read2_cb((uv_pipe_t*) stream, nread, &buf, UV_UNKNOWN_HANDLE);
+ if (is_ipc) {
+ err = uv__stream_recv_cmsg(stream, &msg);
+ if (err != 0) {
+ stream->read_cb(stream, err, NULL);
+ return;
}
}
+ stream->read_cb(stream, nread, &buf);
/* Return if we didn't fill the buffer, there is no more data to read. */
if (nread < buflen) {
@@ -1102,6 +1143,10 @@ static void uv__read(uv_stream_t* stream) {
}
+#undef UV__CMSG_FD_COUNT
+#undef UV__CMSG_FD_SIZE
+
+
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE) &&
"uv_shutdown (unix) only supports uv_handle_t right now");
@@ -1371,10 +1416,9 @@ int uv_try_write(uv_stream_t* stream,
}
-static int uv__read_start_common(uv_stream_t* stream,
- uv_alloc_cb alloc_cb,
- uv_read_cb read_cb,
- uv_read2_cb read2_cb) {
+int uv_read_start(uv_stream_t* stream,
+ uv_alloc_cb alloc_cb,
+ uv_read_cb read_cb) {
assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
stream->type == UV_TTY);
@@ -1394,7 +1438,6 @@ static int uv__read_start_common(uv_stream_t* stream,
assert(alloc_cb);
stream->read_cb = read_cb;
- stream->read2_cb = read2_cb;
stream->alloc_cb = alloc_cb;
uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
@@ -1405,18 +1448,6 @@ static int uv__read_start_common(uv_stream_t* stream,
}
-int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb,
- uv_read_cb read_cb) {
- return uv__read_start_common(stream, alloc_cb, read_cb, NULL);
-}
-
-
-int uv_read2_start(uv_stream_t* stream, uv_alloc_cb alloc_cb,
- uv_read2_cb read_cb) {
- return uv__read_start_common(stream, alloc_cb, NULL, read_cb);
-}
-
-
int uv_read_stop(uv_stream_t* stream) {
/* Sanity check. We're going to stop the handle unless it's primed for
* writing but that means there should be some kind of write action in
@@ -1435,7 +1466,6 @@ int uv_read_stop(uv_stream_t* stream) {
uv__stream_osx_interrupt_select(stream);
stream->read_cb = NULL;
- stream->read2_cb = NULL;
stream->alloc_cb = NULL;
return 0;
}
@@ -1469,6 +1499,9 @@ int uv___stream_fd(uv_stream_t* handle) {
void uv__stream_close(uv_stream_t* handle) {
+ unsigned int i;
+ uv__stream_queued_fds_t* queued_fds;
+
#if defined(__APPLE__)
/* Terminate select loop first */
if (handle->select != NULL) {
@@ -1506,6 +1539,15 @@ void uv__stream_close(uv_stream_t* handle) {
handle->accepted_fd = -1;
}
+ /* Close all queued fds */
+ if (handle->queued_fds != NULL) {
+ queued_fds = handle->queued_fds;
+ for (i = 0; i < queued_fds->offset; i++)
+ uv__close(queued_fds->fds[i]);
+ free(handle->queued_fds);
+ handle->queued_fds = NULL;
+ }
+
assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT));
}
diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c
index ca9459dd0d..c7ed101a75 100644
--- a/deps/uv/src/unix/tty.c
+++ b/deps/uv/src/unix/tty.c
@@ -35,26 +35,61 @@ static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER;
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
- uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY);
+ int flags;
+ int newfd;
+ int r;
+
+ newfd = -1;
+
+ uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY);
+
+ /* Reopen the file descriptor when it refers to a tty. This lets us put the
+ * tty in non-blocking mode without affecting other processes that share it
+ * with us.
+ *
+ * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also
+ * affects fd 1 of `cat` because both file descriptors refer to the same
+ * struct file in the kernel. When we reopen our fd 0, it points to a
+ * different struct file, hence changing its properties doesn't affect
+ * other processes.
+ */
+ if (isatty(fd)) {
+ newfd = uv__open_cloexec("/dev/tty", O_RDWR);
+
+ if (newfd == -1)
+ return -errno;
-#if defined(__APPLE__)
- {
- int err = uv__stream_try_select((uv_stream_t*) tty, &fd);
- if (err)
- return err;
+ r = uv__dup2_cloexec(newfd, fd);
+ if (r < 0 && r != -EINVAL) {
+ /* EINVAL means newfd == fd which could conceivably happen if another
+ * thread called close(fd) between our calls to isatty() and open().
+ * That's a rather unlikely event but let's handle it anyway.
+ */
+ uv__close(newfd);
+ return r;
+ }
+
+ fd = newfd;
}
-#endif /* defined(__APPLE__) */
-
- if (readable) {
- uv__nonblock(fd, 1);
- uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_READABLE);
- } else {
- /* Note: writable tty we set to blocking mode. */
- uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_WRITABLE);
- tty->flags |= UV_STREAM_BLOCKING;
+
+#if defined(__APPLE__)
+ r = uv__stream_try_select((uv_stream_t*) tty, &fd);
+ if (r) {
+ if (newfd != -1)
+ uv__close(newfd);
+ return r;
}
+#endif
+ if (readable)
+ flags = UV_STREAM_READABLE;
+ else
+ flags = UV_STREAM_WRITABLE;
+
+ uv__nonblock(fd, 1);
+ uv__stream_open((uv_stream_t*) tty, fd, flags);
tty->mode = 0;
+
return 0;
}