From 67c39ab72e9d73f6ef4af7e5cf1142c4f6b2afab Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Mon, 22 Aug 2022 09:53:24 -0700 Subject: [PATCH] Handle 'eshell-pipe-broken' when evaluating Lisp forms in Eshell * lisp/eshell/esh-cmd.el (eshell-exec-lisp): Handle 'eshell-pipe-broken'. * lisp/eshell/esh-io.el (eshell-output-object-to-target): Only signal 'eshell-pipe-broken' if the process being written to has finished. * test/lisp/eshell/esh-proc-tests.el (esh-proc-test/pipeline-connection-type/middle) (esh-proc-test/pipeline-connection-type/last): Remove ':unstable'. --- lisp/eshell/esh-cmd.el | 9 +++++++++ lisp/eshell/esh-io.el | 12 +++++++++--- test/lisp/eshell/esh-proc-tests.el | 4 ---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 2f77f3f497..a43ad77213 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -1347,6 +1347,15 @@ eshell-exec-lisp (apply func-or-form args))))) (and result (funcall printer result)) result) + (eshell-pipe-broken + ;; If FUNC-OR-FORM tried and failed to write some output to a + ;; process, it will raise an `eshell-pipe-broken' signal (this is + ;; analogous to SIGPIPE on POSIX systems). In this case, set the + ;; command status to some non-zero value to indicate an error; to + ;; match GNU/Linux, we use 141, which the numeric value of + ;; SIGPIPE on GNU/Linux (13) with the high bit (2^7) set. + (setq eshell-last-command-status 141) + nil) (error (setq eshell-last-command-status 1) (let ((msg (error-message-string err))) diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el index e5977c9580..d54be55c13 100644 --- a/lisp/eshell/esh-io.el +++ b/lisp/eshell/esh-io.el @@ -498,10 +498,16 @@ eshell-output-object-to-target ((eshell-processp target) (unless (stringp object) (setq object (eshell-stringify object))) - (condition-case nil + (condition-case err (process-send-string target object) - ;; If `process-send-string' raises an error, treat it as a broken pipe. - (error (signal 'eshell-pipe-broken (list target))))) + (error + ;; If `process-send-string' raises an error and the process has + ;; finished, treat it as a broken pipe. Otherwise, just + ;; re-throw the signal. + (if (memq (process-status target) + '(run stop open closed)) + (signal (car err) (cdr err)) + (signal 'eshell-pipe-broken (list target)))))) ((consp target) (apply (car target) object (cdr target)))) diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el index 62e784e8f6..2369bb5cc0 100644 --- a/test/lisp/eshell/esh-proc-tests.el +++ b/test/lisp/eshell/esh-proc-tests.el @@ -74,8 +74,6 @@ esh-proc-test/pipeline-connection-type/first (ert-deftest esh-proc-test/pipeline-connection-type/middle () "Test that all streams are pipes when a command is in the middle of a pipeline." - ;; Repeated unreproducible errors. - :tags '(:unstable) (skip-unless (and (executable-find "sh") (executable-find "cat"))) (eshell-command-result-equal @@ -84,8 +82,6 @@ esh-proc-test/pipeline-connection-type/middle (ert-deftest esh-proc-test/pipeline-connection-type/last () "Test that only output streams are PTYs when a command ends a pipeline." - ;; Repeated unreproducible errors. - :tags '(:unstable) (skip-unless (executable-find "sh")) (eshell-command-result-equal (concat "echo | " esh-proc-test--detect-pty-cmd) -- 2.25.1