Skip to content

Commit 90cff81

Browse files
authored
Merge pull request #343 from dezgeg/pgrep-threads
pgrep: Support -w option
2 parents 0fac169 + 8b64351 commit 90cff81

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

src/uu/pgrep/src/pgrep.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ const USAGE: &str = help_usage!("pgrep.md");
2828
#[uucore::main]
2929
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
3030
let matches = uu_app().try_get_matches_from(args)?;
31-
let settings = process_matcher::get_match_settings(&matches)?;
31+
let mut settings = process_matcher::get_match_settings(&matches)?;
32+
settings.threads = matches.get_flag("lightweight");
3233

3334
// Collect pids
3435
let pids = process_matcher::find_matching_pids(&settings);
@@ -82,7 +83,7 @@ pub fn uu_app() -> Command {
8283
.hide_default_value(true),
8384
arg!(-l --"list-name" "list PID and process name"),
8485
arg!(-a --"list-full" "list PID and full command line"),
85-
// arg!(-w --lightweight "list all TID"),
86+
arg!(-w --lightweight "list all TID"),
8687
])
8788
.args(process_matcher::clap_args(
8889
"Name of the program to find the PID of",

src/uu/pgrep/src/process.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6+
use regex::Regex;
67
use std::hash::Hash;
8+
use std::sync::LazyLock;
79
use std::{
810
collections::HashMap,
911
fmt::{self, Display, Formatter},
@@ -460,6 +462,22 @@ pub fn walk_process() -> impl Iterator<Item = ProcessInformation> {
460462
.flat_map(ProcessInformation::try_from)
461463
}
462464

465+
static THREAD_REGEX: LazyLock<Regex> = LazyLock::new(|| {
466+
Regex::new(r"^/proc/[0-9]+$|^/proc/[0-9]+/task$|^/proc/[0-9]+/task/[0-9]+$").unwrap()
467+
});
468+
469+
pub fn walk_threads() -> impl Iterator<Item = ProcessInformation> {
470+
WalkDir::new("/proc/")
471+
.min_depth(1)
472+
.max_depth(3)
473+
.follow_links(false)
474+
.into_iter()
475+
.filter_entry(|e| THREAD_REGEX.is_match(e.path().as_os_str().to_string_lossy().as_ref()))
476+
.flatten()
477+
.filter(|it| it.path().as_os_str().to_string_lossy().contains("/task/"))
478+
.flat_map(ProcessInformation::try_from)
479+
}
480+
463481
#[cfg(test)]
464482
mod tests {
465483
use super::*;

src/uu/pgrep/src/process_matcher.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use uucore::{
2121

2222
use uucore::error::{UResult, USimpleError};
2323

24-
use crate::process::{walk_process, ProcessInformation, Teletype};
24+
use crate::process::{walk_process, walk_threads, ProcessInformation, Teletype};
2525

2626
pub struct Settings {
2727
pub regex: Regex,
@@ -44,6 +44,7 @@ pub struct Settings {
4444
pub gid: Option<HashSet<u32>>,
4545
pub pgroup: Option<HashSet<u64>>,
4646
pub session: Option<HashSet<u64>>,
47+
pub threads: bool,
4748
}
4849

4950
pub fn get_match_settings(matches: &ArgMatches) -> UResult<Settings> {
@@ -100,6 +101,7 @@ pub fn get_match_settings(matches: &ArgMatches) -> UResult<Settings> {
100101
})
101102
.collect()
102103
}),
104+
threads: false,
103105
};
104106

105107
if !settings.newest
@@ -194,8 +196,14 @@ fn collect_matched_pids(settings: &Settings) -> Vec<ProcessInformation> {
194196
let filtered: Vec<ProcessInformation> = {
195197
let mut tmp_vec = Vec::new();
196198

199+
let pids = if settings.threads {
200+
walk_threads().collect::<Vec<_>>()
201+
} else {
202+
walk_process().collect::<Vec<_>>()
203+
};
197204
let our_pid = std::process::id() as usize;
198-
for mut pid in walk_process().collect::<Vec<_>>() {
205+
206+
for mut pid in pids {
199207
if pid.pid == our_pid {
200208
continue;
201209
}

tests/by-util/test_pgrep.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,3 +478,21 @@ fn test_session() {
478478
fn test_nonexisting_session() {
479479
new_ucmd!().arg("--session=9999999999").fails();
480480
}
481+
482+
#[test]
483+
#[cfg(target_os = "linux")]
484+
fn test_threads() {
485+
std::thread::Builder::new()
486+
.name("PgrepTest".to_owned())
487+
.spawn(|| {
488+
let thread_tid = unsafe { uucore::libc::gettid() };
489+
new_ucmd!()
490+
.arg("-w")
491+
.arg("PgrepTest")
492+
.succeeds()
493+
.stdout_contains(thread_tid.to_string());
494+
})
495+
.unwrap()
496+
.join()
497+
.unwrap();
498+
}

0 commit comments

Comments
 (0)