top: forest view segmentation fault, the final solution

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.
This commit is contained in:
Jim Warner 2011-12-06 12:03:15 -06:00 committed by Craig Small
parent 242be5194c
commit cd608f462e
2 changed files with 10 additions and 3 deletions

12
top.c
View File

@ -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] = Seed_ppt[self]; // add this as root or child
Tree_ppt[Tree_idx++]->pad_3 = level; // borrow 1 byte, 127 levels Tree_ppt[Tree_idx++]->pad_3 = level; // borrow 1 byte, 127 levels
#ifdef TREE_ONEPASS
for (i = self + 1; i < Frame_maxtask; i++) { 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 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)) || (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? 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) while (0 == Seed_ppt[i]->ppid) // identify trees (expect 2)
forest_add(i++, 1); // add parent plus children forest_add(i++, 1); // add parent plus children
for (i = 0; i < Frame_maxtask; i++) // finally, protect ourselves if (Tree_idx != Frame_maxtask) // this will keep us sane...
if (!Seed_ppt[i]->pad_3) // against any kernel anomaly for (i = 0; i < Frame_maxtask; i++)
Tree_ppt[Tree_idx++] = Seed_ppt[i]; if (!Seed_ppt[i]->pad_3)
Tree_ppt[Tree_idx++] = Seed_ppt[i];
} }
memcpy(Seed_ppt, Tree_ppt, sizeof(proc_t*) * Frame_maxtask); memcpy(Seed_ppt, Tree_ppt, sizeof(proc_t*) * Frame_maxtask);
} // end: forest_create } // end: forest_create

1
top.h
View File

@ -38,6 +38,7 @@
//#define STRCMPNOCASE /* use strcasecmp vs. strcmp when sorting */ //#define STRCMPNOCASE /* use strcasecmp vs. strcmp when sorting */
//#define TERMIOS_ONLY /* just limp along with native input only */ //#define TERMIOS_ONLY /* just limp along with native input only */
//#define TREE_NORESET /* sort keys do NOT force forest view OFF */ //#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' */ //#define USE_X_COLHDR /* emphasize header vs. whole col, for 'x' */