diff --git a/src/uu/timeout/src/timeout.rs b/src/uu/timeout/src/timeout.rs index a4e34c626..0b3543f96 100644 --- a/src/uu/timeout/src/timeout.rs +++ b/src/uu/timeout/src/timeout.rs @@ -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()) } diff --git a/tests/by-util/test_timeout.rs b/tests/by-util/test_timeout.rs index eab2313a3..7e640ad75 100644 --- a/tests/by-util/test_timeout.rs +++ b/tests/by-util/test_timeout.rs @@ -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();