Skip to content

Commit 11584c8

Browse files
committed
process_matcher: Fix off-by-one in signal mask
Apparently the signal masks in /proc/status are off-by-one, ie. bit 0 represents signal 1. In original pgrep signal 0 results in matching signal 64 so replicate this behaviour also.
1 parent dd470f4 commit 11584c8

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

src/uu/pgrep/src/process_matcher.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,17 @@ pub fn find_matching_pids(settings: &Settings) -> Vec<ProcessInformation> {
140140
let mut pids = collect_matched_pids(settings);
141141
#[cfg(unix)]
142142
if settings.require_handler {
143+
// Bits in SigCgt are off by one (ie. bit 0 represents signal 1, etc.)
144+
let mask_to_test = if settings.signal == 0 {
145+
// In original pgrep, testing for signal 0 seems to return results for signal 64 instead.
146+
1 << (64 - 1)
147+
} else {
148+
1 << (settings.signal - 1)
149+
};
143150
pids.retain(|pid| {
144151
let mask =
145152
u64::from_str_radix(pid.clone().status().get("SigCgt").unwrap(), 16).unwrap();
146-
mask & (1 << settings.signal) != 0
153+
mask & mask_to_test != 0
147154
});
148155
}
149156
if pids.is_empty() {

tests/by-util/test_pgrep.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,17 @@ fn test_invalid_signal() {
369369
.stderr_contains("Unknown signal 'foo'");
370370
}
371371

372+
#[test]
373+
#[cfg(target_os = "linux")]
374+
fn test_signal_that_never_matches() {
375+
new_ucmd!()
376+
.arg("--require-handler")
377+
.arg("--signal=KILL")
378+
.arg(".*")
379+
.fails()
380+
.no_output();
381+
}
382+
372383
#[test]
373384
#[cfg(target_os = "linux")]
374385
fn test_does_not_match_pid() {

0 commit comments

Comments
 (0)