]> granicus.if.org Git - psmisc/commitdiff
pstree finds orphans
authorCraig Small <csmall@users.sourceforge.net>
Fri, 31 Aug 2012 00:05:24 +0000 (10:05 +1000)
committerCraig Small <csmall@users.sourceforge.net>
Fri, 31 Aug 2012 00:05:24 +0000 (10:05 +1000)
Commit 26f9b6c1553d021c0bf9dd85f0647dc6e210948d while fixing the missing
root pid problem introduced another problem where PIDs are out of order.
A process that has a lower PID than its PPID would appear twice with
the tree breaking in strange ways.

We now scan the entire process tree first then perform two checks
 if PID==1 is missing add it
 if a process has no parent, then make it a child of PID==1, either the
 real one or the faked one made in step 1

As this is done after all procsses are found, we don't get the previous
breakage.

Ref: https://sourceforge.net/tracker/?func=detail&aid=3537508&group_id=15273&atid=115273

Signed-off-by: Craig Small <csmall@users.sourceforge.net>
ChangeLog
doc/pstree.1
src/pstree.c

index ce56ba0038aaf1549d0735d62aacd84dc7fc08ab..4615695010d8629d829f540ac3000b2da8883128 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@ Changes in 22.20
 ================
        * pstree sorts properly on names Debian #682014
        * fuser -m regresion fixed SF #3559232, thanks to hanpt
+       * pstree finds orphaned processes SF#3537508
+
 Changes in 22.19
 ================
        * killall with no args exits again SF #3536526
index ecd182d51ff205de1efbc96ca2cf038e6b6b3691..fea80b63f71e4ec9a45d9af6cd99f99177a28790 100644 (file)
@@ -74,6 +74,13 @@ then it will prompt the user at the end of the line to press return and
 will not return until that has happened.  This is useful for when
 .B pstree
 is run in a xterminal.
+.PP
+Certain kernel or mount parameters, such as the hidepid option for procfs,
+will hide information for some processes. In these situations
+.B pstree
+will attempt to build the tree without this information, showing process
+names as question marks.
+
 .SH OPTIONS
 .IP \fB\-a\fP
 Show command line arguments.  If the command line of a process is
index 9d9e8d524e9ca94bd0bcaa21ec3fba6b5ff9c568..1d2eae30cc1644634300f9bc5369be3fa856f68d 100644 (file)
@@ -134,6 +134,7 @@ static char last_char = 0;
 static int dumped = 0;                /* used by dump_by_user */
 static int charlen = 0;                /* length of character */
 
+static void fix_orphans(void);
 /*
  * Allocates additional buffer space for width and more as needed.
  * The first call will allocate the first buffer.
@@ -248,8 +249,8 @@ static PROC *find_proc(pid_t pid)
 
     for (walk = list; walk; walk = walk->next)
         if (walk->pid == pid)
-            break;
-    return walk;
+                 return walk;
+       return NULL;
 }
 
 #ifdef WITH_SELINUX
@@ -390,21 +391,7 @@ add_proc(const char *comm, pid_t pid, pid_t ppid, pid_t pgid, uid_t uid,
         parent = new_proc("?", ppid, 0, scontext);
 #else                                /*WITH_SELINUX */
         parent = new_proc("?", ppid, 0);
-#endif                                /*WITH_SELINUX */
-       /* When using kernel 3.3 with hidepid feature enabled on /proc
-        * then we need fake root pid */
-       if (!isthread && pid != 1) {
-               PROC *root;
-               if (!(root = find_proc(1))) {
-#ifdef WITH_SELINUX
-                       root = new_proc("?", 1, 0, scontext);
-#else                                /*WITH_SELINUX */
-                       root = new_proc("?", 1, 0);
 #endif
-               }
-               add_child(root, parent);
-               parent->parent = root;
-       }
     }
     add_child(parent, this);
     this->parent = parent;
@@ -790,6 +777,7 @@ static void read_proc(void)
       free(path);
     }
   (void) closedir(dir);
+  fix_orphans();
   if (print_args)
     free(buffer);
   if (empty) {
@@ -798,6 +786,33 @@ static void read_proc(void)
   }
 }
 
+static void fix_orphans(void)
+{
+  /* When using kernel 3.3 with hidepid feature enabled on /proc
+   * then we need fake root pid and gather all the orphan processes
+   * that is, processes with no known parent
+   * As we cannot be sure if it is just the root pid or others missing
+   * we gather the lot
+   */
+  PROC *root, *walk;
+
+  if (!(root = find_proc(1))) {
+#ifdef WITH_SELINUX
+    root = new_proc("?", 1, 0, scontext);
+#else                                /*WITH_SELINUX */
+    root = new_proc("?", 1, 0);
+#endif
+  }
+  for (walk = list; walk; walk = walk->next) {
+       if (walk->pid == 1 || walk->pid == 0)
+         continue;
+       if (walk->parent == NULL) { 
+         add_child(root, walk);
+      walk->parent = root;
+       }
+  }
+}
+
 static void usage(void)
 {
     fprintf(stderr,