Subject: bug#72018: 30.0.60; [PATCH] Don't emit a prompt when a background Eshell process is killed

From: Jim Porter <[email-masked]>
Date: Tue, 9 Jul 2024 11:04:05 -0700

Steps to reproduce:

   emacs -Q -f eshell
   $ sleep 100 &
   $ kill -9 <sleep's process id>

After this, you'll see two Eshell prompts get emitted (one with a "[9]" 
for the exit status of "sleep"). We don't want to emit prompts when 
background processes die though.

This is a regression from Emacs 29, likely due to some changes I made to 
improve support for complex background commands. Eli, is this ok to 
merge to the release branch?

From 3e5a702f0136cc6a071546a854aea54536c87783 Mon Sep 17 00:00:00 2001
From: Jim Porter <[email-masked]>
Date: Tue, 9 Jul 2024 10:45:35 -0700
Subject: [PATCH] Don't emit a prompt in Eshell when a background command is
 killed

* lisp/eshell/esh-cmd.el (eshell-resume-command): Check for
background-ness before resetting the prompt.

* test/lisp/eshell/esh-cmd-tests.el
(esh-cmd-test/background/simple-command): Make the regexp a bit
stricter.
(esh-cmd-test/background/kill): New test.
---
 lisp/eshell/esh-cmd.el            |  7 +++++--
 test/lisp/eshell/esh-cmd-tests.el | 14 +++++++++++++-
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 0b3137127d2..d0de6e55ce6 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -1040,8 +1040,11 @@ eshell-resume-command
                  (not (string-match eshell-reset-signals status)))
             (eshell-resume-eval command)
           (eshell-remove-command command)
-          (declare-function eshell-reset "esh-mode" (&optional no-hooks))
-          (eshell-reset))))))
+          ;; Reset the prompt if the command we just aborted was in the
+          ;; foreground.
+          (unless (car command)
+            (declare-function eshell-reset "esh-mode" (&optional no-hooks))
+            (eshell-reset)))))))
 
 (defun eshell-resume-eval (command)
   "Destructively evaluate a COMMAND which may need to be deferred.
diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el
index 70e1901c169..d8124a19af6 100644
--- a/test/lisp/eshell/esh-cmd-tests.el
+++ b/test/lisp/eshell/esh-cmd-tests.el
@@ -113,7 +113,7 @@ esh-cmd-test/background/simple-command
     (with-temp-eshell
      (eshell-match-command-output
       (format "*echo hi > #<%s> &" bufname)
-      (rx "[echo" (? ".exe") "] " (+ digit) "\n"))
+      (rx bos "[echo" (? ".exe") "] " (+ digit) "\n"))
      (eshell-wait-for-subprocess t))
     (should (equal (buffer-string) "hi\n"))))
 
@@ -129,6 +129,18 @@ esh-cmd-test/background/subcommand
      (eshell-wait-for-subprocess t))
     (should (equal (buffer-string) "olleh\n"))))
 
+(ert-deftest esh-cmd-test/background/kill ()
+  "Make sure that a background command that gets killed doesn't emit a prompt."
+  (skip-unless (executable-find "sleep"))
+  (let ((background-message (rx bos "[sleep" (? ".exe") "] " (+ digit) "\n")))
+    (with-temp-eshell
+      (eshell-match-command-output "*sleep 10 &" background-message)
+      (kill-process (caar eshell-process-list))
+      (eshell-wait-for-subprocess t)
+      ;; Ensure we didn't emit another prompt after killing the
+      ;; background process.
+      (should (eshell-match-output background-message)))))
+
 
 ;; Lisp forms
 
-- 
2.25.1