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 f8e8a122f845253175ba6f176c12408056163fdb..c92de2f23b83ba4dbedc6980ceb9b106d06467c1 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 f91a47630614b4736ebe5bb642d6430574c8c8ed..0550e4512a2c7594fc27dae37448cf6a09a5606a 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 2a9720357b27b91f3a5ff7689f4cb0f16787031b..7208f28a80149d39d056a4767c7b8742f1147009 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() }))) }