From 4ce9df3f1eef057dca04233fd2453e5da83bccd5 Mon Sep 17 00:00:00 2001 From: James Gowans Date: Sat, 24 Sep 2022 19:19:07 +0200 Subject: [PATCH] process: support getting Process for current thread Getting info about the current thread is useful when the data for the current thread is different to that of the thread group leader process. For example, schedstats. Signed-off-by: James Gowans --- src/process/mod.rs | 24 +++++++++++++++++++++++- src/process/tests.rs | 14 ++++++++++++++ support.md | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/process/mod.rs b/src/process/mod.rs index 61ace2c3..947f441f 100644 --- a/src/process/mod.rs +++ b/src/process/mod.rs @@ -822,7 +822,12 @@ impl Process { .or_else(|| { rustix::fs::readlinkat(&rustix::fs::cwd(), &root, Vec::new()) .ok() - .and_then(|s| s.to_string_lossy().parse::().ok()) + .and_then(|s| { + let s = s.to_string_lossy(); + // Symlink for /proc/thread-self has the thread PID at the end + // of the path like /proc/pid/task/tid + s.split("/").last().and_then(|l| l.parse::().ok()) + }) }); let pid = match pidres { Some(pid) => pid, @@ -835,10 +840,27 @@ impl Process { /// Returns a `Process` for the currently running process. /// /// This is done by using the `/proc/self` symlink + /// + /// Note that if this is called from a thread then the returned `Process` will be + /// that of the thread leader. This is the behaviour of /proc/self. pub fn myself() -> ProcResult { let root = PathBuf::from("/proc/self"); Self::new_with_root(root) } + + /// Returns a `Process` for the currently running thread. + /// + /// This is done by using the `/proc/thread-self` symlink + /// + /// Unlike `myself()`, the returned `Process` will be that of the thread if called + /// from a thread in a thread group. + /// Some information, such as schedstats, will be different between the thread + /// and the thread group leader process. + /// Certain information, such as `tasks` will be unavailable on threads. + pub fn thread_myself() -> ProcResult { + let root = PathBuf::from("/proc/thread-self"); + Self::new_with_root(root) + } } impl Process { diff --git a/src/process/tests.rs b/src/process/tests.rs index 6ea27d8d..c4bbaf7a 100644 --- a/src/process/tests.rs +++ b/src/process/tests.rs @@ -479,3 +479,17 @@ fn test_fdtarget() { let _ = FDTarget::from_str("n:ǟF"); let _ = FDTarget::from_str("pipe:"); } + +#[test] +fn test_thread_self() { + let handler = std::thread::spawn(|| { + let me_process = Process::myself().unwrap(); + let me_thread = Process::thread_myself().unwrap(); + // In a thread, the thread Process and thread group leader process (myself) + // should be different. + assert_ne!(me_process.pid, me_thread.pid); + // Thread should have schedstats + me_thread.schedstat().unwrap(); + }); + handler.join().unwrap(); +} diff --git a/support.md b/support.md index 7dc41858..9f4a1662 100644 --- a/support.md +++ b/support.md @@ -247,7 +247,7 @@ This is an approximate list of all the files under the `/proc` mount, and an ind * [ ] `/proc/sys/vm/user_reserve_kbytes` * [ ] `/proc/sysrq-trigger` * [ ] `/proc/sysvipc` -* [ ] `/proc/thread-self` +* [x] `/proc/thread-self` * [ ] `/proc/timer_list` * [ ] `/proc/timer_stats` * [ ] `/proc/tty`