[codex-rs] Improve linux sandbox timeouts (#662)

* Fixes flaking rust unit test
* Adds explicit sandbox exec timeout handling
This commit is contained in:
Parker Thompson
2025-04-25 12:56:20 -07:00
committed by GitHub
parent 55e25abf78
commit 7d9de34bc7
3 changed files with 40 additions and 11 deletions

View File

@@ -1,4 +1,6 @@
use std::io;
#[cfg(target_family = "unix")]
use std::os::unix::process::ExitStatusExt;
use std::path::PathBuf;
use std::process::ExitStatus;
use std::process::Stdio;
@@ -18,17 +20,18 @@ use crate::error::Result;
use crate::error::SandboxErr;
use crate::protocol::SandboxPolicy;
/// Maximum we send for each stream, which is either:
/// - 10KiB OR
/// - 256 lines
// Maximum we send for each stream, which is either:
// - 10KiB OR
// - 256 lines
const MAX_STREAM_OUTPUT: usize = 10 * 1024;
const MAX_STREAM_OUTPUT_LINES: usize = 256;
const DEFAULT_TIMEOUT_MS: u64 = 10_000;
/// Hardcode this since it does not seem worth including the libc craate just
/// for this.
// Hardcode these since it does not seem worth including the libc crate just
// for these.
const SIGKILL_CODE: i32 = 9;
const TIMEOUT_CODE: i32 = 64;
const MACOS_SEATBELT_READONLY_POLICY: &str = include_str!("seatbelt_readonly_policy.sbpl");
@@ -113,10 +116,20 @@ pub async fn process_exec_tool_call(
let duration = start.elapsed();
match raw_output_result {
Ok(raw_output) => {
let exit_code = raw_output.exit_status.code().unwrap_or(-1);
let stdout = String::from_utf8_lossy(&raw_output.stdout).to_string();
let stderr = String::from_utf8_lossy(&raw_output.stderr).to_string();
#[cfg(target_family = "unix")]
match raw_output.exit_status.signal() {
Some(TIMEOUT_CODE) => return Err(CodexErr::Sandbox(SandboxErr::Timeout)),
Some(signal) => {
return Err(CodexErr::Sandbox(SandboxErr::Signal(signal)));
}
None => {}
}
let exit_code = raw_output.exit_status.code().unwrap_or(-1);
// NOTE(ragona): This is much less restrictive than the previous check. If we exec
// a command, and it returns anything other than success, we assume that it may have
// been a sandboxing error and allow the user to retry. (The user of course may choose
@@ -244,7 +257,7 @@ pub async fn exec(
// timeout
child.start_kill()?;
// Debatable whether `child.wait().await` should be called here.
synthetic_exit_status(128 + SIGKILL_CODE)
synthetic_exit_status(128 + TIMEOUT_CODE)
}
}
}