Skip to content

Commit

Permalink
Merge pull request #180 from zmjackson/task-children
Browse files Browse the repository at this point in the history
Add suport for /proc/[pid]/task/[tid]/children
  • Loading branch information
eminence authored Jul 23, 2022
2 parents ee01040 + 2fe66a5 commit 18e3300
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ rust-version = "1.48"
default = ["chrono", "flate2"]

[dependencies]
rustix = { version = "0.35.6", features = ["fs", "process", "param"] }
rustix = { version = "0.35.6", features = ["fs", "process", "param", "thread"] }
bitflags = "1.2"
lazy_static = "1.0.2"
chrono = {version = "0.4.1", optional = true }
Expand Down
49 changes: 48 additions & 1 deletion src/process/task.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::io::Read;
use std::path::{Path, PathBuf};

use super::{FileWrapper, Io, Schedstat, Stat, Status};
use crate::ProcResult;
use crate::{ProcError, ProcResult};
use rustix::fd::BorrowedFd;
use rustix::io::OwnedFd;

Expand Down Expand Up @@ -75,11 +76,34 @@ impl Task {
pub fn schedstat(&self) -> ProcResult<Schedstat> {
Schedstat::from_reader(FileWrapper::open_at(&self.root, &self.fd, "schedstat")?)
}

/// Thread children from `/proc/<pid>/task/<tid>/children`
///
/// WARNING:
/// This interface is not reliable unless all the child processes are stoppped or frozen.
/// If a child task exits while the file is being read, non-exiting children may be omitted.
/// See the procfs(5) man page for more information.
///
/// This data will be unique per task.
pub fn children(&self) -> ProcResult<Vec<u32>> {
let mut buf = String::new();
let mut file = FileWrapper::open_at(&self.root, &self.fd, "children")?;
file.read_to_string(&mut buf)?;
buf.split_whitespace()
.map(|child| {
child
.parse()
.map_err(|_| ProcError::Other("Failed to parse task's child PIDs".to_string()))
})
.collect()
}
}

#[cfg(test)]
mod tests {
use crate::process::Io;
use rustix;
use std::process;
use std::sync::{Arc, Barrier};

#[test]
Expand Down Expand Up @@ -188,4 +212,27 @@ mod tests {
assert!(found_one);
assert!(found_two);
}

#[test]
fn test_task_children() {
// Use tail -f /dev/null to create two infinite processes
let mut command = process::Command::new("tail");
command.arg("-f").arg("/dev/null");
let (mut child1, mut child2) = (command.spawn().unwrap(), command.spawn().unwrap());

let tid = rustix::thread::gettid();

let children = crate::process::Process::myself()
.unwrap()
.task_from_tid(tid.as_raw_nonzero().get() as i32)
.unwrap()
.children()
.unwrap();

assert!(children.contains(&child1.id()));
assert!(children.contains(&child2.id()));

child1.kill().unwrap();
child2.kill().unwrap();
}
}
2 changes: 1 addition & 1 deletion support.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ This is an approximate list of all the files under the `/proc` mount, and an ind
* [x] `/proc/[pid]/task/[tid]/stat`
* [x] `/proc/[pid]/task/[tid]/status`
* [x] `/proc/[pid]/task/[tid]/io`
* [ ] `/proc/[pid]/task/[tid]/children`
* [x] `/proc/[pid]/task/[tid]/children`
* [ ] `/proc/[pid]/timers`
* [ ] `/proc/[pid]/timerslack_ns`
* [ ] `/proc/[pid]/uid_map`
Expand Down

0 comments on commit 18e3300

Please sign in to comment.