Skip to content

Commit d07664b

Browse files
bellmanbellman
authored andcommitted
fix: keep hooks clean and close bash stdin
1 parent ce116d9 commit d07664b

2 files changed

Lines changed: 39 additions & 14 deletions

File tree

.github/hooks/pre-push

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ cd "$repo_root"
1313

1414
if [[ -x scripts/roadmap-check-ids.sh ]]; then
1515
echo "pre-push: scripts/roadmap-check-ids.sh" >&2
16-
scripts/roadmap-check-ids.sh
16+
scripts/roadmap-check-ids.sh >&2
1717
fi
1818

1919
if [[ "${SKIP_CLAW_PRE_PUSH_BUILD:-}" == "1" ]]; then

rust/crates/runtime/src/bash.rs

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -330,20 +330,24 @@ fn prepare_tokio_command(
330330
prepare_sandbox_dirs(cwd);
331331
}
332332

333-
if let Some(launcher) = build_linux_sandbox_command(command, cwd, sandbox_status) {
334-
let mut prepared = TokioCommand::new(launcher.program);
335-
prepared.args(launcher.args);
336-
prepared.current_dir(cwd);
337-
prepared.envs(launcher.env);
338-
return prepared;
339-
}
333+
let mut prepared =
334+
if let Some(launcher) = build_linux_sandbox_command(command, cwd, sandbox_status) {
335+
let mut cmd = TokioCommand::new(launcher.program);
336+
cmd.args(launcher.args);
337+
cmd.envs(launcher.env);
338+
cmd
339+
} else {
340+
let mut cmd = TokioCommand::new("sh");
341+
cmd.arg("-lc").arg(command);
342+
if sandbox_status.filesystem_active {
343+
cmd.env("HOME", cwd.join(".sandbox-home"));
344+
cmd.env("TMPDIR", cwd.join(".sandbox-tmp"));
345+
}
346+
cmd
347+
};
340348

341-
let mut prepared = TokioCommand::new("sh");
342-
prepared.arg("-lc").arg(command).current_dir(cwd);
343-
if sandbox_status.filesystem_active {
344-
prepared.env("HOME", cwd.join(".sandbox-home"));
345-
prepared.env("TMPDIR", cwd.join(".sandbox-tmp"));
346-
}
349+
prepared.current_dir(cwd);
350+
prepared.stdin(Stdio::null());
347351
prepared
348352
}
349353

@@ -419,6 +423,27 @@ mod tests {
419423
assert_eq!(structured[0]["event"], "test.hung");
420424
assert_eq!(structured[0]["data"]["provenance"], "bash.timeout");
421425
}
426+
427+
#[test]
428+
fn prevents_stdin_hangs_by_redirecting_to_null() {
429+
let output = execute_bash(BashCommandInput {
430+
command: String::from("cat"),
431+
timeout: Some(2_000),
432+
description: None,
433+
run_in_background: Some(false),
434+
dangerously_disable_sandbox: Some(true),
435+
namespace_restrictions: None,
436+
isolate_network: None,
437+
filesystem_mode: None,
438+
allowed_mounts: None,
439+
})
440+
.expect("bash command should execute cleanly");
441+
442+
assert!(
443+
!output.interrupted,
444+
"Command hung and was cut off by the timeout!"
445+
);
446+
}
422447
}
423448

424449
/// Maximum output bytes before truncation (16 KiB, matching upstream).

0 commit comments

Comments
 (0)