From fe43296f7fd11171ebd73c0e6d248b9c6da5279d Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Thu, 17 Feb 2022 06:58:21 +0100 Subject: [PATCH] chore: backport EPROTOTYPE fixes from libuv (#32856) This commit backports three commits from libuv's 1.x branch to fix issues with CPU going to 100% on macOS when EPROTOTYPE is returned. See: https://github.com/libuv/libuv/commit/abb109f30f7c0b3615b75156376d2e886c365df8 See: https://github.com/libuv/libuv/commit/3a7b95593acaab9739404bd120baa62c2007a18a See: https://github.com/libuv/libuv/commit/de24da8c111687a2871d528052f5442e9b371ca1 --- patches/node/.patches | 3 + ...imum_supported_version_to_10_15_3406.patch | 25 +++++++ ...ove_eprototype_error_workaround_3405.patch | 65 +++++++++++++++++++ ...nslate_eprototype_to_econnreset_3413.patch | 44 +++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 patches/node/darwin_bump_minimum_supported_version_to_10_15_3406.patch create mode 100644 patches/node/darwin_remove_eprototype_error_workaround_3405.patch create mode 100644 patches/node/darwin_translate_eprototype_to_econnreset_3413.patch diff --git a/patches/node/.patches b/patches/node/.patches index 7824d1d885c8..55ddb7c5a228 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -28,3 +28,6 @@ fix_crash_caused_by_gethostnamew_on_windows_7.patch fix_suppress_clang_-wdeprecated-declarations_in_libuv.patch fix_don_t_create_console_window_when_creating_process.patch fix_serdes_test.patch +darwin_remove_eprototype_error_workaround_3405.patch +darwin_translate_eprototype_to_econnreset_3413.patch +darwin_bump_minimum_supported_version_to_10_15_3406.patch diff --git a/patches/node/darwin_bump_minimum_supported_version_to_10_15_3406.patch b/patches/node/darwin_bump_minimum_supported_version_to_10_15_3406.patch new file mode 100644 index 000000000000..43023e3d0225 --- /dev/null +++ b/patches/node/darwin_bump_minimum_supported_version_to_10_15_3406.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ben Noordhuis +Date: Tue, 8 Feb 2022 14:18:29 +0100 +Subject: darwin: bump minimum supported version to 10.15 (#3406) + +We can't realistically claim to support 10.7 or any version that Apple +no longer supports so let's bump the baseline to something more +realistic. + +Refs: https://github.com/libuv/libuv/pull/482 +Refs: https://github.com/libuv/libuv/pull/3405 + +diff --git a/deps/uv/SUPPORTED_PLATFORMS.md b/deps/uv/SUPPORTED_PLATFORMS.md +index 30e0ea617a6fcaa5b4b7c7c5b117652e61f367d3..dc57dfb12dc7ddf8d29308ac44f46084a933d5ca 100644 +--- a/deps/uv/SUPPORTED_PLATFORMS.md ++++ b/deps/uv/SUPPORTED_PLATFORMS.md +@@ -3,7 +3,7 @@ + | System | Support type | Supported versions | Notes | + |---|---|---|---| + | GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | | +-| macOS | Tier 1 | macOS >= 10.7 | | ++| macOS | Tier 1 | macOS >= 10.15 | Current and previous macOS release | + | Windows | Tier 1 | >= Windows 8 | VS 2015 and later are supported | + | FreeBSD | Tier 1 | >= 10 | | + | AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix | diff --git a/patches/node/darwin_remove_eprototype_error_workaround_3405.patch b/patches/node/darwin_remove_eprototype_error_workaround_3405.patch new file mode 100644 index 000000000000..60dc8b799e4b --- /dev/null +++ b/patches/node/darwin_remove_eprototype_error_workaround_3405.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ben Noordhuis +Date: Sun, 9 Jan 2022 12:20:15 +0100 +Subject: darwin: remove EPROTOTYPE error workaround (#3405) + +It's been reported in the past that OS X 10.10, because of a race +condition in the XNU kernel, sometimes returns a transient EPROTOTYPE +error when trying to write to a socket. Libuv handles that by retrying +the operation until it succeeds or fails with a different error. + +Recently it's been reported that current versions of the operating +system formerly known as OS X fail permanently with EPROTOTYPE under +certain conditions, resulting in an infinite loop. + +Because Apple isn't exactly forthcoming with bug fixes or even details, +I'm opting to simply remove the workaround and have the error bubble up. + +Refs: https://github.com/libuv/libuv/pull/482 + +diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c +index bc64fe8f44b26d9f4c0d4d0d282b65cdf11a531b..1af448e7691392c3f7794eed1905d9132394e207 100644 +--- a/deps/uv/src/unix/stream.c ++++ b/deps/uv/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,17 +852,17 @@ 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; + + return UV__ERR(errno); diff --git a/patches/node/darwin_translate_eprototype_to_econnreset_3413.patch b/patches/node/darwin_translate_eprototype_to_econnreset_3413.patch new file mode 100644 index 000000000000..903921bce934 --- /dev/null +++ b/patches/node/darwin_translate_eprototype_to_econnreset_3413.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ben Noordhuis +Date: Wed, 12 Jan 2022 16:11:43 +0100 +Subject: darwin: translate EPROTOTYPE to ECONNRESET (#3413) + +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. + +Refs: https://github.com/libuv/libuv/pull/482 +Refs: https://github.com/libuv/libuv/pull/3405 + +diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c +index 1af448e7691392c3f7794eed1905d9132394e207..9d22debf2bf5bd5912ade152e55a85ad652e3819 100644 +--- a/deps/uv/src/unix/stream.c ++++ b/deps/uv/src/unix/stream.c +@@ -865,6 +865,20 @@ static int uv__try_write(uv_stream_t* stream, + 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); + } +