]> git.eshelyaron.com Git - emacs.git/commitdiff
Always perform Eshell process cleanup runs in the Eshell buffer
authorJim Porter <jporterbugs@gmail.com>
Wed, 26 Jun 2024 04:39:35 +0000 (21:39 -0700)
committerEshel Yaron <me@eshelyaron.com>
Wed, 26 Jun 2024 13:34:30 +0000 (15:34 +0200)
Previously, some code executed in a timer, which could execute in the
wrong buffer, leading to a hang.

* lisp/eshell/esh-proc.el (eshell-sentinel): Use 'with-current-buffer'
in the timer function.

* test/lisp/eshell/esh-proc-tests.el (eshell-test-value): New variable.
(esh-proc-test/sentinel/change-buffer): New test.

(cherry picked from commit da4bc5c9274a6705501e24fb8f2984f5bf5fe099)

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

index e05590f2542ad40dafcbd7c68d6c232b0e579c8c..2ff41c3d409baf0cb0e72ff1f025317988eab8f4 100644 (file)
@@ -530,28 +530,30 @@ PROC is the process that's exiting.  STRING is the exit message."
                                            (not (process-live-p proc))))
                      (finish-io
                       (lambda ()
-                        (if (or (process-get proc :eshell-busy)
-                                (and wait-for-stderr (car stderr-live)))
-                            (progn
-                              (eshell-debug-command 'process
-                                "i/o busy for process `%s'" proc)
-                              (run-at-time 0 nil finish-io))
-                          (when data
-                            (ignore-error eshell-pipe-broken
-                              (eshell-output-object
-                               data index handles)))
-                          (eshell-close-handles
-                           status
-                           (when status (list 'quote (= status 0)))
-                           handles)
-                          ;; Clear the handles to mark that we're 100%
-                          ;; finished with the I/O for this process.
-                          (process-put proc :eshell-handles nil)
-                          (eshell-debug-command 'process
-                            "finished external process `%s'" proc)
-                          (if primary
-                              (run-hook-with-args 'eshell-kill-hook proc string)
-                            (setcar stderr-live nil))))))
+                        (with-current-buffer (process-buffer proc)
+                          (if (or (process-get proc :eshell-busy)
+                                  (and wait-for-stderr (car stderr-live)))
+                              (progn
+                                (eshell-debug-command 'process
+                                  "i/o busy for process `%s'" proc)
+                                (run-at-time 0 nil finish-io))
+                            (when data
+                              (ignore-error eshell-pipe-broken
+                                (eshell-output-object
+                                 data index handles)))
+                            (eshell-close-handles
+                             status
+                             (when status (list 'quote (= status 0)))
+                             handles)
+                            ;; Clear the handles to mark that we're 100%
+                            ;; finished with the I/O for this process.
+                            (process-put proc :eshell-handles nil)
+                            (eshell-debug-command 'process
+                              "finished external process `%s'" proc)
+                            (if primary
+                                (run-hook-with-args 'eshell-kill-hook
+                                                    proc string)
+                              (setcar stderr-live nil)))))))
               (funcall finish-io)))
         (when-let ((entry (assq proc eshell-process-list)))
           (eshell-remove-process-entry entry))))))
index 643cb8b125a35fde157308057e677c002a454102..85b02845ab30e2081700e698b2ecdec780b998d9 100644 (file)
@@ -45,6 +45,8 @@
           "'")
   "A shell command that prints the standard streams connected as TTYs.")
 
+(defvar eshell-test-value nil)
+
 ;;; Tests:
 
 \f
      (should (= eshell-last-command-status 1))
      (should (eq eshell-last-command-result nil)))))
 
+(ert-deftest esh-proc-test/sentinel/change-buffer ()
+  "Check that changing the current buffer while running a command works.
+See bug#71778."
+  (eshell-with-temp-buffer bufname ""
+    (with-temp-eshell
+      (let (eshell-test-value)
+        (eshell-insert-command
+         (concat (format "for i in 1 2 {sleep 1; echo hello} > #<%s>; " bufname)
+                 "setq eshell-test-value t"))
+        (with-current-buffer bufname
+          (eshell-wait-for (lambda () eshell-test-value))
+          (should (equal (buffer-string) "hellohello")))
+        (eshell-match-command-output "echo goodbye" "\\`goodbye\n")))))
+
 \f
 ;; Pipelines