From 3f7d3834c6a820291b6855c11af918a183116bd3 Mon Sep 17 00:00:00 2001 From: Misha Davidov Date: Mon, 4 Aug 2025 15:35:15 -0700 Subject: [PATCH] exec: timeout on grandchildren We were enforcing the 10 s wall-clock limit only on the child process. If that child (bash) spawns grandchildren and we kill it on timeout, those grandchildren still have the original stdout/err pipe open, so the background tasks that are draining the pipes block forever --- codex-rs/core/src/exec.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/codex-rs/core/src/exec.rs b/codex-rs/core/src/exec.rs index 5793ccaacb..a8bbd0f52c 100644 --- a/codex-rs/core/src/exec.rs +++ b/codex-rs/core/src/exec.rs @@ -361,14 +361,13 @@ pub(crate) async fn consume_truncated_output( handle: &mut JoinHandle>>, timeout: Duration, ) -> std::io::Result> { - tokio::select! { - join_res = &mut *handle => { - match join_res { - Ok(io_res) => io_res, - Err(join_err) => Err(std::io::Error::other(join_err)), - } + match tokio::time::timeout(timeout, &mut *handle).await { + Ok(join_res) => match join_res { + Ok(io_res) => io_res, + Err(join_err) => Err(std::io::Error::other(join_err)), }, - _ = tokio::time::sleep(timeout) => { + Err(_elapsed) => { + // Timeout: abort the task to avoid hanging on open pipes. handle.abort(); Ok(Vec::new()) }