Skip to content

Commit 22c25b0

Browse files
Merge pull request #318 from dezgeg/pidof_t_flag
pidof: Support '-t' flag
2 parents 7ce2c32 + 967d288 commit 22c25b0

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

src/uu/pgrep/src/process.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ pub struct ProcessInformation {
186186
cached_stat: Option<Rc<Vec<String>>>,
187187

188188
cached_start_time: Option<u64>,
189+
190+
cached_thread_ids: Option<Rc<Vec<usize>>>,
189191
}
190192

191193
impl ProcessInformation {
@@ -328,6 +330,31 @@ impl ProcessInformation {
328330

329331
Teletype::Unknown
330332
}
333+
334+
pub fn thread_ids(&mut self) -> Rc<Vec<usize>> {
335+
if let Some(c) = &self.cached_thread_ids {
336+
return Rc::clone(c);
337+
}
338+
339+
let tids_dir = format!("/proc/{}/task", self.pid);
340+
let result = Rc::new(
341+
WalkDir::new(tids_dir)
342+
.min_depth(1)
343+
.max_depth(1)
344+
.follow_links(false)
345+
.into_iter()
346+
.flatten()
347+
.flat_map(|it| {
348+
it.path()
349+
.file_name()
350+
.map(|it| it.to_str().unwrap().parse::<usize>().unwrap())
351+
})
352+
.collect::<Vec<_>>(),
353+
);
354+
355+
self.cached_thread_ids = Some(Rc::clone(&result));
356+
Rc::clone(&result)
357+
}
331358
}
332359
impl TryFrom<DirEntry> for ProcessInformation {
333360
type Error = io::Error;
@@ -446,6 +473,26 @@ mod tests {
446473
assert!(result.contains(&pid_entry.tty()));
447474
}
448475

476+
#[test]
477+
#[cfg(target_os = "linux")]
478+
fn test_thread_ids() {
479+
let main_tid = unsafe { uucore::libc::gettid() };
480+
std::thread::spawn(move || {
481+
let mut pid_entry = ProcessInformation::try_new(
482+
PathBuf::from_str(&format!("/proc/{}", current_pid())).unwrap(),
483+
)
484+
.unwrap();
485+
let thread_ids = pid_entry.thread_ids();
486+
487+
assert!(thread_ids.contains(&(main_tid as usize)));
488+
489+
let new_thread_tid = unsafe { uucore::libc::gettid() };
490+
assert!(thread_ids.contains(&(new_thread_tid as usize)));
491+
})
492+
.join()
493+
.unwrap();
494+
}
495+
449496
#[test]
450497
fn test_stat_split() {
451498
let case = "32 (idle_inject/3) S 2 0 0 0 -1 69238848 0 0 0 0 0 0 0 0 -51 0 1 0 34 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 0 0 0 17 3 50 1 0 0 0 0 0 0 0 0 0 0 0";

src/uu/pidof/src/pidof.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
3333

3434
let output = collected
3535
.into_iter()
36-
.map(|it| it.pid.to_string())
36+
.map(|it| it.to_string())
3737
.collect::<Vec<_>>()
3838
.join(arg_separator);
3939

@@ -61,7 +61,7 @@ fn get_executable_name(process: &mut ProcessInformation) -> String {
6161
.to_string()
6262
}
6363

64-
fn collect_matched_pids(matches: &ArgMatches) -> Vec<ProcessInformation> {
64+
fn collect_matched_pids(matches: &ArgMatches) -> Vec<usize> {
6565
let program_names: Vec<_> = matches
6666
.get_many::<String>("program-name")
6767
.unwrap()
@@ -84,16 +84,20 @@ fn collect_matched_pids(matches: &ArgMatches) -> Vec<ProcessInformation> {
8484
let should_omit = arg_omit_pid.contains(&process.pid);
8585

8686
if contains && !should_omit {
87-
processed.push(process);
87+
if matches.get_flag("t") {
88+
processed.extend_from_slice(&process.thread_ids());
89+
} else {
90+
processed.push(process.pid);
91+
}
8892
}
8993
}
9094

91-
processed.sort_by(|a, b| b.pid.cmp(&a.pid));
95+
processed.sort_by(|a, b| b.cmp(a));
9296

9397
let flag_s = matches.get_flag("s");
9498
if flag_s {
9599
match processed.first() {
96-
Some(first) => vec![first.clone()],
100+
Some(first) => vec![*first],
97101
None => Vec::new(),
98102
}
99103
} else {
@@ -164,6 +168,13 @@ pub fn uu_app() -> Command {
164168
.help("Only return one PID")
165169
.action(ArgAction::SetTrue),
166170
)
171+
.arg(
172+
Arg::new("t")
173+
.short('t')
174+
.long("lightweight")
175+
.help("Show thread ids instead of process ids")
176+
.action(ArgAction::SetTrue),
177+
)
167178
// .arg(
168179
// Arg::new("x")
169180
// .short('x')

tests/by-util/test_pidof.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,27 @@ fn test_separator() {
8181
.stdout_matches(re);
8282
}
8383
}
84+
85+
#[test]
86+
#[cfg(target_os = "linux")]
87+
fn test_threads() {
88+
let main_tid = unsafe { uucore::libc::gettid() };
89+
std::thread::spawn(move || {
90+
let argv0 = std::env::args().next().unwrap();
91+
let our_name = std::path::Path::new(argv0.as_str())
92+
.file_name()
93+
.unwrap()
94+
.to_str()
95+
.unwrap();
96+
97+
let new_thread_tid = unsafe { uucore::libc::gettid() };
98+
new_ucmd!()
99+
.arg("-t")
100+
.arg(our_name)
101+
.succeeds()
102+
.stdout_contains(main_tid.to_string())
103+
.stdout_contains(new_thread_tid.to_string());
104+
})
105+
.join()
106+
.unwrap();
107+
}

0 commit comments

Comments
 (0)