From a52f6d43542e66b0426e02b6af3589185c29335b Mon Sep 17 00:00:00 2001 From: valdaarhun Date: Sun, 7 Aug 2022 00:07:02 +0530 Subject: [PATCH] Implement LinuxProcessList_checkPidNamespace Add actionToggle and fix LinuxProcessList_checkPidNamespace Read cgroup file irrespective of flags Improve logic to check if running in container Add isContainerOrVMSlice() Also change "(Process *)lp" to "proc" Remove check for root slice Remove Process_isRunningInContainer Co-authored-by: BenBE --- Action.c | 6 ++++ Process.h | 3 ++ linux/LinuxProcessList.c | 64 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Action.c b/Action.c index ffc4a893..1007be2f 100644 --- a/Action.c +++ b/Action.c @@ -221,6 +221,11 @@ static Htop_Reaction actionToggleUserlandThreads(State* st) { return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING; } +static Htop_Reaction actionToggleRunningInContainer(State* st){ + st->settings->hideRunningInContainer = !st->settings->hideRunningInContainer; + return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING; +} + static Htop_Reaction actionToggleProgramPath(State* st) { st->settings->showProgramPath = !st->settings->showProgramPath; return HTOP_REFRESH | HTOP_SAVE_SETTINGS; @@ -752,6 +757,7 @@ void Action_setBindings(Htop_Action* keys) { keys['K'] = actionToggleKernelThreads; keys['M'] = actionSortByMemory; keys['N'] = actionSortByPID; + keys['O'] = actionToggleRunningInContainer; keys['P'] = actionSortByCPU; keys['S'] = actionSetup; keys['T'] = actionSortByTime; diff --git a/Process.h b/Process.h index d7127ff0..fa047ace 100644 --- a/Process.h +++ b/Process.h @@ -134,6 +134,9 @@ typedef struct Process_ { /* This is a userland thread / LWP */ bool isUserlandThread; + /* This process is running inside a container */ + bool isRunningInContainer; + /* Controlling terminal identifier of the process */ unsigned long int tty_nr; diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index a28d5148..ac115f24 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -10,6 +10,7 @@ in the source distribution for its full text. #include "linux/LinuxProcessList.h" #include +#include #include #include #include @@ -763,6 +764,43 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t p return r == 7; } +static bool LinuxProcessList_checkPidNamespace(Process *process, openat_arg_t procFd) { + FILE *statusfile = fopenat(procFd, "status", "r"); + if (!statusfile) + return false; + + while (true) { + char buffer[PROC_LINE_LENGTH + 1]; + if (fgets(buffer, sizeof(buffer), statusfile) == NULL) + break; + + if (!String_startsWith(buffer, "NSpid:")) + continue; + + char *ptr = buffer; + int pid_ns_count = 0; + while(*ptr != '\0' && *ptr != '\n' && !isdigit(*ptr)) + ++ptr; + + while(*ptr != '\0' && *ptr != '\n') { + if (isdigit(*ptr)) + pid_ns_count++; + while(isdigit(*ptr)) + ++ptr; + while(*ptr != '\0' && *ptr != '\n' && !isdigit(*ptr)) + ++ptr; + } + + if (pid_ns_count > 1) + process->isRunningInContainer = true; + + break; + } + + fclose(statusfile); + return true; +} + static bool LinuxProcessList_readSmapsFile(LinuxProcess* process, openat_arg_t procFd, bool haveSmapsRollup) { //http://elixir.free-electrons.com/linux/v4.10/source/fs/proc/task_mmu.c#L719 //kernel will return data in chunks of size PAGE_SIZE or less. @@ -891,6 +929,13 @@ static void LinuxProcessList_readOpenVZData(LinuxProcess* process, openat_arg_t #endif +static bool isContainerOrVMSlice(char *cgroup) { + if (String_startsWith(cgroup, "/user") || String_startsWith(cgroup, "/system")) + return false; + + return true; +} + static void LinuxProcessList_readCGroupFile(LinuxProcess* process, openat_arg_t procFd) { FILE* file = fopenat(procFd, "cgroup", "r"); if (!file) { @@ -1453,6 +1498,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ const unsigned int activeCPUs = pl->activeCPUs; const bool hideKernelThreads = settings->hideKernelThreads; const bool hideUserlandThreads = settings->hideUserlandThreads; + const bool hideRunningInContainer = settings->hideRunningInContainer; while ((entry = readdir(dir)) != NULL) { const char* name = entry->d_name; @@ -1504,6 +1550,14 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ LinuxProcessList_recurseProcTree(this, procFd, "task", proc, period); + if ((ss->flags & PROCESS_FLAG_LINUX_CGROUP) || hideRunningInContainer) { + LinuxProcessList_readCGroupFile(lp, procFd); + if (hideRunningInContainer && lp->cgroup && isContainerOrVMSlice(lp -> cgroup)) { + if (!LinuxProcessList_checkPidNamespace(proc, procFd)) + goto errorReadingProcess; + } + } + /* * These conditions will not trigger on first occurrence, cause we need to * add the process to the ProcessList and do all one time scans @@ -1526,6 +1580,12 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ Compat_openatArgClose(procFd); continue; } + if (preExisting && hideRunningInContainer && proc->isRunningInContainer) { + proc->updated = true; + proc->show = false; + Compat_openatArgClose(procFd); + continue; + } if (ss->flags & PROCESS_FLAG_IO) LinuxProcessList_readIoFile(lp, procFd, pl->realtimeMs); @@ -1640,10 +1700,6 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ } #endif - if (ss->flags & PROCESS_FLAG_LINUX_CGROUP) { - LinuxProcessList_readCGroupFile(lp, procFd); - } - if (ss->flags & PROCESS_FLAG_LINUX_OOM) { LinuxProcessList_readOomData(lp, procFd); }