From cf880c77d6ca9eb89a156590ccff09c5e93ad784 Mon Sep 17 00:00:00 2001 From: jimmyfraiture Date: Wed, 8 Oct 2025 11:51:32 +0100 Subject: [PATCH] Fix 1 --- codex-rs/core/src/subsessions/manager.rs | 39 ++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/codex-rs/core/src/subsessions/manager.rs b/codex-rs/core/src/subsessions/manager.rs index bfbd0ba6e8..40d6f75ba3 100644 --- a/codex-rs/core/src/subsessions/manager.rs +++ b/codex-rs/core/src/subsessions/manager.rs @@ -80,9 +80,8 @@ impl ChildRecord { warn!("subsession cancellation receiver already dropped"); } let mut guard = self.handle.lock().await; - if let Some(handle) = guard.take() { - handle.abort(); - } + let _ = guard.take(); + // Drop the handle so the task can observe the cancellation signal and shut down cleanly. } } @@ -391,7 +390,9 @@ fn build_child_config( mod tests { use super::*; use pretty_assertions::assert_eq; + use tokio::sync::oneshot; use tokio::sync::watch; + use tokio::time::timeout; #[tokio::test] async fn cancel_pending_children_only_updates_pending_records() { @@ -426,4 +427,36 @@ mod tests { status => panic!("expected done status, got {status:?}"), } } + + #[tokio::test] + async fn send_cancel_allows_task_to_observe_shutdown() { + let (cancel_tx, mut cancel_rx) = watch::channel(false); + let record = Arc::new(ChildRecord::new(cancel_tx)); + let (observed_tx, observed_rx) = oneshot::channel(); + + let handle = tokio::spawn(async move { + loop { + if *cancel_rx.borrow() { + let _ = observed_tx.send(()); + break; + } + if cancel_rx.changed().await.is_err() { + break; + } + } + }); + + record.set_handle(handle).await; + record.send_cancel().await; + + let observed = timeout(Duration::from_millis(200), observed_rx).await; + assert!( + observed.is_ok(), + "task should observe cancellation before the handle is dropped" + ); + assert!( + observed.unwrap().is_ok(), + "task should report cancellation observation" + ); + } }