]> git.eshelyaron.com Git - emacs.git/commitdiff
Don't set exit info in Eshell if the command is being piped elsewhere
authorJim Porter <jporterbugs@gmail.com>
Fri, 19 Jul 2024 16:34:03 +0000 (09:34 -0700)
committerEshel Yaron <me@eshelyaron.com>
Mon, 22 Jul 2024 10:32:47 +0000 (12:32 +0200)
Previously, the exit info in Eshell was that of the last command that
finished, rather than the last command in a pipeline.

* lisp/eshell/esh-cmd.el (eshell-exec-lisp)
(eshell-lisp-command): Check whether the command is being piped.

* lisp/eshell/esh-proc.el (eshell-gather-process-output): Record whether
the command is being piped...
(eshell-sentinel): ... and do the right thing with that info.

* test/lisp/eshell/esh-proc-tests.el
(esh-proc-test/sigpipe-exits-process): Check the exit status to ensure
we don't report the first process's SIGPIPE exit.

(cherry picked from commit b7893e73878df83043e05dc8cb811971c0e99f03)

lisp/eshell/esh-cmd.el
lisp/eshell/esh-proc.el
test/lisp/eshell/esh-proc-tests.el

index d21ac850c024433f1b4cafb1fe8ff06ec7f94194..2b47962735a70eda1485e9dd0bd1701edfba8dd6 100644 (file)
@@ -1425,10 +1425,12 @@ case."
      ;; 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.
-     (eshell-set-exit-info 141)
+     (when (memq eshell-in-pipeline-p '(nil last))
+       (eshell-set-exit-info 141))
      nil)
     (error
-     (eshell-set-exit-info 1)
+     (when (memq eshell-in-pipeline-p '(nil last))
+       (eshell-set-exit-info 1))
      (let ((msg (error-message-string err)))
        (if (and (not form-p)
                 (string-match "^Wrong number of arguments" msg)
@@ -1507,7 +1509,8 @@ a string naming a Lisp function."
   (unless eshell-allow-commands
     (signal 'eshell-commands-forbidden '(lisp)))
   (catch 'eshell-external               ; deferred to an external command
-    (eshell-set-exit-info 0)
+    (when (memq eshell-in-pipeline-p '(nil last))
+      (eshell-set-exit-info 0))
     (setq eshell-last-arguments args)
     (let* ((eshell-ensure-newline-p t)
            (command-form-p (functionp object))
@@ -1543,16 +1546,17 @@ a string naming a Lisp function."
               (eshell-eval* #'eshell-print-maybe-n
                             #'eshell-error-maybe-n
                             object))))
-      (eshell-set-exit-info
-       ;; If `eshell-lisp-form-nil-is-failure' is non-nil, Lisp forms
-       ;; that succeeded but have a nil result should have an exit
-       ;; status of 2.
-       (when (and eshell-lisp-form-nil-is-failure
-                  (not command-form-p)
-                  (= eshell-last-command-status 0)
-                  (not result))
-         2)
-       result)
+      (when (memq eshell-in-pipeline-p '(nil last))
+        (eshell-set-exit-info
+         ;; If `eshell-lisp-form-nil-is-failure' is non-nil, Lisp forms
+         ;; that succeeded but have a nil result should have an exit
+         ;; status of 2.
+         (when (and eshell-lisp-form-nil-is-failure
+                    (not command-form-p)
+                    (= eshell-last-command-status 0)
+                    (not result))
+           2)
+         result))
       (eshell-close-handles))))
 
 (define-obsolete-function-alias 'eshell-lisp-command* #'eshell-lisp-command
index 2735be882b655ab52c274364c5a2bd57df1f5a7c..dc7b497666be4b86dbe0a147f65e9834e58b06da 100644 (file)
@@ -394,6 +394,9 @@ Used only on systems which do not support async subprocesses.")
         (mapconcat #'shell-quote-argument (process-command proc) " "))
       (eshell-record-process-object proc)
       (eshell-record-process-properties proc)
+      ;; Don't set exit info for processes being piped elsewhere.
+      (when (memq (bound-and-true-p eshell-in-pipeline-p) '(nil last))
+        (process-put proc :eshell-set-exit-info t))
       (when stderr-proc
         ;; Provide a shared flag between the primary and stderr
         ;; processes.  This lets the primary process wait to clean up
@@ -546,6 +549,7 @@ PROC is the process that's exiting.  STRING is the exit message."
           (let* ((handles (process-get proc :eshell-handles))
                  (index (process-get proc :eshell-handle-index))
                  (primary (= index eshell-output-handle))
+                 (set-exit-info (process-get proc :eshell-set-exit-info))
                  (data (process-get proc :eshell-pending))
                  (stderr-live (process-get proc :eshell-stderr-live)))
             ;; Write the exit message for the last process in the
@@ -576,7 +580,7 @@ PROC is the process that's exiting.  STRING is the exit message."
                                   (ignore-error eshell-pipe-broken
                                     (eshell-output-object
                                      data index handles)))
-                                (when primary
+                                (when set-exit-info
                                   (let ((status (process-exit-status proc)))
                                     (eshell-set-exit-info status (= status 0))))
                                 (eshell-close-handles handles)
index d46004688f94111660c09531d028415b6cef7d19..3121e751006e2bf301093589c14da2614c6dc56b 100644 (file)
@@ -167,7 +167,10 @@ See bug#71778."
               "sh -c 'read NAME; echo ${NAME}'")
       "y\n")
      (eshell-wait-for-subprocess t)
-     (should (equal (process-list) starting-process-list)))))
+     (should (equal (process-list) starting-process-list))
+     ;; Make sure the exit status is from the last command in the
+     ;; pipeline.
+     (should (= eshell-last-command-status 0)))))
 
 (ert-deftest esh-proc-test/pipeline-connection-type/no-pipeline ()
   "Test that all streams are PTYs when a command is not in a pipeline."