Skip to content

Commit 3b20d8d

Browse files
committed
uucore: handle SIGRTMIN+N and SIGRTMAX-N notation
On Linux, signals in the range SIGRTMIN..SIGRTMAX are valid in addition to SIGRTMIN and SIGRTMAX themselves. The notation SIGRTMIN+N and SIGRTMAX-N is used to reference signals in that range. Adapt signal helpers to understand this.
1 parent f7ba1f9 commit 3b20d8d

2 files changed

Lines changed: 73 additions & 13 deletions

File tree

src/uu/env/src/env.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ fn list_signal_handling(log: &SignalActionLog) {
11481148
SignalActionKind::Ignore => "IGNORE",
11491149
SignalActionKind::Block => "BLOCK",
11501150
};
1151-
let signal_name = signal_name_by_value(sig_value).unwrap_or("?");
1151+
let signal_name = signal_name_by_value(sig_value).unwrap_or("?".to_string());
11521152
eprintln!("{signal_name:<10} ({}): {action}", sig_value as i32);
11531153
}
11541154
}

src/uucore/src/lib/features/signals.rs

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -399,31 +399,67 @@ pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<usize> {
399399
if is_signal(value) {
400400
return Some(value);
401401
}
402-
return realtime_signal_bounds()
403-
.filter(|&(rtmin, rtmax)| value >= rtmin && value <= rtmax)
404-
.map(|_| value);
405402
}
406403
let signal_name = signal_name_upcase.trim_start_matches("SIG");
407404

408405
if let Some(pos) = ALL_SIGNALS.iter().position(|&s| s == signal_name) {
409406
return Some(pos);
410407
}
411408

412-
realtime_signal_bounds().and_then(|(rtmin, rtmax)| match signal_name {
413-
"RTMIN" => Some(rtmin),
414-
"RTMAX" => Some(rtmax),
415-
_ => None,
409+
realtime_signal_bounds().and_then(|(rtmin, rtmax)| {
410+
if signal_name.starts_with("RTMIN+") {
411+
if let Ok(n) = signal_name.trim_start_matches("RTMIN+").parse::<usize>() {
412+
let value = rtmin + n;
413+
return (value >= rtmin && value <= rtmax).then_some(value);
414+
}
415+
}
416+
417+
if signal_name.starts_with("RTMAX-") {
418+
if let Ok(n) = signal_name.trim_start_matches("RTMAX-").parse::<usize>() {
419+
let value = rtmax - n;
420+
return (value >= rtmin && value <= rtmax).then_some(value);
421+
}
422+
}
423+
424+
match signal_name {
425+
"RTMIN" => Some(rtmin),
426+
"RTMAX" => Some(rtmax),
427+
_ => None,
428+
}
416429
})
417430
}
418431

419432
/// Returns true if the given number is a valid signal number.
420433
pub fn is_signal(num: usize) -> bool {
421-
num < ALL_SIGNALS.len()
434+
if num < ALL_SIGNALS.len() {
435+
return true;
436+
}
437+
438+
if let Some((rtmin, rtmax)) = realtime_signal_bounds() {
439+
return num >= rtmin && num <= rtmax;
440+
}
441+
442+
false
422443
}
423444

424445
/// Returns the signal name for a given signal value.
425-
pub fn signal_name_by_value(signal_value: usize) -> Option<&'static str> {
426-
ALL_SIGNALS.get(signal_value).copied()
446+
pub fn signal_name_by_value(signal_value: usize) -> Option<String> {
447+
if let Some(name) = ALL_SIGNALS.get(signal_value).copied() {
448+
return Some(name.to_string());
449+
}
450+
451+
realtime_signal_bounds().and_then(|(rtmin, rtmax)| {
452+
if signal_value == rtmin {
453+
Some("RTMIN".to_string())
454+
} else if signal_value == rtmax {
455+
Some("RTMAX".to_string())
456+
} else if signal_value > rtmin && signal_value < rtmax {
457+
let n = signal_value - rtmin;
458+
Some(format!("RTMIN+{n}"))
459+
} else {
460+
None
461+
}
462+
})
427463
}
428464

429465
#[cfg(any(target_os = "linux", target_os = "android"))]
@@ -449,7 +485,7 @@ pub fn signal_number_upper_bound() -> usize {
449485
/// Returns the signal name for list-style interfaces.
450486
pub fn signal_list_name_by_value(signal_value: usize) -> Option<String> {
451487
if let Some(signal_name) = signal_name_by_value(signal_value) {
452-
return Some(signal_name.to_string());
488+
return Some(signal_name);
453489
}
454490

455491
realtime_signal_bounds().and_then(|(rtmin, rtmax)| {
@@ -719,7 +755,7 @@ fn signal_by_long_name() {
719755
#[test]
720756
fn name() {
721757
for (value, signal) in ALL_SIGNALS.iter().enumerate() {
722-
assert_eq!(signal_name_by_value(value), Some(*signal));
758+
assert_eq!(signal_name_by_value(value), Some(signal.to_string()));
723759
}
724760
}
725761

@@ -783,11 +819,35 @@ fn linux_realtime_signals_resolve_by_name_or_value() {
783819

784820
// By name
785821
assert_eq!(signal_by_name_or_value("RTMIN"), Some(rtmin));
822+
for i in 1..rtmax - rtmin - 1 {
823+
assert_eq!(
824+
signal_by_name_or_value(&format!("RTMIN+{i}")),
825+
Some(rtmin + i)
826+
);
827+
assert_eq!(
828+
signal_by_name_or_value(&format!("RTMAX-{i}")),
829+
Some(rtmax - i)
830+
);
831+
}
786832
assert_eq!(signal_by_name_or_value("RTMAX"), Some(rtmax));
787833
assert_eq!(signal_by_name_or_value("SIGRTMIN"), Some(rtmin));
834+
for i in 1..rtmax - rtmin - 1 {
835+
assert_eq!(
836+
signal_by_name_or_value(&format!("SIGRTMIN+{i}")),
837+
Some(rtmin + i)
838+
);
839+
assert_eq!(
840+
signal_by_name_or_value(&format!("SIGRTMAX-{i}")),
841+
Some(rtmax - i)
842+
);
843+
}
788844
assert_eq!(signal_by_name_or_value("SIGRTMAX"), Some(rtmax));
789845

790846
// By numeric value
791847
assert_eq!(signal_by_name_or_value(&rtmin.to_string()), Some(rtmin));
848+
for i in 1..rtmax - rtmin - 1 {
849+
let value = rtmin + i;
850+
assert_eq!(signal_by_name_or_value(&value.to_string()), Some(value));
851+
}
792852
assert_eq!(signal_by_name_or_value(&rtmax.to_string()), Some(rtmax));
793853
}

0 commit comments

Comments
 (0)