From f977ace7f8c75f698e468cd4f5add09082dcdaf8 Mon Sep 17 00:00:00 2001 From: Michael Camilleri Date: Fri, 23 Jun 2023 15:50:19 +0900 Subject: [PATCH] Avoid prematurely closing file descriptors when redirecting IO --- src/core/os.c | 6 ++++-- test/suite-os.janet | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/core/os.c b/src/core/os.c index 70f0449c..65afdce9 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -1145,14 +1145,16 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) { posix_spawn_file_actions_addclose(&actions, pipe_in); } else if (new_in != JANET_HANDLE_NONE && new_in != 0) { posix_spawn_file_actions_adddup2(&actions, new_in, 0); - posix_spawn_file_actions_addclose(&actions, new_in); + if (new_in != new_out && new_in != new_err) + posix_spawn_file_actions_addclose(&actions, new_in); } if (pipe_out != JANET_HANDLE_NONE) { posix_spawn_file_actions_adddup2(&actions, pipe_out, 1); posix_spawn_file_actions_addclose(&actions, pipe_out); } else if (new_out != JANET_HANDLE_NONE && new_out != 1) { posix_spawn_file_actions_adddup2(&actions, new_out, 1); - posix_spawn_file_actions_addclose(&actions, new_out); + if (new_out != new_err) + posix_spawn_file_actions_addclose(&actions, new_out); } if (pipe_err != JANET_HANDLE_NONE) { posix_spawn_file_actions_adddup2(&actions, pipe_err, 2); diff --git a/test/suite-os.janet b/test/suite-os.janet index f88c997d..1af75674 100644 --- a/test/suite-os.janet +++ b/test/suite-os.janet @@ -94,9 +94,9 @@ (assert (= (length buf) 2) "cryptorand appends to buffer")) # 80db68210 -(assert-no-error (os/clock :realtime) "realtime clock") -(assert-no-error (os/clock :cputime) "cputime clock") -(assert-no-error (os/clock :monotonic) "monotonic clock") +(assert-no-error "realtime clock" (os/clock :realtime)) +(assert-no-error "cputime clock" (os/clock :cputime)) +(assert-no-error "monotonic clock" (os/clock :monotonic)) (def before (os/clock :monotonic)) (def after (os/clock :monotonic)) @@ -129,5 +129,16 @@ (string/format "(os/exit %d)" i)] :p)) (string "os/execute " i))) +# os/execute IO redirection +(assert-no-error "IO redirection" + (defn devnull [] + (def os (os/which)) + (def path (if (or (= os :mingw) (= os :windows)) + "NUL" + "/dev/null")) + (os/open path :w)) + (with [dn (devnull)] + (os/execute ["ls"] :px {:out dn :err dn}))) + (end-suite)