From 274d41a39850eaaf4b60d0cfa66ea52dc917b274 Mon Sep 17 00:00:00 2001 From: jif Date: Sun, 27 Sep 2026 14:47:22 +0000 Subject: [PATCH] Prevent Linux ETXTBSY races in MCP stdio tests (#48724) ## Why Concurrent test spawns can inherit a writable descriptor for the MCP server wrapper, causing `ETXTBSY` when launching it on Linux. ## What changed Write the wrapper through a separate `/bin/sh` process on Linux so its writable descriptor stays out of the test process. Check the writer's exit status and include stderr on failure. Retain direct file writes on other Unix platforms. GitOrigin-RevId: f99952ec000ba7317243e87fd664dc0e31bb7b24 --- codex-rs/rmcp-client/tests/mcp_2026_stdio.rs | 24 ++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/codex-rs/rmcp-client/tests/mcp_2026_stdio.rs b/codex-rs/rmcp-client/tests/mcp_2026_stdio.rs index 53ba7fbb95..3c7e5ee117 100644 --- a/codex-rs/rmcp-client/tests/mcp_2026_stdio.rs +++ b/codex-rs/rmcp-client/tests/mcp_2026_stdio.rs @@ -55,10 +55,26 @@ async fn exercise_stdio_server( } else { use std::os::unix::fs::PermissionsExt; let wrapper = root.path().join("server"); - std::fs::write( - &wrapper, - "#!/bin/sh\nprintf '%s' \"$0\" > argv0\nexec \"$MCP_SERVER\" \"$@\"\n", - )?; + let script = "#!/bin/sh\nprintf '%s' \"$0\" > argv0\nexec \"$MCP_SERVER\" \"$@\"\n"; + #[cfg(target_os = "linux")] + { + // Keep the writable descriptor out of this process so concurrent test + // spawns cannot inherit it and cause ETXTBSY when launching the wrapper. + let output = std::process::Command::new("/bin/sh") + .arg("-c") + .arg("printf '%s' \"$1\" > \"$2\"") + .arg("write-mcp-fixture") + .arg(script) + .arg(&wrapper) + .output()?; + anyhow::ensure!( + output.status.success(), + "failed to write MCP wrapper: {}", + String::from_utf8_lossy(&output.stderr) + ); + } + #[cfg(not(target_os = "linux"))] + std::fs::write(&wrapper, script)?; std::fs::set_permissions(wrapper, std::fs::Permissions::from_mode(0o755))?; env.insert(OsString::from("MCP_SERVER"), server.into_os_string()); (