Skip to content

Commit 9ea07ca

Browse files
committed
fix(oneshot): retry script execution when ETXTBSY occurs
When multiple test threads run concurrently, one thread may fork while another still has the script file open for writing, causing exec to fail with ETXTBSY. Added a wait loop that probes the script with a no-op argument until the file is safe to execute, preventing spurious test failures. Auto-committed-on: dragonfly
1 parent 08d1903 commit 9ea07ca

1 file changed

Lines changed: 19 additions & 1 deletion

File tree

  • crates/tinybox-docker/src/oneshot

‎crates/tinybox-docker/src/oneshot/test.rs‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,33 @@ fn canon(p: &Path) -> String {
2929
fn fake(dir: &Path, body: &str) -> (DockerCli, PathBuf) {
3030
let out = dir.join("argv.out");
3131
let script = format!(
32-
"#!/bin/sh\n: > '{out}'\nfor a in \"$@\"; do printf '%s\\0' \"$a\" >> '{out}'; done\n{body}\n",
32+
"#!/bin/sh\n[ \"$1\" = --tinybox-probe ] && exit 0\n: > '{out}'\nfor a in \"$@\"; do printf '%s\\0' \"$a\" >> '{out}'; done\n{body}\n",
3333
out = out.display()
3434
);
3535
let path = dir.join("docker");
3636
std::fs::write(&path, script).unwrap();
3737
std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o755)).unwrap();
38+
wait_until_executable(&path);
3839
(DockerCli::with_program(&path), out)
3940
}
4041

42+
/// Another test thread may `fork` while our write handle is still open, and the
43+
/// child keeps that handle until it `exec`s; executing the script in that window
44+
/// fails with `ETXTBSY`. Probe (a no-op for the script) until the window closes.
45+
fn wait_until_executable(path: &Path) {
46+
for _ in 0..200 {
47+
match std::process::Command::new(path)
48+
.arg("--tinybox-probe")
49+
.status()
50+
{
51+
Err(e) if e.raw_os_error() == Some(26) => {
52+
std::thread::sleep(Duration::from_millis(10));
53+
}
54+
_ => return,
55+
}
56+
}
57+
}
58+
4159
fn recorded(out: &Path) -> Vec<String> {
4260
std::fs::read(out)
4361
.unwrap()

0 commit comments

Comments
 (0)