summaryrefslogtreecommitdiffstats
path: root/Utilities/cmlibuv/src/unix/stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/unix/stream.c')
-rw-r--r--Utilities/cmlibuv/src/unix/stream.c44
1 files changed, 20 insertions, 24 deletions
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index 4159cdc..52e2b9a 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -58,20 +58,6 @@ struct uv__stream_select_s {
fd_set* swrite;
size_t swrite_sz;
};
-
-/* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
- * EPROTOTYPE can be returned while trying to write to a socket that is
- * shutting down. If we retry the write, we should get the expected EPIPE
- * instead.
- */
-# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR || errno == EPROTOTYPE)
-# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
- (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
- (errno == EMSGSIZE && send_handle != NULL))
-#else
-# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR)
-# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
- (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
#endif /* defined(__APPLE__) */
static void uv__stream_connect(uv_stream_t*);
@@ -866,19 +852,33 @@ static int uv__try_write(uv_stream_t* stream,
do
n = sendmsg(uv__stream_fd(stream), &msg, 0);
- while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
+ while (n == -1 && errno == EINTR);
} else {
do
n = uv__writev(uv__stream_fd(stream), iov, iovcnt);
- while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
+ while (n == -1 && errno == EINTR);
}
if (n >= 0)
return n;
- if (IS_TRANSIENT_WRITE_ERROR(errno, send_handle))
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
return UV_EAGAIN;
+#ifdef __APPLE__
+ /* macOS versions 10.10 and 10.15 - and presumbaly 10.11 to 10.14, too -
+ * have a bug where a race condition causes the kernel to return EPROTOTYPE
+ * because the socket isn't fully constructed. It's probably the result of
+ * the peer closing the connection and that is why libuv translates it to
+ * ECONNRESET. Previously, libuv retried until the EPROTOTYPE error went
+ * away but some VPN software causes the same behavior except the error is
+ * permanent, not transient, turning the retry mechanism into an infinite
+ * loop. See https://github.com/libuv/libuv/pull/482.
+ */
+ if (errno == EPROTOTYPE)
+ return UV_ECONNRESET;
+#endif /* __APPLE__ */
+
return UV__ERR(errno);
}
@@ -1010,7 +1010,6 @@ uv_handle_type uv__handle_type(int fd) {
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_HANDLE_READ_EOF;
stream->flags &= ~UV_HANDLE_READING;
- stream->flags &= ~UV_HANDLE_READABLE;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
@@ -1550,15 +1549,12 @@ int uv__read_start(uv_stream_t* stream,
assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
stream->type == UV_TTY);
- /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just
- * expresses the desired state of the user.
- */
+ /* The UV_HANDLE_READING flag is irrelevant of the state of the stream - it
+ * just expresses the desired state of the user. */
stream->flags |= UV_HANDLE_READING;
+ stream->flags &= ~UV_HANDLE_READ_EOF;
/* TODO: try to do the read inline? */
- /* TODO: keep track of tcp state. If we've gotten a EOF then we should
- * not start the IO watcher.
- */
assert(uv__stream_fd(stream) >= 0);
assert(alloc_cb);