Wait for all processes in a pipeline before resuming an Eshell command

Previously, we only waited until the tail process was finished, but
now, we wait for all of them.  This is more consistent with other
shells, and prevents some cases of a process's output coming *after*
we continued past its pipeline.

* lisp/eshell/esh-cmd.el (eshell-resume-command): Simplify
conditionals, and check that all the foreground processes are dead
before resuming Eshell command.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/pipeline-wait/multi-proc): New test.
This commit is contained in:
Jim Porter 2023-09-06 17:01:06 -07:00
parent e554ee0b5f
commit 2ec41c174f
2 changed files with 21 additions and 7 deletions

View file

@ -994,13 +994,17 @@ process(es) in a cons cell like:
result)))
(defun eshell-resume-command (proc status)
"Resume the current command when a process ends."
(when proc
(unless (or (not (stringp status))
(string= "stopped" status)
(string-match eshell-reset-signals status))
(if (eq proc (eshell-tail-process))
(eshell-resume-eval)))))
"Resume the current command when a pipeline ends."
(when (and proc
;; Make sure STATUS is something we want to handle.
(stringp status)
(not (string= "stopped" status))
(not (string-match eshell-reset-signals status))
;; Make sure PROC is one of our foreground processes and
;; that all of those processes are now dead.
(member proc eshell-last-async-procs)
(not (seq-some #'process-live-p eshell-last-async-procs)))
(eshell-resume-eval)))
(defun eshell-resume-eval ()
"Destructively evaluate a form which may need to be deferred."

View file

@ -154,6 +154,16 @@ bug#59469."
(eshell-match-command-output "*echo hi | echo bye"
"bye\nhi\n")))
(ert-deftest esh-cmd-test/pipeline-wait/multi-proc ()
"Check that a pipeline waits for all its processes before returning."
(skip-unless (and (executable-find "echo")
(executable-find "sh")
(executable-find "rev")))
(with-temp-eshell
(eshell-match-command-output
"*echo hello | sh -c 'sleep 1; rev' 1>&2 | *echo goodbye"
"goodbye\nolleh\n")))
(ert-deftest esh-cmd-test/pipeline-wait/subcommand ()
"Check that piping with an asynchronous subcommand waits for the subcommand."
(skip-unless (and (executable-find "echo")