diff options
author | Brad King <brad.king@kitware.com> | 2024-06-24 13:37:18 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2024-06-24 13:37:18 (GMT) |
commit | 1deb5430890e7473a51f3764a9bf906cef267ebd (patch) | |
tree | 4a76b744a614b67c4c1aaa8696eca915d352e423 | |
parent | 1c4c5ad545ca66af1b7e2c8503bcb298ca326ffe (diff) | |
parent | 422c1de564cec5689de052d5eb0c2ddd7065833c (diff) | |
download | CMake-1deb5430890e7473a51f3764a9bf906cef267ebd.zip CMake-1deb5430890e7473a51f3764a9bf906cef267ebd.tar.gz CMake-1deb5430890e7473a51f3764a9bf906cef267ebd.tar.bz2 |
Merge topic 'libuv-macos-kqueue' into release-3.29
422c1de564 libuv: macos: restore use of kqueue instead of posix poll
7e3519e705 libuv: macos: reap child processes more reliably when using kqueue
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !9619
-rw-r--r-- | Utilities/cmlibuv/CMakeLists.txt | 4 | ||||
-rw-r--r-- | Utilities/cmlibuv/include/uv/darwin.h | 9 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/unix/core.c | 1 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/unix/darwin.c | 2 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/unix/internal.h | 1 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/unix/kqueue.c | 43 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/unix/loop.c | 5 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/unix/process.c | 27 | ||||
-rw-r--r-- | Utilities/cmlibuv/src/unix/signal.c | 2 |
9 files changed, 54 insertions, 40 deletions
diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index 29dd18e..a0b161b 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -191,8 +191,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") src/unix/bsd-ifaddrs.c src/unix/darwin.c src/unix/darwin-proctitle.c - src/unix/no-fsevents.c - src/unix/posix-poll.c + src/unix/fsevents.c + src/unix/kqueue.c src/unix/proctitle.c ) endif() diff --git a/Utilities/cmlibuv/include/uv/darwin.h b/Utilities/cmlibuv/include/uv/darwin.h index 7eeb194..d226415 100644 --- a/Utilities/cmlibuv/include/uv/darwin.h +++ b/Utilities/cmlibuv/include/uv/darwin.h @@ -30,11 +30,6 @@ # define UV_PLATFORM_SEM_T semaphore_t #endif -#if 1 /* FIXME(#25839): use posix poll to avoid kqueue hangs on macOS. */ -# include "posix.h" -#else -#define UV_HAVE_KQUEUE 1 - #define UV_IO_PRIVATE_PLATFORM_FIELDS \ int rcount; \ int wcount; \ @@ -58,9 +53,9 @@ int cf_error; \ uv_mutex_t cf_mutex; \ -#endif - #define UV_STREAM_PRIVATE_PLATFORM_FIELDS \ void* select; \ +#define UV_HAVE_KQUEUE 1 + #endif /* UV_DARWIN_H */ diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c index d0b0e00..83e8b61 100644 --- a/Utilities/cmlibuv/src/unix/core.c +++ b/Utilities/cmlibuv/src/unix/core.c @@ -366,6 +366,7 @@ static int uv__backend_timeout(const uv_loop_t* loop) { (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) && QUEUE_EMPTY(&loop->pending_queue) && QUEUE_EMPTY(&loop->idle_handles) && + (loop->flags & UV_LOOP_REAP_CHILDREN) == 0 && loop->closing_handles == NULL) return uv__next_timeout(loop); return 0; diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c index b9c8084..62f04d3 100644 --- a/Utilities/cmlibuv/src/unix/darwin.c +++ b/Utilities/cmlibuv/src/unix/darwin.c @@ -41,7 +41,6 @@ static mach_timebase_info_data_t timebase; typedef unsigned char UInt8; -#ifdef UV_HAVE_KQUEUE int uv__platform_loop_init(uv_loop_t* loop) { loop->cf_state = NULL; @@ -55,7 +54,6 @@ int uv__platform_loop_init(uv_loop_t* loop) { void uv__platform_loop_delete(uv_loop_t* loop) { uv__fsevents_loop_delete(loop); } -#endif static void uv__hrtime_init_once(void) { diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h index f41ee3c..1b10516 100644 --- a/Utilities/cmlibuv/src/unix/internal.h +++ b/Utilities/cmlibuv/src/unix/internal.h @@ -272,6 +272,7 @@ int uv__epoll_init(uv_loop_t* loop); int uv__platform_loop_init(uv_loop_t* loop); void uv__platform_loop_delete(uv_loop_t* loop); void uv__platform_invalidate_fd(uv_loop_t* loop, int fd); +int uv__process_init(uv_loop_t* loop); /* various */ void uv__async_close(uv_async_t* handle); diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c index 5dac76a..581c552 100644 --- a/Utilities/cmlibuv/src/unix/kqueue.c +++ b/Utilities/cmlibuv/src/unix/kqueue.c @@ -235,6 +235,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { ARRAY_SIZE(events), timeout == -1 ? NULL : &spec); + if (nfds == -1) + assert(errno == EINTR); + if (pset != NULL) pthread_sigmask(SIG_UNBLOCK, pset, NULL); @@ -242,36 +245,26 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the * operating system didn't reschedule our process while in the syscall. */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - if (reset_timeout != 0) { - timeout = user_timeout; - reset_timeout = 0; - if (timeout == -1) - continue; - if (timeout > 0) - goto update_timeout; + uv__update_time(loop); + + if (nfds == 0 || nfds == -1) { + /* If kqueue is empty or interrupted, we might still have children ready + * to reap immediately. */ + if (loop->flags & UV_LOOP_REAP_CHILDREN) { + loop->flags &= ~UV_LOOP_REAP_CHILDREN; + uv__wait_children(loop); + assert((reset_timeout == 0 ? timeout : user_timeout) == 0); + return; /* Equivalent to fall-through behavior. */ } - assert(timeout != -1); - return; - } - - if (nfds == -1) { - if (errno != EINTR) - abort(); - if (reset_timeout != 0) { timeout = user_timeout; reset_timeout = 0; - } - - if (timeout == 0) + } else if (nfds == 0) { + /* Reached the user timeout value. */ + assert(timeout != -1); return; - - if (timeout == -1) - continue; + } /* Interrupted by a signal. Update timeout and poll again. */ goto update_timeout; @@ -423,13 +416,13 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { return; } +update_timeout: if (timeout == 0) return; if (timeout == -1) continue; -update_timeout: assert(timeout > 0); diff = loop->time - base; diff --git a/Utilities/cmlibuv/src/unix/loop.c b/Utilities/cmlibuv/src/unix/loop.c index a88e71c..8939926 100644 --- a/Utilities/cmlibuv/src/unix/loop.c +++ b/Utilities/cmlibuv/src/unix/loop.c @@ -79,12 +79,9 @@ int uv_loop_init(uv_loop_t* loop) { goto fail_platform_init; uv__signal_global_once_init(); - err = uv_signal_init(loop, &loop->child_watcher); + err = uv__process_init(loop); if (err) goto fail_signal_init; - - uv__handle_unref(&loop->child_watcher); - loop->child_watcher.flags |= UV_HANDLE_INTERNAL; QUEUE_INIT(&loop->process_handles); err = uv_rwlock_init(&loop->cloexec_lock); diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c index 3427847..ebe185d 100644 --- a/Utilities/cmlibuv/src/unix/process.c +++ b/Utilities/cmlibuv/src/unix/process.c @@ -92,8 +92,28 @@ static void uv__chld(uv_signal_t* handle, int signum) { assert(signum == SIGCHLD); uv__wait_children(handle->loop); } + + +int uv__process_init(uv_loop_t* loop) { + int err; + + err = uv_signal_init(loop, &loop->child_watcher); + if (err) + return err; + uv__handle_unref(&loop->child_watcher); + loop->child_watcher.flags |= UV_HANDLE_INTERNAL; + return 0; +} + + +#else +int uv__process_init(uv_loop_t* loop) { + memset(&loop->child_watcher, 0, sizeof(loop->child_watcher)); + return 0; +} #endif + void uv__wait_children(uv_loop_t* loop) { uv_process_t* process; int exit_status; @@ -118,6 +138,7 @@ void uv__wait_children(uv_loop_t* loop) { continue; options = 0; process->flags &= ~UV_HANDLE_REAP; + loop->nfds--; #else options = WNOHANG; #endif @@ -1070,6 +1091,10 @@ int uv_spawn(uv_loop_t* loop, process->flags |= UV_HANDLE_REAP; loop->flags |= UV_LOOP_REAP_CHILDREN; } + /* This prevents uv__io_poll() from bailing out prematurely, being unaware + * that we added an event here for it to react to. We will decrement this + * again after the waitpid call succeeds. */ + loop->nfds++; #endif process->pid = pid; @@ -1138,6 +1163,8 @@ int uv_kill(int pid, int signum) { void uv__process_close(uv_process_t* handle) { QUEUE_REMOVE(&handle->queue); uv__handle_stop(handle); +#ifdef UV_USE_SIGCHLD if (QUEUE_EMPTY(&handle->loop->process_handles)) uv_signal_stop(&handle->loop->child_watcher); +#endif } diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c index 1133c73..bb70523 100644 --- a/Utilities/cmlibuv/src/unix/signal.c +++ b/Utilities/cmlibuv/src/unix/signal.c @@ -279,6 +279,8 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) { int uv__signal_loop_fork(uv_loop_t* loop) { + if (loop->signal_pipefd[0] == -1) + return 0; uv__io_stop(loop, &loop->signal_io_watcher, POLLIN); uv__close(loop->signal_pipefd[0]); uv__close(loop->signal_pipefd[1]); |