emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master fad91b56d13 3/3: Ensure that Eshell doesn't consider a process co


From: Jim Porter
Subject: master fad91b56d13 3/3: Ensure that Eshell doesn't consider a process complete until stderr is done
Date: Tue, 12 Sep 2023 14:48:55 -0400 (EDT)

branch: master
commit fad91b56d13e7bc902cce522671ebf47b0632d45
Author: Jim Porter <jporterbugs@gmail.com>
Commit: Jim Porter <jporterbugs@gmail.com>

    Ensure that Eshell doesn't consider a process complete until stderr is done
    
    This will hopefully help resolve some timing issues with subprocesses
    in Eshell.  There's now much less chance of output going missing when
    using redirects.
    
    * lisp/eshell/esh-proc.el (eshell-gather-process-output): Set
    ':eshell-stderr-live'...
    (eshell-sentinel): ... use it.
---
 lisp/eshell/esh-proc.el | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index f5fd982b1a4..5bfcbd6dc15 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -350,6 +350,13 @@ Used only on systems which do not support async 
subprocesses.")
        'process (format-message "started external process `%s'" proc))
       (eshell-record-process-object proc)
       (eshell-record-process-properties proc)
+      (when stderr-proc
+        ;; Provide a shared flag between the primary and stderr
+        ;; processes.  This lets the primary process wait to clean up
+        ;; until stderr is totally finished (see `eshell-sentinel').
+        (let ((stderr-live (list t)))
+          (process-put proc :eshell-stderr-live stderr-live)
+          (process-put stderr-proc :eshell-stderr-live stderr-live)))
       (run-hook-with-args 'eshell-exec-hook proc)
       (when (fboundp 'process-coding-system)
        (let ((coding-systems (process-coding-system proc)))
@@ -491,11 +498,12 @@ PROC is the process that's exiting.  STRING is the exit 
message."
       (unwind-protect
           (let* ((handles (process-get proc :eshell-handles))
                  (index (process-get proc :eshell-handle-index))
+                 (primary (= index eshell-output-handle))
                  (data (process-get proc :eshell-pending))
                  ;; Only get the status for the primary subprocess,
                  ;; not the pipe process (if any).
-                 (status (when (= index eshell-output-handle)
-                           (process-exit-status proc))))
+                 (status (when primary (process-exit-status proc)))
+                 (stderr-live (process-get proc :eshell-stderr-live)))
             ;; Write the exit message for the last process in the
             ;; foreground pipeline if its status is abnormal and
             ;; stderr is already writing to the terminal.
@@ -507,9 +515,12 @@ PROC is the process that's exiting.  STRING is the exit 
message."
             (process-put proc :eshell-pending nil)
             ;; If we're in the middle of handling output from this
             ;; process then schedule the EOF for later.
-            (letrec ((finish-io
+            (letrec ((wait-for-stderr (and primary
+                                           (not (process-live-p proc))))
+                     (finish-io
                       (lambda ()
-                        (if (process-get proc :eshell-busy)
+                        (if (or (process-get proc :eshell-busy)
+                                (and wait-for-stderr (car stderr-live)))
                             (run-at-time 0 nil finish-io)
                           (when data
                             (ignore-error eshell-pipe-broken
@@ -519,11 +530,13 @@ PROC is the process that's exiting.  STRING is the exit 
message."
                            status
                            (when status (list 'quote (= status 0)))
                            handles)
-                          (eshell-kill-process-function proc string)
-                            (eshell-debug-command
-                             'process
-                             (format-message
-                              "finished external process `%s'" proc))))))
+                          (eshell-debug-command
+                           'process
+                           (format-message
+                            "finished external process `%s'" proc))
+                          (if primary
+                              (eshell-kill-process-function proc string)
+                            (setcar stderr-live nil))))))
               (funcall finish-io)))
         (when-let ((entry (assq proc eshell-process-list)))
           (eshell-remove-process-entry entry))))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]