From 6889c552e5786a15afb151293e5c6c9bb1a85c93 Mon Sep 17 00:00:00 2001 From: verycosy Date: Sat, 8 Feb 2025 20:30:45 +0900 Subject: [PATCH] macos: increase child process stdio buffer size On macOS, when calling `spawn`, the child process's stdio buffer size is 8192 bytes. This is due to the AF_UNIX socket buffer size being 8192 bytes in the XNU kernel. When large amounts of data are transferred through the child process's stdio, this buffer size can cause performance issues. To mitigate this, the buffer size has been increased to 65536 bytes, aligning it with the behavior on Linux. --- include/uv/unix.h | 2 ++ src/unix/process.c | 24 ++++++++++++++++++++++-- test/test-spawn.c | 16 ++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/uv/unix.h b/include/uv/unix.h index 7c972026..a5447ceb 100644 --- a/include/uv/unix.h +++ b/include/uv/unix.h @@ -509,4 +509,6 @@ typedef struct { #define UV_FS_O_SEQUENTIAL 0 #define UV_FS_O_TEMPORARY 0 +#define UV_SPAWN_BUFFER_SIZE (64 * 1024) + #endif /* UV_UNIX_H */ diff --git a/src/unix/process.c b/src/unix/process.c index f2038f2c..a2563f06 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -188,6 +188,7 @@ void uv__wait_children(uv_loop_t* loop) { static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { int mask; int fd; + int ret; mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM; @@ -199,8 +200,27 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { assert(container->data.stream != NULL); if (container->data.stream->type != UV_NAMED_PIPE) return UV_EINVAL; - else - return uv_socketpair(SOCK_STREAM, 0, fds, 0, 0); + else { + ret = uv_socketpair(SOCK_STREAM, 0, fds, 0, 0); + +#ifdef __APPLE__ + if(ret == 0) { + int size = UV_SPAWN_BUFFER_SIZE; + int options[] = {SO_RCVBUF, SO_SNDBUF}; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + ret = setsockopt(fds[i], SOL_SOCKET, options[j], &size, sizeof(size)); + + if (ret != 0) + return ret; + } + } + } +#endif + + return ret; + } case UV_INHERIT_FD: case UV_INHERIT_STREAM: diff --git a/test/test-spawn.c b/test/test-spawn.c index 964c8a86..ab810c67 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -603,6 +603,22 @@ TEST_IMPL(spawn_stdin) { r = uv_spawn(uv_default_loop(), &process, &options); ASSERT_OK(r); +#ifdef __APPLE__ + int recv_buf; + int recv_fd; + int send_buf; + int send_fd; + socklen_t optlen = sizeof(int); + + ASSERT_OK(uv_fileno((uv_handle_t*) options.stdio[0].data.stream, &recv_fd)); + ASSERT_OK(getsockopt(recv_fd, SOL_SOCKET, SO_RCVBUF, &recv_buf, &optlen)); + ASSERT_EQ(recv_buf, UV_SPAWN_BUFFER_SIZE); + + ASSERT_OK(uv_fileno((uv_handle_t*) options.stdio[1].data.stream, &send_fd)); + ASSERT_OK(getsockopt(send_fd, SOL_SOCKET, SO_SNDBUF, &send_buf, &optlen)); + ASSERT_EQ(send_buf, UV_SPAWN_BUFFER_SIZE); +#endif + buf.base = buffer; buf.len = sizeof(buffer); r = uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb);