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`