From f73d6fe4ce1cd9c01220da77e071f1f0c12cccbe Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 31 Oct 2025 16:01:50 +0100 Subject: [PATCH] terminal: Kill the terminal child process, not the terminal process on exit (#41631) When rerunning a task, our process id fetching seems to sometimes return the previous terminal's process id when respawning the task, causing us to kill the new terminal once the previous one drops as we spawn a new one, then drop the old one. This results in rerun sometimes spawning a blank task as the terminal immediately exits. The fix here is simple, we actually want to kill the process running inside the terminal process, not the terminal process itself when we exit in the terminal. No relnotes as this was introduced yesterday in https://github.com/zed-industries/zed/pull/41562 Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/terminal/src/pty_info.rs | 23 +++++++++++++++-------- crates/terminal/src/terminal.rs | 2 +- crates/terminal_view/src/terminal_view.rs | 3 ++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/terminal/src/pty_info.rs b/crates/terminal/src/pty_info.rs index f8e8a122f8..c92de2f23b 100644 --- a/crates/terminal/src/pty_info.rs +++ b/crates/terminal/src/pty_info.rs @@ -15,6 +15,12 @@ pub struct ProcessIdGetter { fallback_pid: u32, } +impl ProcessIdGetter { + pub fn fallback_pid(&self) -> Pid { + Pid::from_u32(self.fallback_pid) + } +} + #[cfg(unix)] impl ProcessIdGetter { fn new(pty: &Pty) -> ProcessIdGetter { @@ -31,10 +37,6 @@ impl ProcessIdGetter { } Some(Pid::from_u32(pid as u32)) } - - pub fn fallback_pid(&self) -> u32 { - self.fallback_pid - } } #[cfg(windows)] @@ -66,10 +68,6 @@ impl ProcessIdGetter { } Some(Pid::from_u32(pid)) } - - pub fn fallback_pid(&self) -> u32 { - self.fallback_pid - } } #[derive(Clone, Debug)] @@ -122,10 +120,19 @@ impl PtyProcessInfo { } } + fn get_child(&self) -> Option<&Process> { + let pid = self.pid_getter.fallback_pid(); + self.system.process(pid) + } + pub(crate) fn kill_current_process(&mut self) -> bool { self.refresh().is_some_and(|process| process.kill()) } + pub(crate) fn kill_child_process(&mut self) -> bool { + self.get_child().is_some_and(|process| process.kill()) + } + fn load(&mut self) -> Option { let process = self.refresh()?; let cwd = process.cwd().map_or(PathBuf::new(), |p| p.to_owned()); diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index f91a476306..0550e4512a 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -2237,7 +2237,7 @@ unsafe fn append_text_to_term(term: &mut Term, text_lines: &[&str]) impl Drop for Terminal { fn drop(&mut self) { if let TerminalType::Pty { pty_tx, info } = &mut self.terminal_type { - info.kill_current_process(); + info.kill_child_process(); pty_tx.0.send(Msg::Shutdown).ok(); } } diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 2a9720357b..7208f28a80 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -1141,7 +1141,8 @@ impl Item for TerminalView { let pid = terminal.pid_getter()?.fallback_pid(); Some(TabTooltipContent::Custom(Box::new(move |_window, cx| { - cx.new(|_| TerminalTooltip::new(title.clone(), pid)).into() + cx.new(|_| TerminalTooltip::new(title.clone(), pid.as_u32())) + .into() }))) }