Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vscode/cspell.dictionaries/workspace.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,13 @@ LINESIZE
NAMESIZE
RTLD_NEXT
RTLD
RTMAX
RTMIN
SIGABRT
SIGINT
SIGKILL
SIGRTMAX
SIGRTMIN
SIGSTOP
SIGTERM
SYS_fdatasync
Expand Down
4 changes: 2 additions & 2 deletions src/uu/timeout/src/timeout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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!(
Expand Down
33 changes: 31 additions & 2 deletions src/uucore/src/lib/features/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,11 +396,24 @@ pub static ALL_SIGNALS: [&str; 32] = [
pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<usize> {
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.
Expand Down Expand Up @@ -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));
}
18 changes: 18 additions & 0 deletions tests/by-util/test_timeout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Loading