From 0edcaba9ebc9c607395efae2e1ed35c9d33ab453 Mon Sep 17 00:00:00 2001 From: starr-openai Date: Wed, 8 Apr 2026 12:24:47 -0700 Subject: [PATCH] codex: avoid arg0 dependency cycle in exec-server Keep the standalone exec-server binary capable of self-dispatching its Linux sandbox helper by materializing a private codex-linux-sandbox symlink at startup. This gives sandbox launch a real helper-looking executable path without depending on the top-level codex-arg0 dispatcher. Co-authored-by: Codex --- codex-rs/exec-server/Cargo.toml | 2 +- .../exec-server/src/bin/codex-exec-server.rs | 70 +++++++++++++++++-- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/codex-rs/exec-server/Cargo.toml b/codex-rs/exec-server/Cargo.toml index 17fd939a8b..90d569d3b8 100644 --- a/codex-rs/exec-server/Cargo.toml +++ b/codex-rs/exec-server/Cargo.toml @@ -20,7 +20,6 @@ arc-swap = { workspace = true } async-trait = { workspace = true } base64 = { workspace = true } clap = { workspace = true, features = ["derive"] } -codex-arg0 = { workspace = true } codex-sandboxing = { workspace = true } codex-app-server-protocol = { workspace = true } codex-protocol = { workspace = true } @@ -29,6 +28,7 @@ codex-utils-pty = { workspace = true } futures = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +tempfile = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true, features = [ "fs", diff --git a/codex-rs/exec-server/src/bin/codex-exec-server.rs b/codex-rs/exec-server/src/bin/codex-exec-server.rs index e5e121e5c8..67ee0db18c 100644 --- a/codex-rs/exec-server/src/bin/codex-exec-server.rs +++ b/codex-rs/exec-server/src/bin/codex-exec-server.rs @@ -1,6 +1,10 @@ use clap::Parser; -use codex_arg0::Arg0DispatchPaths; -use codex_arg0::arg0_dispatch_or_else; + +#[cfg(target_os = "linux")] +use std::path::PathBuf; + +#[cfg(target_os = "linux")] +use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0; #[derive(Debug, Parser)] struct ExecServerArgs { @@ -14,13 +18,69 @@ struct ExecServerArgs { } fn main() -> anyhow::Result<()> { - arg0_dispatch_or_else(|arg0_paths: Arg0DispatchPaths| async move { + dispatch_linux_sandbox_arg0(); + + let linux_sandbox_alias = LinuxSandboxAlias::create(); + let codex_linux_sandbox_exe = linux_sandbox_alias.as_ref().map(|alias| alias.path.clone()); + + let runtime = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build()?; + runtime.block_on(async move { let args = ExecServerArgs::parse(); - let runtime = - codex_exec_server::ExecServerRuntimeConfig::new(arg0_paths.codex_linux_sandbox_exe); + let runtime = codex_exec_server::ExecServerRuntimeConfig::new(codex_linux_sandbox_exe); codex_exec_server::run_main_with_runtime(&args.listen, runtime) .await .map_err(|err| anyhow::Error::msg(err.to_string()))?; Ok(()) }) } + +#[cfg(target_os = "linux")] +struct LinuxSandboxAlias { + _temp_dir: tempfile::TempDir, + path: PathBuf, +} + +#[cfg(not(target_os = "linux"))] +struct LinuxSandboxAlias; + +#[cfg(target_os = "linux")] +impl LinuxSandboxAlias { + fn create() -> Option { + let current_exe = std::env::current_exe().ok()?; + let temp_dir = tempfile::Builder::new() + .prefix("codex-exec-server-") + .tempdir() + .ok()?; + let path = temp_dir.path().join(CODEX_LINUX_SANDBOX_ARG0); + std::os::unix::fs::symlink(current_exe, &path).ok()?; + Some(Self { + _temp_dir: temp_dir, + path, + }) + } +} + +#[cfg(not(target_os = "linux"))] +impl LinuxSandboxAlias { + fn create() -> Option { + None + } +} + +#[cfg(target_os = "linux")] +fn dispatch_linux_sandbox_arg0() { + let argv0 = std::env::args_os().next().unwrap_or_default(); + let exe_name = std::path::Path::new(&argv0) + .file_name() + .and_then(|s| s.to_str()) + .unwrap_or(""); + + if exe_name == CODEX_LINUX_SANDBOX_ARG0 { + codex_linux_sandbox::run_main(); + } +} + +#[cfg(not(target_os = "linux"))] +fn dispatch_linux_sandbox_arg0() {}