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 <noreply@openai.com>
This commit is contained in:
starr-openai
2026-04-08 12:24:47 -07:00
parent a69385f63f
commit 0edcaba9eb
2 changed files with 66 additions and 6 deletions

View File

@@ -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",

View File

@@ -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<Self> {
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<Self> {
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() {}