From cd608f462e587ee648f4bd0b798e77a52dd66c13 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Tue, 6 Dec 2011 12:03:15 -0600 Subject: [PATCH] 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. --- top.c | 12 +++++++++--- top.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/top.c b/top.c index 2e0ef131..9ea19bb5 100644 --- 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 9dd133aa..08641ddc 100644 --- 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' */