top: adapt for running with proc mounted as subset=pid
As the issue cited below illustrates, a pids namespace
with proc mounted as subset=pid denies our library any
access to non-task data. In top's case, the result was
a fatal error message which involved "cpu statistics".
With this patch top will now assume an error involving
global cpu (stat) or memory (meminfo) data means we're
running under a restricted pids namespace. As such, an
attempt will be made to still display task level data.
[ if our assumption is incorrect, it's of no matter. ]
[ instead of a fatal error, we'll still try to offer ]
[ a user some minimally useful bit of functionality. ]
Reference(s):
https://gitlab.com/procps-ng/procps/-/issues/227
https://www.freelists.org/post/procps/three-for-newlib,1
. 1st cut at subset=pid
commit bcb837b8c7
Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
60
top/top.c
60
top/top.c
@@ -289,6 +289,10 @@ static sem_t Semaphore_tasks_beg, Semaphore_tasks_end;
|
|||||||
#if defined THREADED_CPU || defined THREADED_MEM || defined THREADED_TSK
|
#if defined THREADED_CPU || defined THREADED_MEM || defined THREADED_TSK
|
||||||
static pthread_t Thread_id_main;
|
static pthread_t Thread_id_main;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Support for a namespace with proc mounted subset=pid,
|
||||||
|
( we'll limit our display to task information only ). */
|
||||||
|
static int Restrict_some = 0;
|
||||||
|
|
||||||
/*###### Tiny useful routine(s) ########################################*/
|
/*###### Tiny useful routine(s) ########################################*/
|
||||||
|
|
||||||
@@ -3368,20 +3372,22 @@ static void before (char *me) {
|
|||||||
|
|
||||||
// get the total cpus (and, if possible, numa node total)
|
// get the total cpus (and, if possible, numa node total)
|
||||||
if ((rc = procps_stat_new(&Stat_ctx)))
|
if ((rc = procps_stat_new(&Stat_ctx)))
|
||||||
error_exit(fmtmk(N_fmt(LIB_errorcpu_fmt),__LINE__, strerror(-rc)));
|
Restrict_some = Cpu_cnt = 1;
|
||||||
if (!(Stat_reap = procps_stat_reap(Stat_ctx, which, Stat_items, MAXTBL(Stat_items))))
|
else {
|
||||||
error_exit(fmtmk(N_fmt(LIB_errorcpu_fmt),__LINE__, strerror(errno)));
|
if (!(Stat_reap = procps_stat_reap(Stat_ctx, which, Stat_items, MAXTBL(Stat_items))))
|
||||||
|
error_exit(fmtmk(N_fmt(LIB_errorcpu_fmt),__LINE__, strerror(errno)));
|
||||||
#ifndef PRETEND0NUMA
|
#ifndef PRETEND0NUMA
|
||||||
Numa_node_tot = Stat_reap->numa->total;
|
Numa_node_tot = Stat_reap->numa->total;
|
||||||
#endif
|
#endif
|
||||||
Cpu_cnt = Stat_reap->cpus->total;
|
Cpu_cnt = Stat_reap->cpus->total;
|
||||||
#ifdef PRETEND48CPU
|
#ifdef PRETEND48CPU
|
||||||
Cpu_cnt = 48;
|
Cpu_cnt = 48;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// prepare for memory stats from new library API ...
|
// prepare for memory stats from new library API ...
|
||||||
if ((rc = procps_meminfo_new(&Mem_ctx)))
|
if ((rc = procps_meminfo_new(&Mem_ctx)))
|
||||||
error_exit(fmtmk(N_fmt(LIB_errormem_fmt),__LINE__, strerror(-rc)));
|
Restrict_some = 1;
|
||||||
|
|
||||||
// establish max depth for newlib pids stack (# of result structs)
|
// establish max depth for newlib pids stack (# of result structs)
|
||||||
Pids_itms = alloc_c(sizeof(enum pids_item) * MAXTBL(Fieldstab));
|
Pids_itms = alloc_c(sizeof(enum pids_item) * MAXTBL(Fieldstab));
|
||||||
@@ -5047,6 +5053,10 @@ static void keys_global (int ch) {
|
|||||||
static void keys_summary (int ch) {
|
static void keys_summary (int ch) {
|
||||||
WIN_t *w = Curwin; // avoid gcc bloat with a local copy
|
WIN_t *w = Curwin; // avoid gcc bloat with a local copy
|
||||||
|
|
||||||
|
if (Restrict_some && ch != 'C') {
|
||||||
|
show_msg(N_txt(X_RESTRICTED_txt));
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '!':
|
case '!':
|
||||||
if (CHKw(w, View_CPUSUM) || CHKw(w, View_CPUNOD))
|
if (CHKw(w, View_CPUSUM) || CHKw(w, View_CPUNOD))
|
||||||
@@ -5734,6 +5744,22 @@ static void summary_show (void) {
|
|||||||
char tmp[MEDBUFSIZ];
|
char tmp[MEDBUFSIZ];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (Restrict_some) {
|
||||||
|
#ifdef THREADED_TSK
|
||||||
|
sem_wait(&Semaphore_tasks_end);
|
||||||
|
#endif
|
||||||
|
// Display Task States only
|
||||||
|
if (isROOM(View_STATES, 1)) {
|
||||||
|
show_special(0, fmtmk(N_unq(STATE_line_1_fmt)
|
||||||
|
, Thread_mode ? N_txt(WORD_threads_txt) : N_txt(WORD_process_txt)
|
||||||
|
, PIDSmaxt, Pids_reap->counts->running
|
||||||
|
, Pids_reap->counts->sleeping + Pids_reap->counts->other
|
||||||
|
, Pids_reap->counts->stopped, Pids_reap->counts->zombied));
|
||||||
|
Msg_row += 1;
|
||||||
|
}
|
||||||
|
goto restrict_end;
|
||||||
|
}
|
||||||
|
|
||||||
// Display Uptime and Loadavg
|
// Display Uptime and Loadavg
|
||||||
if (isROOM(View_LOADAV, 1)) {
|
if (isROOM(View_LOADAV, 1)) {
|
||||||
if (!Rc.mode_altscr)
|
if (!Rc.mode_altscr)
|
||||||
@@ -5951,6 +5977,7 @@ numa_oops:
|
|||||||
#undef memPARM
|
#undef memPARM
|
||||||
} // end: View_MEMORY
|
} // end: View_MEMORY
|
||||||
|
|
||||||
|
restrict_end:
|
||||||
#undef isROOM
|
#undef isROOM
|
||||||
#undef anyFLG
|
#undef anyFLG
|
||||||
} // end: summary_show
|
} // end: summary_show
|
||||||
@@ -6061,6 +6088,10 @@ static const char *task_show (const WIN_t *q, int idx) {
|
|||||||
break;
|
break;
|
||||||
/* s_int, scale_pcnt with special handling */
|
/* s_int, scale_pcnt with special handling */
|
||||||
case EU_CPU: // PIDS_TICS_ALL_DELTA
|
case EU_CPU: // PIDS_TICS_ALL_DELTA
|
||||||
|
if (Restrict_some) {
|
||||||
|
cp = justify_pad("?", W, Jn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
{ float u = (float)rSv(EU_CPU, u_int);
|
{ float u = (float)rSv(EU_CPU, u_int);
|
||||||
int n = rSv(EU_THD, s_int);
|
int n = rSv(EU_THD, s_int);
|
||||||
#ifndef TREE_VCPUOFF
|
#ifndef TREE_VCPUOFF
|
||||||
@@ -6130,6 +6161,10 @@ static const char *task_show (const WIN_t *q, int idx) {
|
|||||||
break;
|
break;
|
||||||
/* ul_int, scale_pcnt */
|
/* ul_int, scale_pcnt */
|
||||||
case EU_MEM: // derive from PIDS_MEM_RES
|
case EU_MEM: // derive from PIDS_MEM_RES
|
||||||
|
if (Restrict_some) {
|
||||||
|
cp = justify_pad("?", W, Jn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
cp = scale_pcnt((float)rSv(EU_MEM, ul_int) * 100 / MEM_VAL(mem_TOT), W, Jn);
|
cp = scale_pcnt((float)rSv(EU_MEM, ul_int) * 100 / MEM_VAL(mem_TOT), W, Jn);
|
||||||
break;
|
break;
|
||||||
/* ul_int, make_str with special handling */
|
/* ul_int, make_str with special handling */
|
||||||
@@ -6399,16 +6434,19 @@ static void frame_make (void) {
|
|||||||
#else
|
#else
|
||||||
tasks_refresh(NULL);
|
tasks_refresh(NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!Restrict_some) {
|
||||||
#ifdef THREADED_CPU
|
#ifdef THREADED_CPU
|
||||||
sem_post(&Semaphore_cpus_beg);
|
sem_post(&Semaphore_cpus_beg);
|
||||||
#else
|
#else
|
||||||
cpus_refresh(NULL);
|
cpus_refresh(NULL);
|
||||||
#endif
|
#endif
|
||||||
#ifdef THREADED_MEM
|
#ifdef THREADED_MEM
|
||||||
sem_post(&Semaphore_memory_beg);
|
sem_post(&Semaphore_memory_beg);
|
||||||
#else
|
#else
|
||||||
memory_refresh(NULL);
|
memory_refresh(NULL);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// whoa either first time or thread/task mode change, (re)prime the pump...
|
// whoa either first time or thread/task mode change, (re)prime the pump...
|
||||||
if (Pseudo_row == PROC_XTRA) {
|
if (Pseudo_row == PROC_XTRA) {
|
||||||
|
@@ -571,6 +571,7 @@ static void build_norm_nlstab (void) {
|
|||||||
Norm_nlstab[XTRA_warnold_txt] = _("saving prevents older top from reading, save anyway?");
|
Norm_nlstab[XTRA_warnold_txt] = _("saving prevents older top from reading, save anyway?");
|
||||||
Norm_nlstab[X_SEMAPHORES_fmt] = _("failed sem_init() at %d: %s");
|
Norm_nlstab[X_SEMAPHORES_fmt] = _("failed sem_init() at %d: %s");
|
||||||
Norm_nlstab[X_THREADINGS_fmt] = _("failed pthread_create() at %d: %s");
|
Norm_nlstab[X_THREADINGS_fmt] = _("failed pthread_create() at %d: %s");
|
||||||
|
Norm_nlstab[X_RESTRICTED_txt] = _("sorry, restricted namespace with reduced functionality");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -84,7 +84,7 @@ enum norm_nls {
|
|||||||
WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
|
WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
|
||||||
XTRA_badflds_fmt, XTRA_fixwide_fmt, XTRA_modebad_txt, XTRA_size2up_txt,
|
XTRA_badflds_fmt, XTRA_fixwide_fmt, XTRA_modebad_txt, XTRA_size2up_txt,
|
||||||
XTRA_vforest_fmt, XTRA_warncfg_txt, XTRA_warnold_txt, XTRA_winsize_txt,
|
XTRA_vforest_fmt, XTRA_warncfg_txt, XTRA_warnold_txt, XTRA_winsize_txt,
|
||||||
X_SEMAPHORES_fmt, X_THREADINGS_fmt,
|
X_RESTRICTED_txt, X_SEMAPHORES_fmt, X_THREADINGS_fmt,
|
||||||
#ifndef INSP_OFFDEMO
|
#ifndef INSP_OFFDEMO
|
||||||
YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt,
|
YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt,
|
||||||
YINSP_deqtyp_txt, YINSP_dstory_txt,
|
YINSP_deqtyp_txt, YINSP_dstory_txt,
|
||||||
|
Reference in New Issue
Block a user