From 01b716cf12199c82b480e5f2a7afb12128d273a4 Mon Sep 17 00:00:00 2001 From: Serhii Melnychuk <111431514+DepsCian@users.noreply.github.com> Date: Mon, 5 Jan 2026 17:19:10 +0200 Subject: [PATCH] terminal: Kill entire process group on Unix when stopping command (#45993) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem When clicking Stop button on a terminal tool call (or using terminal kill bindings), only the shell process was killed. Child processes (like `sleep`, `npm run`, etc.) continued running as orphans. ## Solution On Unix, use `killpg()` instead of `sysinfo::Process::kill()` to terminate the entire foreground process group. `tcgetpgrp()` already returns the foreground process group ID, so `killpg()` is the correct syscall to use here. ## Testing 1. Run a long command in terminal tool (e.g. `sleep 30`) 2. Click Stop button 3. Verify with `ps aux | grep sleep` that the process is actually killed ## Notes - This fix is Unix-only (Linux, macOS) - Windows behavior unchanged — may need separate investigation with Job Objects ## Release Notes - Fixed terminal Stop button not killing child processes on Unix (Linux, macOS) --- crates/terminal/src/pty_info.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/terminal/src/pty_info.rs b/crates/terminal/src/pty_info.rs index c92de2f23b83ba4dbedc6980ceb9b106d06467c1..60654378d9e53d8f5aa977900bd664a4a0898d67 100644 --- a/crates/terminal/src/pty_info.rs +++ b/crates/terminal/src/pty_info.rs @@ -125,6 +125,15 @@ impl PtyProcessInfo { self.system.process(pid) } + #[cfg(unix)] + pub(crate) fn kill_current_process(&mut self) -> bool { + let Some(pid) = self.pid_getter.pid() else { + return false; + }; + unsafe { libc::killpg(pid.as_u32() as i32, libc::SIGKILL) == 0 } + } + + #[cfg(not(unix))] pub(crate) fn kill_current_process(&mut self) -> bool { self.refresh().is_some_and(|process| process.kill()) }