top: eliminate a potential abend when exiting 'A' mode

In that issue cited below, Tyson Nottingham identified
a potential abend which was associated with 'alternate
display mode' plus that troublesome 'mkVIZrow1' macro.
He also offered a perfectly adequate fix for that bug.

I refer to that macro as troublesome since it's now so
widely used and sometimes (by design) causes 'begtask'
to go negative (invalid). And now I found yet one more
place where it should have been used but wasn't ('f').

It's also troublesome as evidenced by some git history
listed below. Heck, there was even a commit addressing
the same symptoms (alternate display mode abend) which
Tyson suffered. Clearly, the current design is flawed.

So, with those two issues in mind, I've refactored the
approach to maintaining a visible task in the 1st row.
Henceforth, a 'mkVIZrow1' macro will be issued in only
two places: once at startup and after most keystrokes.

Such an approach likely results in additional calls to
the 'window_hlp' routine that aren't really necessary.
But, it provides a cleaner design less prone to errors
in the future. Besides, such additional overhead would
only be incurred when interacting with the user. Thus,
new costs are of no concern and will never be noticed.

Reference(s):
. Tyson Nottingham reported problem
https://gitlab.com/procps-ng/procps/-/issues/245
. Jun, 2018 - visible row 1 tasks first addressed
commit 6aedeac667
. Jun, 2018 - adressed edge case, new bugs created
commit 9d59ddc466
. Sep, 2018 - additional edge case addressed
commit 59f02f19c7
. May, 2021 - some abends fixed, new error created
commit 8281ac4f98
. Jun, 2021 - try to prorect against future errors
commit 2ea082b4af
. Sep, 2021 - integrate mkVIZ & 'focused' tasks
commit 69978e3650

Discovered by: Tyson Nottingham
Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2022-07-26 00:00:00 -05:00 committed by Craig Small
parent 0df22d89db
commit 80e2a7a682
2 changed files with 22 additions and 28 deletions

View File

@ -4438,10 +4438,11 @@ static void win_names (WIN_t *q, const char *name) {
static void win_reset (WIN_t *q) { static void win_reset (WIN_t *q) {
SETw(q, Show_IDLEPS | Show_TASKON); SETw(q, Show_IDLEPS | Show_TASKON);
#ifndef SCROLLVAR_NO #ifndef SCROLLVAR_NO
q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = q->varcolbeg = q->focus_pid = 0; q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->varcolbeg = q->focus_pid = 0;
#else #else
q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = q->focus_pid = 0; q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->focus_pid = 0;
#endif #endif
mkVIZoff(q)
osel_clear(q); osel_clear(q);
q->findstr[0] = '\0'; q->findstr[0] = '\0';
q->rc.combine_cpus = 0; q->rc.combine_cpus = 0;
@ -4910,7 +4911,7 @@ static void forest_config (WIN_t *q) {
// watch out for newly forked/cloned tasks 'above' us ... // watch out for newly forked/cloned tasks 'above' us ...
if (q->begtask < q->focus_beg) { if (q->begtask < q->focus_beg) {
q->begtask = q->focus_beg; q->begtask = q->focus_beg;
q->begnext = 0; // as 'mkVIZoff' but in any window mkVIZoff(q)
} }
#ifdef FOCUS_HARD_Y #ifdef FOCUS_HARD_Y
// if some task 'above' us ended, try to maintain focus // if some task 'above' us ended, try to maintain focus
@ -4918,7 +4919,7 @@ static void forest_config (WIN_t *q) {
if (q->begtask > q->focus_beg if (q->begtask > q->focus_beg
&& (SCREEN_ROWS > (q->focus_end - q->focus_beg))) { && (SCREEN_ROWS > (q->focus_end - q->focus_beg))) {
q->begtask = q->focus_beg; q->begtask = q->focus_beg;
q->begnext = 0; // as 'mkVIZoff' but in any window mkVIZoff(q)
} }
#endif #endif
} }
@ -5463,7 +5464,6 @@ static void keys_global (int ch) {
case '?': case '?':
case 'h': case 'h':
help_view(); help_view();
mkVIZrow1
break; break;
case 'B': case 'B':
TOGw(w, View_NOBOLD); TOGw(w, View_NOBOLD);
@ -5490,7 +5490,6 @@ static void keys_global (int ch) {
break; break;
case 'g': case 'g':
win_select(0); win_select(0);
mkVIZrow1
break; break;
case 'H': case 'H':
Thread_mode = !Thread_mode; Thread_mode = !Thread_mode;
@ -5575,7 +5574,6 @@ static void keys_global (int ch) {
break; break;
case 'Z': case 'Z':
wins_colors(); wins_colors();
mkVIZrow1
break; break;
case '0': case '0':
Rc.zero_suppress = !Rc.zero_suppress; Rc.zero_suppress = !Rc.zero_suppress;
@ -5858,10 +5856,7 @@ static void keys_task (int ch) {
case 'O': case 'O':
case 'o': case 'o':
case kbd_CtrlO: case kbd_CtrlO:
if (VIZCHKw(w)) { if (VIZCHKw(w)) other_filters(ch);
other_filters(ch);
mkVIZrow1
}
break; break;
case 'U': case 'U':
case 'u': case 'u':
@ -5870,7 +5865,6 @@ static void keys_task (int ch) {
if (*str != kbd_ESC if (*str != kbd_ESC
&& (errmsg = user_certify(w, str, ch))) && (errmsg = user_certify(w, str, ch)))
show_msg(errmsg); show_msg(errmsg);
mkVIZrow1
} }
break; break;
case 'V': case 'V':
@ -5976,10 +5970,7 @@ static void keys_window (int ch) {
break; break;
case 'a': case 'a':
case 'w': case 'w':
if (ALTCHKw) { if (ALTCHKw) win_select(ch);
win_select(ch);
mkVIZrow1
}
break; break;
case 'G': case 'G':
if (ALTCHKw) { if (ALTCHKw) {
@ -6076,10 +6067,8 @@ static void keys_window (int ch) {
case kbd_HOME: case kbd_HOME:
#ifndef SCROLLVAR_NO #ifndef SCROLLVAR_NO
if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS)) w->begtask = w->begpflg = w->varcolbeg = 0; if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS)) w->begtask = w->begpflg = w->varcolbeg = 0;
mkVIZrow1
#else #else
if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS)) w->begtask = w->begpflg = 0; if (VIZCHKw(w)) if (CHKw(w, Show_IDLEPS)) w->begtask = w->begpflg = 0;
mkVIZrow1
#endif #endif
break; break;
case kbd_END: case kbd_END:
@ -6525,6 +6514,13 @@ static void do_key (int ch) {
key_tab[i].func(ch); key_tab[i].func(ch);
if (Frames_signal == BREAK_off) if (Frames_signal == BREAK_off)
Frames_signal = BREAK_kbd; Frames_signal = BREAK_kbd;
/* due to the proliferation of the need for 'mkVIZrow1', |
aside from 'wins_stage_2' use, we'll now issue it one |
time here. there will remain several places where the |
companion 'mkVIZrowX' macro is issued, thus the check |
for a value already in 'begnext' in this conditional. | */
if (CHKw(Curwin, Show_TASKON) && !mkVIZyes)
mkVIZrow1
goto all_done; goto all_done;
} }
}; };
@ -6911,14 +6907,11 @@ static const char *task_show (const WIN_t *q, int idx) {
/* /*
* A window_show *Helper* function ensuring that Curwin's 'begtask' * A window_show *Helper* function ensuring that a window 'begtask' |
* represents a visible process (not any hidden/filtered-out task). * represents a visible process (not any hidden/filtered-out task). |
* In reality, this function is called: * In reality this function is called exclusively for the 'current' |
* 1) exclusively for the 'current' window * window and only after available user keystroke(s) are processed. |
* 2) immediately after interacting with the user * Note: it's entirely possible there are NO visible tasks to show! | */
* 3) who struck: up, down, pgup, pgdn, home, end, 'o/O' or 'u/U'
* 4) or upon the user switching from one window to another window
* ( note: it's entirely possible there are NO visible tasks to show ) */
static void window_hlp (void) { static void window_hlp (void) {
WIN_t *w = Curwin; // avoid gcc bloat with a local copy WIN_t *w = Curwin; // avoid gcc bloat with a local copy
int i, reversed; int i, reversed;
@ -6966,7 +6959,7 @@ fwd_redux:
} }
wrap_up: wrap_up:
w->begnext = 0; mkVIZoff(w)
OFFw(w, NOPRINT_xxx); OFFw(w, NOPRINT_xxx);
} // end: window_hlp } // end: window_hlp

View File

@ -440,9 +440,10 @@ typedef struct WIN_t {
// Support for a proper (visible) row #1 whenever Curwin changes // Support for a proper (visible) row #1 whenever Curwin changes
// ( or a key which might affect vertical scrolling was struck ) // ( or a key which might affect vertical scrolling was struck )
#define mkVIZyes Curwin->begnext != 0 #define mkVIZyes ( Curwin->begnext != 0 )
#define mkVIZrow1 { Curwin->begnext = +1; Curwin->begtask -= 1; } #define mkVIZrow1 { Curwin->begnext = +1; Curwin->begtask -= 1; }
#define mkVIZrowX(n) { Curwin->begnext = (n); } #define mkVIZrowX(n) { Curwin->begnext = (n); }
#define mkVIZoff(w) { w->begnext = 0; }
/* Special Section: end ------------------------------------------ */ /* Special Section: end ------------------------------------------ */
/* /////////////////////////////////////////////////////////////// */ /* /////////////////////////////////////////////////////////////// */