From: Craig Small Date: Fri, 31 Aug 2012 00:05:24 +0000 (+1000) Subject: pstree finds orphans X-Git-Tag: v22.20rc1~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f118a020b35fe6ad3d844478363dcf3186556204;p=psmisc pstree finds orphans 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 --- diff --git a/ChangeLog b/ChangeLog index ce56ba0..4615695 100644 --- 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 diff --git a/doc/pstree.1 b/doc/pstree.1 index ecd182d..fea80b6 100644 --- a/doc/pstree.1 +++ b/doc/pstree.1 @@ -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 diff --git a/src/pstree.c b/src/pstree.c index 9d9e8d5..1d2eae3 100644 --- a/src/pstree.c +++ b/src/pstree.c @@ -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,