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.
This commit is contained in:
Timothy Sample 2018-11-15 11:07:45 -05:00
parent 9dbf64d740
commit b92630b39d
1 changed files with 9 additions and 0 deletions

View File

@ -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))