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
This commit is contained in:
jif
2026-09-27 14:55:33 +00:00
committed by copyberry
parent 41f9084b30
commit 274d41a398
+20 -4
View File
@@ -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());
(