timeout: exit with 128+9 when the timeout signal is KILL

identified here https://efraingaray.com/en/blog/rust-coreutils-contra-gnu/
This commit is contained in:
Sylvestre Ledru committed 2026-10-05 23:27:43 +02:00
1 parent 065068a1e3
commit a185142fda
2 files changed
+33 -1

No files matched your search

+8 -1
View File
@@ -309,7 +309,12 @@ fn timeout(
report_if_verbose(signal, &cmd[0], verbose);
platform::send_signal(process, signal, foreground, None, &spawn_state);
if let Some(kill_after) = kill_after {
// KILL cannot be caught, so a later kill is pointless and the
// exit status reports the signal instead of the timeout.
let sent_kill = signal_by_name_or_value("KILL") == Some(signal);
if let Some(kill_after) = kill_after
&& !sent_kill
{
return match wait_or_kill_process(
process,
&cmd[0],
@@ -337,6 +342,8 @@ fn timeout(
})
.unwrap_or_else(|| ExitStatus::CommandTimedOut.into());
Err(exit_code.into())
} else if sent_kill {
Err(ExitStatus::SignalSent(signal).into())
} else {
Err(ExitStatus::CommandTimedOut.into())
}
+25
View File
@@ -130,6 +130,31 @@ fn test_kill_after_preserves_timeout_exit_without_preserve_status() {
.fails_with_code(124)
.no_output();
}
/// A timeout signal of KILL reports 128 + 9 rather than 124, with or
/// without `--kill-after`; other signals keep reporting 124.
#[test]
fn test_kill_signal_reports_signal_exit_code() {
let (ts, bin) = scenario_with_bin();
for args in [
&["-s", "KILL", ".05"][..],
&["--signal=9", ".05"],
&["-s", "SIGKILL", "--kill-after=3", ".05"],
// Only the child is signaled here, but the status is still 128+9.
&["--foreground", "-s", "KILL", ".05"],
] {
ts.ucmd()
.args(args)
.args(&[bin.as_str(), "sleep", "20"])
.fails_with_code(128 + 9)
.no_output();
}
ts.ucmd()
.args(&["-s", "HUP", ".05", &bin, "sleep", "20"])
.fails_with_code(124)
.no_output();
}
#[test]
fn test_preserve_status_even_when_send_signal() {
let (ts, bin) = scenario_with_bin();