From a245a7caa8edebeba09829191280b00926bbd4c9 Mon Sep 17 00:00:00 2001 From: Herman Semenoff Date: Tue, 10 Feb 2026 14:45:05 +0300 Subject: [PATCH] librc: fix unnecessary copying parent memory page table posix_spawn() is a more lightweight and modern alternative to fork()/exec(), which are used inside popen(). The main advantage of posix_spawn is that it can create a new process without completely duplicating the address space of the parent process. References: - https://blog.famzah.net/2018/12/19/posix_spawn-performance-benchmarks-and-usage-examples/ - https://lobste.rs/s/smbsd5/fork_road - https://www.reddit.com/r/C_Programming/comments/1lvdhp2/fork_vs_posix_spawn/ --- src/librc/librc-depend.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index c7ef4dcd8..516b410f2 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "queue.h" #include "librc.h" @@ -791,12 +792,27 @@ rc_deptree_update(void) bool retval = true; const char *sys = rc_sys(); int serrno; + pid_t pid; + char *argv[] = { "sh", "-c", GENDEP, NULL }; + int pipe_fd[2]; /* Phase 1 - source all init scripts and print dependencies */ setup_environment(); - if (!(fp = popen(GENDEP, "r"))) + if (pipe(pipe_fd) == -1) return false; + if (posix_spawnp(&pid, argv[0], NULL, NULL, argv, NULL) != 0) { + close(pipe_fd[0]); + close(pipe_fd[1]); + return false; + } + close(pipe_fd[1]); + fp = fdopen(pipe_fd[0], "r"); + if (!fp) { + close(pipe_fd[0]); + return false; + } + config = rc_stringlist_new(); deptree = make_deptree(); @@ -876,7 +892,7 @@ rc_deptree_update(void) } } free(line); - pclose(fp); + fclose(fp); /* Phase 2 - if we're a special system, remove services that don't * work for them. This doesn't stop them from being run directly. */