diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-03-31 13:29:57 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-03-31 13:29:57 +0300 |
| commit | f8c452294d6f76ccb264c0d9e205398492f00e18 (patch) | |
| tree | 68f9505424de441b5da4dbe26fab6149e2a75734 /src/pane.rs | |
| parent | b8ccdf600c750411b439d0eb41f6a70e3c595f4f (diff) | |
fix: terminate pane sessions on close
Diffstat (limited to 'src/pane.rs')
| -rw-r--r-- | src/pane.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/pane.rs b/src/pane.rs index 7a5a75dd..c6b8e175 100644 --- a/src/pane.rs +++ b/src/pane.rs @@ -160,7 +160,74 @@ fn recent_text_from_parser(parser: &mut vt100::Parser<PtyResponses>, lines: usiz } } +fn wait_for_processes_to_exit(pids: &[u32], timeout: std::time::Duration) -> bool { + let deadline = std::time::Instant::now() + timeout; + loop { + if pids + .iter() + .all(|pid| !crate::platform::process_exists(*pid)) + { + return true; + } + if std::time::Instant::now() >= deadline { + return false; + } + std::thread::sleep(std::time::Duration::from_millis(20)); + } +} + +fn shutdown_pane_processes(pane_id: PaneId, child_pid: u32) { + if child_pid == 0 { + return; + } + + let mut pids = crate::platform::session_processes(child_pid); + if pids.is_empty() { + pids.push(child_pid); + } + pids.sort_unstable(); + pids.dedup(); + + for (signal, grace) in [ + ( + crate::platform::Signal::Hangup, + std::time::Duration::from_millis(250), + ), + ( + crate::platform::Signal::Terminate, + std::time::Duration::from_millis(250), + ), + ( + crate::platform::Signal::Kill, + std::time::Duration::from_millis(250), + ), + ] { + crate::platform::signal_processes(&pids, signal); + if wait_for_processes_to_exit(&pids, grace) { + info!( + pane = pane_id.raw(), + pid = child_pid, + ?signal, + "pane session terminated" + ); + return; + } + } + + warn!( + pane = pane_id.raw(), + pid = child_pid, + pids = ?pids, + "pane session still alive after forced shutdown" + ); +} + impl PaneRuntime { + pub fn shutdown(self, pane_id: PaneId) { + self.detect_handle.abort(); + shutdown_pane_processes(pane_id, self.child_pid.load(Ordering::Acquire)); + } + pub fn spawn( pane_id: PaneId, rows: u16, |
