diff --git a/.vscode/cspell.dictionaries/workspace.wordlist.txt b/.vscode/cspell.dictionaries/workspace.wordlist.txt index 1d3929832a2..d936ee43ab5 100644 --- a/.vscode/cspell.dictionaries/workspace.wordlist.txt +++ b/.vscode/cspell.dictionaries/workspace.wordlist.txt @@ -183,9 +183,13 @@ LINESIZE NAMESIZE RTLD_NEXT RTLD +RTMAX +RTMIN SIGABRT SIGINT SIGKILL +SIGRTMAX +SIGRTMIN SIGSTOP SIGTERM SYS_fdatasync diff --git a/src/uu/timeout/src/timeout.rs b/src/uu/timeout/src/timeout.rs index 6944794f19c..cb483db8fb8 100644 --- a/src/uu/timeout/src/timeout.rs +++ b/src/uu/timeout/src/timeout.rs @@ -22,7 +22,7 @@ use uucore::translate; use uucore::{ format_usage, - signals::{signal_by_name_or_value, signal_name_by_value}, + signals::{signal_by_name_or_value, signal_list_name_by_value}, }; use nix::sys::signal::{SigHandler, Signal, kill}; @@ -227,7 +227,7 @@ fn report_if_verbose(signal: usize, cmd: &str, verbose: bool) { let s = if signal == 0 { "0".to_string() } else { - signal_name_by_value(signal).unwrap().to_string() + signal_list_name_by_value(signal).unwrap() }; let mut stderr = std::io::stderr(); let _ = writeln!( diff --git a/src/uucore/src/lib/features/signals.rs b/src/uucore/src/lib/features/signals.rs index 6b89704fcad..a5141f299e3 100644 --- a/src/uucore/src/lib/features/signals.rs +++ b/src/uucore/src/lib/features/signals.rs @@ -396,11 +396,24 @@ pub static ALL_SIGNALS: [&str; 32] = [ pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option { let signal_name_upcase = signal_name_or_value.to_uppercase(); if let Ok(value) = signal_name_upcase.parse() { - return if is_signal(value) { Some(value) } else { None }; + if is_signal(value) { + return Some(value); + } + return realtime_signal_bounds() + .filter(|&(rtmin, rtmax)| value >= rtmin && value <= rtmax) + .map(|_| value); } let signal_name = signal_name_upcase.trim_start_matches("SIG"); - ALL_SIGNALS.iter().position(|&s| s == signal_name) + if let Some(pos) = ALL_SIGNALS.iter().position(|&s| s == signal_name) { + return Some(pos); + } + + realtime_signal_bounds().and_then(|(rtmin, rtmax)| match signal_name { + "RTMIN" => Some(rtmin), + "RTMAX" => Some(rtmax), + _ => None, + }) } /// Returns true if the given number is a valid signal number. @@ -754,3 +767,19 @@ fn linux_unnamed_signal_numbers_are_valid_for_lists() { assert_eq!(signal_list_value_by_name_or_number("32"), Some(32)); assert_eq!(signal_list_value_by_name_or_number("33"), Some(33)); } + +#[cfg(any(target_os = "linux", target_os = "android"))] +#[test] +fn linux_realtime_signals_resolve_by_name_or_value() { + let (rtmin, rtmax) = realtime_signal_bounds().unwrap(); + + // By name + assert_eq!(signal_by_name_or_value("RTMIN"), Some(rtmin)); + assert_eq!(signal_by_name_or_value("RTMAX"), Some(rtmax)); + assert_eq!(signal_by_name_or_value("SIGRTMIN"), Some(rtmin)); + assert_eq!(signal_by_name_or_value("SIGRTMAX"), Some(rtmax)); + + // By numeric value + assert_eq!(signal_by_name_or_value(&rtmin.to_string()), Some(rtmin)); + assert_eq!(signal_by_name_or_value(&rtmax.to_string()), Some(rtmax)); +} diff --git a/tests/by-util/test_timeout.rs b/tests/by-util/test_timeout.rs index 4bbc532e9cc..bb2ea78b825 100644 --- a/tests/by-util/test_timeout.rs +++ b/tests/by-util/test_timeout.rs @@ -286,3 +286,21 @@ fn test_foreground_signal0_kill_after() { .args(&["--foreground", "-s0", "-k.1", ".1", "sleep", "10"]) .fails_with_code(137); } + +#[test] +#[cfg(any(target_os = "linux", target_os = "android"))] +fn test_realtime_signal_names() { + // timeout should accept RTMIN and RTMAX as valid signal names + new_ucmd!() + .args(&["-v", "-s", "RTMAX", ".1", "sleep", "1"]) + .fails() + .stderr_contains("sending signal RTMAX to command"); + new_ucmd!() + .args(&["-v", "-s", "RTMIN", ".1", "sleep", "1"]) + .fails() + .stderr_contains("sending signal RTMIN to command"); + new_ucmd!() + .args(&["-v", "-s", "SIGRTMAX", ".1", "sleep", "1"]) + .fails() + .stderr_contains("sending signal RTMAX to command"); +}