]> granicus.if.org Git - procps-ng/commitdiff
library: ensure thread group leader retrieval accuracy
authorJim Warner <james.warner@comcast.net>
Sat, 7 Aug 2021 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@dropbear.xyz>
Mon, 9 Aug 2021 12:03:23 +0000 (22:03 +1000)
With that recent addition of the autogroup provisions,
it became apparent that '/proc/<pid>/task' information
is sometimes incomplete. In fact, there's no autogroup
file at all in any '/proc/<pid>/task/<pid>' directory!

As a result, when the top -H mode was invoked, all the
processes showed a -1 for AGID, even the group leader.

So, this commit will ensure that for every TGID leader
its basic '/proc/<pid>' directory will always be used.
The 'task' subdirectory is now only used for siblings.

[ and it's time that readeither prologue was updated ]

Signed-off-by: Jim Warner <james.warner@comcast.net>
proc/readproc.c

index 03971c2f153b89acdf8034942ee1c70fbdafa714..e52b6a223be2032f2f48b7ad0e18509f6f41f806 100644 (file)
@@ -1452,12 +1452,11 @@ out:
 //////////////////////////////////////////////////////////////////////////////////
 // readeither: return a pointer to a proc_t filled with requested info about
 // the next unique process or task available.  If no more are available,
-// return a null pointer (boolean false).  Use the passed buffer instead
-// of allocating space if it is non-NULL.
+// return a null pointer (boolean false).
 proc_t *readeither (PROCTAB *restrict const PT, proc_t *restrict x) {
     static proc_t skel_p;    // skeleton proc_t, only uses tid + tgid
     static proc_t *new_p;    // for process/task transitions
-    static int canary;
+    static int canary, leader;
     char path[PROCPATHLEN];
     proc_t *ret;
 
@@ -1474,16 +1473,20 @@ next_proc:
         if (errno == ENOMEM) goto end_procs;
         // fills in the PT->path, plus skel_p.tid and skel_p.tgid
         if (!PT->finder(PT,&skel_p)) goto end_procs;       // simple_nextpid
+        leader = skel_p.tid;
         if (!task_dir_missing) break;
         if ((ret = PT->reader(PT,x))) return ret;          // simple_readproc
     }
 
 next_task:
     // fills in our path, plus x->tid and x->tgid
-    if ((!(PT->taskfinder(PT,&skel_p,x,path)))             // simple_nexttid
-    || (!(ret = PT->taskreader(PT,x,path)))) {             // simple_readtask
+    if (!(PT->taskfinder(PT,&skel_p,x,path)))              // simple_nexttid
         goto next_proc;
-    }
+    /* to avoid loss of some thread group leader data,
+       we must check its base dir, not its 'task' dir! */
+    if (x->tid == leader) ret = PT->reader(PT,x);          // simple_readproc
+    else ret = PT->taskreader(PT,x,path);                  // simple_readtask
+    if (!ret) goto next_proc;
     if (!new_p) {
         new_p = ret;
         canary = new_p->tid;