diff --git a/deps/libuv/ChangeLog b/deps/libuv/ChangeLog index 1c239131..ea28356d 100644 --- a/deps/libuv/ChangeLog +++ b/deps/libuv/ChangeLog @@ -1,4 +1,15 @@ -2022.03.07, Version 1.44.0 (Stable) +2022.03.09, Version 1.44.1 (Stable) + +Changes since version 1.44.0: + +* process: simplify uv__write_int calls (Jameson Nash) + +* macos: don't use thread-unsafe strtok() (Ben Noordhuis) + +* process: fix hang after NOTE_EXIT (Jameson Nash) + + +2022.03.07, Version 1.44.0 (Stable), d2bff508457336d808ba7148b33088f6acbfe0a6 Changes since version 1.43.0: diff --git a/deps/libuv/configure.ac b/deps/libuv/configure.ac index 40715b3f..bd1e9c61 100644 --- a/deps/libuv/configure.ac +++ b/deps/libuv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.44.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.44.1], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/libuv/include/uv/version.h b/deps/libuv/include/uv/version.h index 42464019..56ac1bf4 100644 --- a/deps/libuv/include/uv/version.h +++ b/deps/libuv/include/uv/version.h @@ -32,7 +32,7 @@ #define UV_VERSION_MAJOR 1 #define UV_VERSION_MINOR 44 -#define UV_VERSION_PATCH 0 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/libuv/src/unix/kqueue.c b/deps/libuv/src/unix/kqueue.c index 857eb1d5..03605514 100644 --- a/deps/libuv/src/unix/kqueue.c +++ b/deps/libuv/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/libuv/src/unix/process.c b/deps/libuv/src/unix/process.c index 270d5287..8802e4f3 100644 --- a/deps/libuv/src/unix/process.c +++ b/deps/libuv/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__) +#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__)) +#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); @@ -216,16 +237,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 +303,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 +330,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 +383,6 @@ static void uv__process_child_init(const uv_process_options_t* options, #endif uv__write_errno(error_fd); - abort(); } #endif @@ -394,30 +408,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; + int which[] = {CTL_KERN, KERN_OSRELEASE}; + unsigned major; + unsigned minor; + unsigned patch; + char buf[256]; + size_t len; - /* Get a version string */ - r = sysctlbyname("kern.osrelease", version_str, &version_str_size, NULL, 0); - if (r != 0) + 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 */ } @@ -980,7 +986,7 @@ int uv_spawn(uv_loop_t* loop, goto error; } -#if !(defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)) +#ifdef UV_USE_SIGCHLD uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); #endif @@ -999,13 +1005,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__) +#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/libuv/src/uv-common.h b/deps/libuv/src/uv-common.h index 8a190bf8..6001b0cf 100644 --- a/deps/libuv/src/uv-common.h +++ b/deps/libuv/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);