From 164d23f38dfcedc5cc38fd82fb51d256272535f8 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Fri, 4 Jul 2025 13:25:47 +0200 Subject: [PATCH] libutil/runProgram2: support posix_spawn-like dup-to-self redirections posix_spawn unsets CLOEXEC for fds that are dup'd onto their existing fd number. this is very useful when inheriting fd numbers exceeding stderr. Change-Id: I6f14585d424ded6741fdd087f0c4d33a05936bcc --- lix/libutil/processes.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lix/libutil/processes.cc b/lix/libutil/processes.cc index f8971f8bf..aa692d4c3 100644 --- a/lix/libutil/processes.cc +++ b/lix/libutil/processes.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -332,7 +333,13 @@ RunningProgram runProgram2(const RunOptions & options) if (options.captureStdout && dup2(out.writeSide.get(), STDOUT_FILENO) == -1) throw SysError("dupping stdout"); for (auto redirection : options.redirections) { - if (dup2(redirection.from, redirection.dup) == -1) { + if (redirection.dup == redirection.from) { + if (int flags = fcntl(redirection.from, F_GETFD); + flags < 0 || fcntl(redirection.from, F_SETFD, flags & ~FD_CLOEXEC) < 0) + { + throw SysError("clearing O_CLOEXEC of fd %i", redirection.dup); + } + } else if (dup2(redirection.from, redirection.dup) == -1) { throw SysError("dupping fd %i to %i", redirection.dup, redirection.from); } }