storkit: merge 377_bug_update_story_mcp_tool_writes_front_matter_values_as_yaml_strings_instead_of_native_types

This commit is contained in:
dave
2026-03-23 18:43:14 +00:00
parent 1a7b6c7342
commit 8b85ca743e
2 changed files with 85 additions and 6 deletions

View File

@@ -102,13 +102,29 @@ fn run_command_with_timeout(
args: &[&str],
dir: &Path,
) -> Result<(bool, String), String> {
let mut child = Command::new(program)
.args(args)
// On Linux, execve can return ETXTBSY (26) briefly after a file is written
// before the kernel releases its "write open" state. Retry once after a
// short pause to handle this race condition.
let mut last_err = None;
let mut cmd = Command::new(&program);
cmd.args(args)
.current_dir(dir)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.map_err(|e| format!("Failed to spawn command: {e}"))?;
.stderr(std::process::Stdio::piped());
let mut child = loop {
match cmd.spawn() {
Ok(c) => break c,
Err(e) if e.raw_os_error() == Some(26) => {
// ETXTBSY — wait briefly and retry once
if last_err.is_some() {
return Err(format!("Failed to spawn command: {e}"));
}
last_err = Some(e);
std::thread::sleep(std::time::Duration::from_millis(50));
}
Err(e) => return Err(format!("Failed to spawn command: {e}")),
}
};
// Drain stdout/stderr in background threads so the pipe buffers never fill.
let stdout_handle = child.stdout.take().map(|r| {