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()); (