From b92630b39d50263947cb4d3cda206fcf92a2d526 Mon Sep 17 00:00:00 2001 From: Timothy Sample Date: Thu, 15 Nov 2018 11:07:45 -0500 Subject: [PATCH] Flush ports before forking There are two issues that arise due to output port buffers and forking. If we run Scheme code in a child process, we need to avoid copying buffered output into the child process. Otherwise, the buffered output could be written twice. If we run non-Scheme code (i.e., exec), we need to flush the ports to ensure proper sequencing of writes since the non-Scheme code will not know about the buffered output and will write its output before the buffer gets flushed. * geesh/shell.scm (exec-utility): Flush all ports before forking. (%subshell): Ditto. --- geesh/shell.scm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/geesh/shell.scm b/geesh/shell.scm index d5025b1..9299686 100644 --- a/geesh/shell.scm +++ b/geesh/shell.scm @@ -58,6 +58,11 @@ extra environment variables @var{bindings}. The first argument given to the new process will be @var{name}, and the rest of the arguments will be @var{args}." (let ((utility-env (environment->environ env bindings))) + ;; We need to flush all ports here to ensure the proper sequence + ;; of output. Without flushing, output that we have written could + ;; stay in a buffer while the utility (which does not know about + ;; the buffer) produces its output. + (flush-all-ports) (match (primitive-fork) (0 (install-current-ports!) (apply execle path utility-env name args)) @@ -193,6 +198,10 @@ by @var{saved-port}, where @var{saved-port} is a return value of (define* (%subshell thunk) "Run @var{thunk} in a new process and return the ID of the new process." + ;; We need to flush all ports before forking to avoid copying the + ;; port buffers into the child process, which could lead to + ;; duplicate output. + (flush-all-ports) (match (primitive-fork) (0 (thunk) (primitive-exit))