From e92b692932b8313f335009758b60f67b5adaadc7 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Thu, 7 Aug 2014 00:00:00 -0500 Subject: [PATCH] top: swat a potential buglet affecting new graph modes This patch will cure a potential aberration associated with a terminal's size (SIGWINCH) and top's new graphs modes. The symptoms were a dangling tilde (~) plus the potential loss of a graph's right-most visual content. The condition was only apparent when a %Cpu approached 100% usage. Also the apparent loss of content affected the 'block' graph only. With 'bar' graphs, that affect became the loss of proper right-most bar graph colors. The cause was determined to be a combination of: 1) an unnecessary snprintf precision specification; and 2) a rounding quirk for any graphs which displayed distinct types of information (as for user/syst, used/unavail). These could then combine to produce an extra bar/block which, in turn, resulted in the truncation of a pseudo termcap attribute used by the show_special() function. What was originally interpreted as an intractable race condition turns out to be just a self inflicted wound. Reference(s): http://www.freelists.org/post/procps/top-Possible-bug-in-the-graphs,1 Signed-off-by: Jim Warner --- top/top.c | 38 ++++++++++++++++++++++++++------------ top/top.h | 1 + 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/top/top.c b/top/top.c index 554d5066..38b5b7b3 100644 --- a/top/top.c +++ b/top/top.c @@ -1877,13 +1877,11 @@ static void adj_geometry (void) { PSU_CLREOS(0); // prepare to customize potential cpu/memory graphs - Graph_adj = ((float)Screen_cols - GRAPH_prefix - GRAPH_suffix) / 100.0; - if (Graph_adj > 1.0) Graph_adj = 1.0; - else if (Screen_cols < 80) Graph_adj = (80.0 - GRAPH_prefix - GRAPH_suffix) / 100.0; Graph_len = Screen_cols - GRAPH_prefix - GRAPH_actual - GRAPH_suffix; if (Graph_len >= 0) Graph_len = GRAPH_actual; else if (Screen_cols > 80) Graph_len = Screen_cols - GRAPH_prefix - GRAPH_suffix; else Graph_len = 80 - GRAPH_prefix - GRAPH_suffix; + Graph_adj = (float)Graph_len / 100.0; fflush(stdout); Frames_signal = BREAK_off; @@ -5089,11 +5087,19 @@ static void summary_hlp (CPU_t *cpu, const char *pfx) { int ix = Curwin->rc.graph_cpus - 1; float pct_user = (float)(u_frme + n_frme) * scale, pct_syst = (float)s_frme * scale; - snprintf(user, sizeof(user), gtab[ix].user, (int)((pct_user * Graph_adj) + .5), gtab[ix].type); - snprintf(syst, sizeof(syst), gtab[ix].syst, (int)((pct_syst * Graph_adj) + .5), gtab[ix].type); +#ifndef QUICK_GRAPHS + int num_user = (int)((pct_user * Graph_adj) + .5), + num_syst = (int)((pct_syst * Graph_adj) + .5); + if (num_user + num_syst > Graph_len) --num_syst; + snprintf(user, sizeof(user), gtab[ix].user, num_user, gtab[ix].type); + snprintf(syst, sizeof(syst), gtab[ix].syst, num_syst, gtab[ix].type); +#else + snprintf(user, sizeof(user), gtab[ix].user, (int)((pct_user * Graph_adj) + .6), gtab[ix].type); + snprintf(syst, sizeof(syst), gtab[ix].syst, (int)((pct_syst * Graph_adj) + .4), gtab[ix].type); +#endif snprintf(dual, sizeof(dual), "%s%s", user, syst); - show_special(0, fmtmk("%%%s ~3%#5.1f~2/%-#5.1f~3 %3.0f[~1%-*.*s]~1\n" - , pfx, pct_user, pct_syst, pct_user + pct_syst, Graph_len +4, Graph_len +4, dual)); + show_special(0, fmtmk("%%%s ~3%#5.1f~2/%-#5.1f~3 %3.0f[~1%-*s]~1\n" + , pfx, pct_user, pct_syst, pct_user + pct_syst, Graph_len +4, dual)); } else { show_special(0, fmtmk(Cpu_States_fmts, pfx , (float)u_frme * scale, (float)s_frme * scale @@ -5243,14 +5249,22 @@ numa_nope: pct_misc = (float)(kb_main_total - kb_main_available - kb_main_used) * (100.0 / (float)kb_main_total), #endif pct_swap = kb_swap_total ? (float)kb_swap_used * (100.0 / (float)kb_swap_total) : 0; - snprintf(used, sizeof(used), gtab[ix].used, (int)((pct_used * Graph_adj) + .5), gtab[ix].type); - snprintf(util, sizeof(util), gtab[ix].misc, (int)((pct_misc * Graph_adj) + .5), gtab[ix].type); +#ifndef QUICK_GRAPHS + int num_used = (int)((pct_used * Graph_adj) + .5), + num_misc = (int)((pct_misc * Graph_adj) + .5); + if (num_used + num_misc > Graph_len) --num_misc; + snprintf(used, sizeof(used), gtab[ix].used, num_used, gtab[ix].type); + snprintf(util, sizeof(util), gtab[ix].misc, num_misc, gtab[ix].type); +#else + snprintf(used, sizeof(used), gtab[ix].used, (int)((pct_used * Graph_adj) + .6), gtab[ix].type); + snprintf(util, sizeof(util), gtab[ix].misc, (int)((pct_misc * Graph_adj) + .4), gtab[ix].type); +#endif snprintf(dual, sizeof(dual), "%s%s", used, util); snprintf(util, sizeof(util), gtab[ix].swap, (int)((pct_swap * Graph_adj) + .5), gtab[ix].type); prT(bfT(0), mkM(total)); prT(bfT(1), mkS(total)); - show_special(0, fmtmk( "%s %s:~3%#5.1f~2/%-9.9s~3[~1%-*.*s]~1\n%s %s:~3%#5.1f~2/%-9.9s~3[~1%-*.*s]~1\n" - , scT(label), N_txt(WORD_abv_mem_txt), pct_used + pct_misc, bfT(0), Graph_len +4, Graph_len +4, dual - , scT(label), N_txt(WORD_abv_swp_txt), pct_swap, bfT(1), Graph_len +2, Graph_len +2, util)); + show_special(0, fmtmk( "%s %s:~3%#5.1f~2/%-9.9s~3[~1%-*s]~1\n%s %s:~3%#5.1f~2/%-9.9s~3[~1%-*s]~1\n" + , scT(label), N_txt(WORD_abv_mem_txt), pct_used + pct_misc, bfT(0), Graph_len +4, dual + , scT(label), N_txt(WORD_abv_swp_txt), pct_swap, bfT(1), Graph_len +2, util)); } else { unsigned long kb_main_my_misc = kb_main_buffers + kb_main_cached; prT(bfT(0), mkM(total)); prT(bfT(1), mkM(free)); diff --git a/top/top.h b/top/top.h index 391da51d..3a7ca0a5 100644 --- a/top/top.h +++ b/top/top.h @@ -51,6 +51,7 @@ //#define PRETEND8CPUS /* pretend we're smp with 8 ticsers (sic) */ //#define PRETENDNOCAP /* use a terminal without essential caps */ //#define PRETEND_NUMA /* pretend 4 (or 3 w/o OFF_NUMASKIP) Nodes */ +//#define QUICK_GRAPHS /* use fast algorithim, accept +2% distort */ //#define RCFILE_NOERR /* rcfile errs silently default, vs. fatal */ //#define RECALL_FIXED /* don't reorder saved strings if recalled */ //#define RMAN_IGNORED /* don't consider auto right margin glitch */