summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2024-06-24 13:37:18 (GMT)
committerBrad King <brad.king@kitware.com>2024-06-24 13:37:18 (GMT)
commit1deb5430890e7473a51f3764a9bf906cef267ebd (patch)
tree4a76b744a614b67c4c1aaa8696eca915d352e423
parent1c4c5ad545ca66af1b7e2c8503bcb298ca326ffe (diff)
parent422c1de564cec5689de052d5eb0c2ddd7065833c (diff)
downloadCMake-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.txt4
-rw-r--r--Utilities/cmlibuv/include/uv/darwin.h9
-rw-r--r--Utilities/cmlibuv/src/unix/core.c1
-rw-r--r--Utilities/cmlibuv/src/unix/darwin.c2
-rw-r--r--Utilities/cmlibuv/src/unix/internal.h1
-rw-r--r--Utilities/cmlibuv/src/unix/kqueue.c43
-rw-r--r--Utilities/cmlibuv/src/unix/loop.c5
-rw-r--r--Utilities/cmlibuv/src/unix/process.c27
-rw-r--r--Utilities/cmlibuv/src/unix/signal.c2
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]);