aboutsummaryrefslogtreecommitdiff
path: root/src/pane.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-07 16:14:46 +0300
committerGitHub <noreply@github.com>2026-09-07 15:14:46 +0200
commite7d8220788b4fa7c266a1e4457591b694478771c (patch)
tree272303d74e0b58c11f9c0c434dae8335d3d06703 /src/pane.rs
parent482818130407691154d1635d4029b95d0e730104 (diff)
fix: preserve sessions after interrupted pane exits (#3418)
* fix: preserve sessions when pane shells are signaled refs #3415 * fix: preserve shutdown checkpoints across platforms refs #3415 --------- Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>
Diffstat (limited to 'src/pane.rs')
-rw-r--r--src/pane.rs23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/pane.rs b/src/pane.rs
index 83bad900..aa6acb57 100644
--- a/src/pane.rs
+++ b/src/pane.rs
@@ -2194,7 +2194,12 @@ impl PaneRuntime {
});
let exit_events = events.clone();
let on_reader_exit = Box::new(move || {
- let _ = rt.block_on(exit_events.send(AppEvent::PaneDied { pane_id }));
+ // Imported handoff panes have no child wait handle, so their exit cause is
+ // unknowable. Checkpoint conservatively; normal autosave settles clean exits.
+ let _ = rt.block_on(exit_events.send(AppEvent::PaneDied {
+ pane_id,
+ exit_reason: crate::platform::ChildExitReason::Handoff,
+ }));
debug!(pane = pane_id.raw(), "handoff PTY actor exiting");
});
PaneRuntimeIo::Actor(PtyIoActor::spawn(PtyIoActorConfig {
@@ -2299,16 +2304,24 @@ impl PaneRuntime {
crate::logging::pane_spawned(pane_id.raw(), pid);
}
tokio::task::spawn_blocking(move || {
- match child.wait() {
+ let exit_reason = match child.wait() {
Ok(status) => {
+ let exit_reason = crate::platform::classify_child_exit(&status);
let status_text = format!("{status:?}");
crate::logging::pane_exited(pane_id.raw(), &status_text);
+ exit_reason
}
- Err(e) => crate::logging::pane_exit_failed(pane_id.raw(), &e.to_string()),
- }
+ Err(e) => {
+ crate::logging::pane_exit_failed(pane_id.raw(), &e.to_string());
+ crate::platform::ChildExitReason::WaitFailed
+ }
+ };
child_wait_completed.store(true, Ordering::Release);
// Use blocking send — PaneDied is critical, must not be dropped
- if let Err(e) = rt.block_on(events.send(AppEvent::PaneDied { pane_id })) {
+ if let Err(e) = rt.block_on(events.send(AppEvent::PaneDied {
+ pane_id,
+ exit_reason,
+ })) {
error!(pane = pane_id.raw(), err = %e, "failed to send PaneDied event");
}
});