From 693823400720000986239d026fac6358813c93db Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Wed, 23 Mar 2022 15:51:10 +0900 Subject: [PATCH] chore: backport additional patches --- patches/node/.patches | 5 + ..._don_t_use_thread-unsafe_strtok_3524.patch | 54 ++++++ ...rocess_fix_hang_after_note_exit_3521.patch | 158 ++++++++++++++++++ ...ess_simplify_uv_write_int_calls_3519.patch | 63 +++++++ .../unix_remove_uv_cloexec_ioctl_3515.patch | 91 ++++++++++ .../unix_simplify_uv_cloexec_fcntl_3492.patch | 36 ++++ 6 files changed, 407 insertions(+) create mode 100644 patches/node/macos_don_t_use_thread-unsafe_strtok_3524.patch create mode 100644 patches/node/process_fix_hang_after_note_exit_3521.patch create mode 100644 patches/node/process_simplify_uv_write_int_calls_3519.patch create mode 100644 patches/node/unix_remove_uv_cloexec_ioctl_3515.patch create mode 100644 patches/node/unix_simplify_uv_cloexec_fcntl_3492.patch diff --git a/patches/node/.patches b/patches/node/.patches index a8b393617056a..2c7f73453169f 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -41,3 +41,8 @@ process_bsd_handle_kevent_note_exit_failure_3451.patch reland_macos_use_posix_spawn_instead_of_fork_3257.patch process_reset_the_signal_mask_if_the_fork_fails_3537.patch process_only_use_f_dupfd_cloexec_if_it_is_defined_3512.patch +unix_simplify_uv_cloexec_fcntl_3492.patch +unix_remove_uv_cloexec_ioctl_3515.patch +process_simplify_uv_write_int_calls_3519.patch +macos_don_t_use_thread-unsafe_strtok_3524.patch +process_fix_hang_after_note_exit_3521.patch diff --git a/patches/node/macos_don_t_use_thread-unsafe_strtok_3524.patch b/patches/node/macos_don_t_use_thread-unsafe_strtok_3524.patch new file mode 100644 index 0000000000000..69e57568216d0 --- /dev/null +++ b/patches/node/macos_don_t_use_thread-unsafe_strtok_3524.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ben Noordhuis +Date: Wed, 9 Mar 2022 11:06:39 +0100 +Subject: macos: don't use thread-unsafe strtok() (#3524) + +Refs https://github.com/libuv/libuv/pull/3524 + +diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c +index 8cde389b826b6b167437845eccd5fed440dcadc4..147164e7ea25abbf655452930d78ee0a714cce36 100644 +--- a/deps/uv/src/unix/process.c ++++ b/deps/uv/src/unix/process.c +@@ -387,30 +387,22 @@ static void uv__spawn_init_posix_spawn_fncs(void) { + + + static void uv__spawn_init_can_use_setsid(void) { +- static const int MACOS_CATALINA_VERSION_MAJOR = 19; +- char version_str[256]; +- char* version_major_str; +- size_t version_str_size = 256; +- int r; +- int version_major; +- +- /* Get a version string */ +- r = sysctlbyname("kern.osrelease", version_str, &version_str_size, NULL, 0); +- if (r != 0) ++ int which[] = {CTL_KERN, KERN_OSRELEASE}; ++ unsigned major; ++ unsigned minor; ++ unsigned patch; ++ char buf[256]; ++ size_t len; ++ ++ len = sizeof(buf); ++ if (sysctl(which, ARRAY_SIZE(which), buf, &len, NULL, 0)) + return; + +- /* Try to get the major version number. If not found +- * fall back to the fork/exec flow */ +- version_major_str = strtok(version_str, "."); +- if (version_major_str == NULL) ++ /* NULL specifies to use LC_C_LOCALE */ ++ if (3 != sscanf_l(buf, NULL, "%u.%u.%u", &major, &minor, &patch)) + return; + +- /* Parse the version major as a number. If it is greater than +- * the major version for macOS Catalina (aka macOS 10.15), then +- * the POSIX_SPAWN_SETSID flag is available */ +- version_major = atoi_l(version_major_str, NULL); /* Use LC_C_LOCALE */ +- if (version_major >= MACOS_CATALINA_VERSION_MAJOR) +- posix_spawn_can_use_setsid = 1; ++ posix_spawn_can_use_setsid = (major >= 19); /* macOS Catalina */ + } + + diff --git a/patches/node/process_fix_hang_after_note_exit_3521.patch b/patches/node/process_fix_hang_after_note_exit_3521.patch new file mode 100644 index 0000000000000..68702cf332b81 --- /dev/null +++ b/patches/node/process_fix_hang_after_note_exit_3521.patch @@ -0,0 +1,158 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jameson Nash +Date: Wed, 23 Mar 2022 15:39:38 +0900 +Subject: process: fix hang after NOTE_EXIT (#3521) + +Bug #3504 seems to affect more platforms than just OpenBSD. As this +seems to be a race condition in these kernels, we do not want to fail +because of it. Instead, we remove the WNOHANG flag from waitpid, and +track exactly which processes have exited. Should also be a slight speed +improvement for excessively large numbers of live children. + +diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c +index 071fe0ce0938657d0fb840af62a432352e938a8a..4c4d990ff5fa6c8ab937be2e4f79ccdaf90670c2 100644 +--- a/deps/uv/src/unix/kqueue.c ++++ b/deps/uv/src/unix/kqueue.c +@@ -117,6 +117,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { + unsigned int revents; + QUEUE* q; + uv__io_t* w; ++ uv_process_t* process; + sigset_t* pset; + sigset_t set; + uint64_t base; +@@ -284,12 +285,22 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { + loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; + for (i = 0; i < nfds; i++) { + ev = events + i; ++ fd = ev->ident; ++ ++ /* Handle kevent NOTE_EXIT results */ + if (ev->filter == EVFILT_PROC) { +- loop->flags |= UV_LOOP_REAP_CHILDREN; ++ QUEUE_FOREACH(q, &loop->process_handles) { ++ process = QUEUE_DATA(q, uv_process_t, queue); ++ if (process->pid == fd) { ++ process->flags |= UV_HANDLE_REAP; ++ loop->flags |= UV_LOOP_REAP_CHILDREN; ++ break; ++ } ++ } + nevents++; + continue; + } +- fd = ev->ident; ++ + /* Skip invalidated events, see uv__platform_invalidate_fd */ + if (fd == -1) + continue; +diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c +index 147164e7ea25abbf655452930d78ee0a714cce36..c8816b85b7e531648064e739fb89257565ad64bb 100644 +--- a/deps/uv/src/unix/process.c ++++ b/deps/uv/src/unix/process.c +@@ -63,12 +63,18 @@ extern char **environ; + # include "zos-base.h" + #endif + +-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ++#if defined(__APPLE__) || \ ++ defined(__DragonFly__) || \ ++ defined(__FreeBSD__) || \ ++ defined(__NetBSD__) || \ ++ defined(__OpenBSD__) + #include ++#else ++#define UV_USE_SIGCHLD + #endif + + +-#if !(defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) ++#ifdef UV_USE_SIGCHLD + static void uv__chld(uv_signal_t* handle, int signum) { + assert(signum == SIGCHLD); + uv__wait_children(handle->loop); +@@ -80,6 +86,7 @@ void uv__wait_children(uv_loop_t* loop) { + int exit_status; + int term_signal; + int status; ++ int options; + pid_t pid; + QUEUE pending; + QUEUE* q; +@@ -93,19 +100,33 @@ void uv__wait_children(uv_loop_t* loop) { + process = QUEUE_DATA(q, uv_process_t, queue); + q = QUEUE_NEXT(q); + ++#ifndef UV_USE_SIGCHLD ++ if ((process->flags & UV_HANDLE_REAP) == 0) ++ continue; ++ options = 0; ++ process->flags &= ~UV_HANDLE_REAP; ++#else ++ options = WNOHANG; ++#endif ++ + do +- pid = waitpid(process->pid, &status, WNOHANG); ++ pid = waitpid(process->pid, &status, options); + while (pid == -1 && errno == EINTR); + +- if (pid == 0) ++#ifdef UV_USE_SIGCHLD ++ if (pid == 0) /* Not yet exited */ + continue; ++#endif + + if (pid == -1) { + if (errno != ECHILD) + abort(); ++ /* The child died, and we missed it. This probably means someone else ++ * stole the waitpid from us. Handle this by not handling it at all. */ + continue; + } + ++ assert(pid == process->pid); + process->status = status; + QUEUE_REMOVE(&process->queue); + QUEUE_INSERT_TAIL(&pending, &process->queue); +@@ -964,7 +985,7 @@ int uv_spawn(uv_loop_t* loop, + goto error; + } + +-#if !(defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) ++#ifdef UV_USE_SIGCHLD + uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); + #endif + +@@ -983,13 +1004,14 @@ int uv_spawn(uv_loop_t* loop, + * fail to open a stdio handle. This ensures we can eventually reap the child + * with waitpid. */ + if (exec_errorno == 0) { +-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ++#ifndef UV_USE_SIGCHLD + struct kevent event; + EV_SET(&event, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, 0); + if (kevent(loop->backend_fd, &event, 1, NULL, 0, NULL)) { + if (errno != ESRCH) + abort(); + /* Process already exited. Call waitpid on the next loop iteration. */ ++ process->flags |= UV_HANDLE_REAP; + loop->flags |= UV_LOOP_REAP_CHILDREN; + } + #endif +diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h +index 8a190bf8fa8c5a282feaf251aec2a30c95776888..6001b0cf68d0b0268b578218b664a737f43c9521 100644 +--- a/deps/uv/src/uv-common.h ++++ b/deps/uv/src/uv-common.h +@@ -130,7 +130,10 @@ enum { + UV_SIGNAL_ONE_SHOT = 0x02000000, + + /* Only used by uv_poll_t handles. */ +- UV_HANDLE_POLL_SLOW = 0x01000000 ++ UV_HANDLE_POLL_SLOW = 0x01000000, ++ ++ /* Only used by uv_process_t handles. */ ++ UV_HANDLE_REAP = 0x10000000 + }; + + int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); diff --git a/patches/node/process_simplify_uv_write_int_calls_3519.patch b/patches/node/process_simplify_uv_write_int_calls_3519.patch new file mode 100644 index 0000000000000..201c9c949d49a --- /dev/null +++ b/patches/node/process_simplify_uv_write_int_calls_3519.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jameson Nash +Date: Mon, 7 Mar 2022 17:07:49 -0500 +Subject: process: simplify uv__write_int calls (#3519) + +Refs https://github.com/libuv/libuv/pull/3519 + +diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c +index b6f9756c6a6710f5f10762b9299cc35047b98097..8cde389b826b6b167437845eccd5fed440dcadc4 100644 +--- a/deps/uv/src/unix/process.c ++++ b/deps/uv/src/unix/process.c +@@ -216,16 +216,14 @@ static void uv__write_int(int fd, int val) { + n = write(fd, &val, sizeof(val)); + while (n == -1 && errno == EINTR); + +- if (n == -1 && errno == EPIPE) +- return; /* parent process has quit */ +- +- assert(n == sizeof(val)); ++ /* The write might have failed (e.g. if the parent process has died), ++ * but we have nothing left but to _exit ourself now too. */ ++ _exit(127); + } + + + static void uv__write_errno(int error_fd) { + uv__write_int(error_fd, UV__ERR(errno)); +- _exit(127); + } + + +@@ -284,10 +282,8 @@ static void uv__process_child_init(const uv_process_options_t* options, + uv__write_errno(error_fd); + #ifndef F_DUPFD_CLOEXEC /* POSIX 2008 */ + n = uv__cloexec(pipes[fd][1], 1); +- if (n) { ++ if (n) + uv__write_int(error_fd, n); +- _exit(127); +- } + #endif + } + +@@ -313,10 +309,8 @@ static void uv__process_child_init(const uv_process_options_t* options, + if (fd == use_fd) { + if (close_fd == -1) { + n = uv__cloexec(use_fd, 0); +- if (n) { ++ if (n) + uv__write_int(error_fd, n); +- _exit(127); +- } + } + } + else { +@@ -368,7 +362,6 @@ static void uv__process_child_init(const uv_process_options_t* options, + #endif + + uv__write_errno(error_fd); +- abort(); + } + #endif + diff --git a/patches/node/unix_remove_uv_cloexec_ioctl_3515.patch b/patches/node/unix_remove_uv_cloexec_ioctl_3515.patch new file mode 100644 index 0000000000000..f49d25998bba2 --- /dev/null +++ b/patches/node/unix_remove_uv_cloexec_ioctl_3515.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jameson Nash +Date: Sun, 6 Mar 2022 15:01:33 -0500 +Subject: unix: remove uv__cloexec_ioctl() (#3515) + +Now that uv__cloexec_fcntl() is simplified +(https://github.com/libuv/libuv/pull/3492), there is no benefit to +maintaining duplicate code paths for the same thing. + +diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c +index 6cd519ad5b3e7af8f5c71b18a59b88458a233f15..8c30802ad15316a8ec20ecedfb5123174d74276b 100644 +--- a/deps/uv/src/unix/core.c ++++ b/deps/uv/src/unix/core.c +@@ -597,20 +597,6 @@ int uv__nonblock_ioctl(int fd, int set) { + + return 0; + } +- +- +-int uv__cloexec_ioctl(int fd, int set) { +- int r; +- +- do +- r = ioctl(fd, set ? FIOCLEX : FIONCLEX); +- while (r == -1 && errno == EINTR); +- +- if (r) +- return UV__ERR(errno); +- +- return 0; +-} + #endif + + +@@ -645,7 +631,7 @@ int uv__nonblock_fcntl(int fd, int set) { + } + + +-int uv__cloexec_fcntl(int fd, int set) { ++int uv__cloexec(int fd, int set) { + int flags; + int r; + +diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h +index 2dcc8b32f5165dd75061a1b55cc1abd2ab93ccc9..543993989b8765247e140e9d950a25192e5e1ca5 100644 +--- a/deps/uv/src/unix/internal.h ++++ b/deps/uv/src/unix/internal.h +@@ -175,11 +175,9 @@ struct uv__stream_queued_fds_s { + defined(__linux__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) +-#define uv__cloexec uv__cloexec_ioctl + #define uv__nonblock uv__nonblock_ioctl + #define UV__NONBLOCK_IS_IOCTL 1 + #else +-#define uv__cloexec uv__cloexec_fcntl + #define uv__nonblock uv__nonblock_fcntl + #define UV__NONBLOCK_IS_IOCTL 0 + #endif +@@ -197,8 +195,7 @@ struct uv__stream_queued_fds_s { + #endif + + /* core */ +-int uv__cloexec_ioctl(int fd, int set); +-int uv__cloexec_fcntl(int fd, int set); ++int uv__cloexec(int fd, int set); + int uv__nonblock_ioctl(int fd, int set); + int uv__nonblock_fcntl(int fd, int set); + int uv__close(int fd); /* preserves errno */ +diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c +index 7705068730cb0536998bad7d304cb87df99b72e8..b6f9756c6a6710f5f10762b9299cc35047b98097 100644 +--- a/deps/uv/src/unix/process.c ++++ b/deps/uv/src/unix/process.c +@@ -283,7 +283,7 @@ static void uv__process_child_init(const uv_process_options_t* options, + if (pipes[fd][1] == -1) + uv__write_errno(error_fd); + #ifndef F_DUPFD_CLOEXEC /* POSIX 2008 */ +- n = uv__cloexec_fcntl(pipes[fd][1], 1); ++ n = uv__cloexec(pipes[fd][1], 1); + if (n) { + uv__write_int(error_fd, n); + _exit(127); +@@ -312,7 +312,7 @@ static void uv__process_child_init(const uv_process_options_t* options, + + if (fd == use_fd) { + if (close_fd == -1) { +- n = uv__cloexec_fcntl(use_fd, 0); ++ n = uv__cloexec(use_fd, 0); + if (n) { + uv__write_int(error_fd, n); + _exit(127); diff --git a/patches/node/unix_simplify_uv_cloexec_fcntl_3492.patch b/patches/node/unix_simplify_uv_cloexec_fcntl_3492.patch new file mode 100644 index 0000000000000..219ae54daa15b --- /dev/null +++ b/patches/node/unix_simplify_uv_cloexec_fcntl_3492.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ben Noordhuis +Date: Sat, 5 Mar 2022 18:55:49 +0100 +Subject: unix: simplify uv__cloexec_fcntl() (#3492) + +FD_CLOEXEC is the only defined flag for fcntl(F_SETFD) so don't bother +getting the status of that flag first with fcntl(F_GETFD), just set it. + +diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c +index a6425294086ff2f1435fdd6866380d3aaaf68200..6cd519ad5b3e7af8f5c71b18a59b88458a233f15 100644 +--- a/deps/uv/src/unix/core.c ++++ b/deps/uv/src/unix/core.c +@@ -649,21 +649,9 @@ int uv__cloexec_fcntl(int fd, int set) { + int flags; + int r; + +- do +- r = fcntl(fd, F_GETFD); +- while (r == -1 && errno == EINTR); +- +- if (r == -1) +- return UV__ERR(errno); +- +- /* Bail out now if already set/clear. */ +- if (!!(r & FD_CLOEXEC) == !!set) +- return 0; +- ++ flags = 0; + if (set) +- flags = r | FD_CLOEXEC; +- else +- flags = r & ~FD_CLOEXEC; ++ flags = FD_CLOEXEC; + + do + r = fcntl(fd, F_SETFD, flags);