procfs icon indicating copy to clipboard operation
procfs copied to clipboard

process: support getting Process for current thread

Open jgowans opened this issue 1 year ago • 6 comments

commit 4ce9df3f1eef057dca04233fd2453e5da83bccd5 (HEAD -> thread-self, github/thread-self)
Author: James Gowans <[email protected]>
Date:   Sat Sep 24 19:19:07 2022 +0200

    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 <[email protected]>

jgowans avatar Sep 24 '22 17:09 jgowans

Updated the branch to include another commit to fix the failing random test.

jgowans avatar Sep 24 '22 19:09 jgowans

Do you mind rebasing? #205 just landed which has a conflict (it also tries to fix the poolsize test). I'm OK dropping the assert from the test, thus maybe we should just drop 833bd50 from this PR

eminence avatar Sep 24 '22 19:09 eminence

Do you mind rebasing? #205 just landed which has a conflict (it also tries to fix the poolsize test). I'm OK dropping the assert from the test, thus maybe we should just drop 833bd50 from this PR

Ah, that's great, let me rebase and drop my commit to change the pool size check.

EDIT: Done

jgowans avatar Sep 24 '22 19:09 jgowans

I have to admit I learned something while reviewing this PR: I didn't realize that you could read /proc/<thread_id>.

So three questions for you, all related:

  • Is there a difference between the contents of /proc/<pid>/task/<tid>/ and /proc/<tid>/ ?
  • Should your new thread_myself function return a Task instead of a Process?
  • Should existing APIs like task_main_thread return a Process ?

eminence avatar Sep 27 '22 01:09 eminence

Hey @jgowans -- just checking in to see how you want to proceed here.

eminence avatar Nov 30 '22 03:11 eminence

Hi @eminence; apologies I missed your reply! :facepalm:

Is there a difference between the contents of /proc//task// and /proc// ?

There do seem to be slight differences, for example:

  • /proc/<tid> has a task and map_files subdir; though the tasks are actually the tasks of the parent "thread group"
  • /proc/<tid> has a autogroup and coredump_filter file; the other doesn't.
  • /proc/<pid>/task/<tid> has a "children" file, the other doesn't.

Even the "parent task" (/proc/<pid>/task/<pid>/ ) has different data to the "parent process" (/proc/<pid>/).

So I guess this is the "process view" and "task view", independent of whether the ID is actually a parent or a thread.

thread-self is a symlink to the "task" dir, so we get the task experience:

➜  ~ ls -l /proc/thread-self
lrwxrwxrwx 1 root root 0 Nov 18 09:23 /proc/thread-self -> 3357812/task/3357812

The procfs man mage also has a nice write up; some relevant parts:

       /proc/[pid]/task (since Linux 2.6.0)
              This is a directory that contains one subdirectory for each thread in the process.  

  For attributes that are shared by all threads, the contents for each of the files under the task/[tid] subdirectories will  be  the  same  as  in  the  corresponding file in the parent /proc/[pid]

 For attributes that are distinct for each thread, the corresponding files under task/[tid] may have different values (e.g., various fields in each of the task/[tid]/status files may be  different  for each thread), or they might not exist in /proc/[pid] at all.

Should your new thread_myself function return a Task instead of a Process?

Yes, that seems much better. Anything which is a wrapper around /proc/pid/task/* should be a struct Task. I actually just hadn't seen the Task struct yet.

Will update.

Should existing APIs like task_main_thread return a Process ?

I'd say no. For that API specifically, it is implemented as getting data from /proc/pid/task/pid, hence gets the "task view" of that process because it's using the task directory. So I believe it's correct as-is.

    /// Return a task for the main thread of this process
    pub fn task_main_thread(&self) -> ProcResult<Task> {
        self.task_from_tid(self.pid)
    }

    /// Return a task for the main thread of this process
    pub fn task_from_tid(&self, tid: i32) -> ProcResult<Task> {
        let path = PathBuf::from("task").join(tid.to_string());
        Task::from_process_at(&self.root, self.fd.as_fd(), path, self.pid, tid)
    }

jgowans avatar Nov 30 '22 07:11 jgowans