]> granicus.if.org Git - procps-ng/commitdiff
top: forest view segmentation fault, the final solution
authorJim Warner <james.warner@comcast.net>
Tue, 6 Dec 2011 18:03:15 +0000 (12:03 -0600)
committerCraig Small <csmall@enc.com.au>
Sun, 11 Dec 2011 11:27:56 +0000 (22:27 +1100)
With forest view mode under procps-ng-3.3.0, top would catch
a SEGV and exit.  The problem was thought to be related to
some linux version 3 anamoly.

In procps-ng-3.3.1, top was protected from abnormal exit and
would display the offending processes with the special orphan
notation '?', instead of the usual artwork.

As it turns out, the problem wasn't with linux and could
surface under a 2.6.xx kernel,  The cause was an occasional
abnormal ordering of tid/tgid/ppid which went unresolved
due to a progressive proc table scan in the recursive
function forest_add().

By default the proc table scan now restarts at the beginning.
However, a #define TREE_ONEPASS is provided should one wish
to restore the 3.3.1 behavior with its reduced overhead.

top.c
top.h

diff --git a/top.c b/top.c
index 2e0ef1311c44932a40cee5e7f78399ea723bc215..9ea19bb5d7626af554ed2ccbbfe0ba5c08560748 100644 (file)
--- a/top.c
+++ b/top.c
@@ -3083,7 +3083,12 @@ static void forest_add (const int self, const int level) {
 
    Tree_ppt[Tree_idx] = Seed_ppt[self];     // add this as root or child
    Tree_ppt[Tree_idx++]->pad_3 = level;     // borrow 1 byte, 127 levels
+#ifdef TREE_ONEPASS
    for (i = self + 1; i < Frame_maxtask; i++) {
+#else
+   for (i = 0; i < Frame_maxtask; i++) {
+      if (i == self) continue;
+#endif
       if (Seed_ppt[self]->tid == Seed_ppt[i]->tgid
       || (Seed_ppt[self]->tid == Seed_ppt[i]->ppid && Seed_ppt[i]->tid == Seed_ppt[i]->tgid))
          forest_add(i, level + 1);          // got one child any others?
@@ -3110,9 +3115,10 @@ static void forest_create (WIN_t *q) {
       }
       while (0 == Seed_ppt[i]->ppid)        // identify trees (expect 2)
          forest_add(i++, 1);                // add parent plus children
-      for (i = 0; i < Frame_maxtask; i++)   // finally, protect ourselves
-         if (!Seed_ppt[i]->pad_3)           // against any kernel anomaly
-            Tree_ppt[Tree_idx++] = Seed_ppt[i];
+      if (Tree_idx != Frame_maxtask)        // this will keep us sane...
+         for (i = 0; i < Frame_maxtask; i++)
+            if (!Seed_ppt[i]->pad_3)
+               Tree_ppt[Tree_idx++] = Seed_ppt[i];
    }
    memcpy(Seed_ppt, Tree_ppt, sizeof(proc_t*) * Frame_maxtask);
 } // end: forest_create
diff --git a/top.h b/top.h
index 9dd133aa5b70ee38070bdd7d14ebcae919938cac..08641ddc6d9f34aef8dc7a13300133b82965633f 100644 (file)
--- a/top.h
+++ b/top.h
@@ -38,6 +38,7 @@
 //#define STRCMPNOCASE            /* use strcasecmp vs. strcmp when sorting  */
 //#define TERMIOS_ONLY            /* just limp along with native input only  */
 //#define TREE_NORESET            /* sort keys do NOT force forest view OFF  */
+//#define TREE_ONEPASS            /* for speed, tolerate dangling children   */
 //#define USE_X_COLHDR            /* emphasize header vs. whole col, for 'x' */