aboutsummaryrefslogtreecommitdiffstats
path: root/linux
diff options
context:
space:
mode:
authorDaniel Lange <DLange@git.local>2022-05-02 16:04:21 +0200
committerDaniel Lange <DLange@git.local>2022-05-02 16:04:21 +0200
commit1b805a31720727008b32b1129a167758519fd4db (patch)
tree900c84e10a25f2c8eaeec3ae54f1365688ce02a4 /linux
parenta6822e98434cf7da6fab033898094976d881ee0f (diff)
downloaddebian_htop-1b805a31720727008b32b1129a167758519fd4db.tar.gz
debian_htop-1b805a31720727008b32b1129a167758519fd4db.tar.bz2
debian_htop-1b805a31720727008b32b1129a167758519fd4db.zip
New upstream version 3.2.0upstream/3.2.0
Diffstat (limited to 'linux')
-rw-r--r--linux/CGroupUtils.c26
-rw-r--r--linux/LinuxProcess.c22
-rw-r--r--linux/LinuxProcessList.c83
-rw-r--r--linux/Platform.c104
-rw-r--r--linux/Platform.h4
5 files changed, 182 insertions, 57 deletions
diff --git a/linux/CGroupUtils.c b/linux/CGroupUtils.c
index 6f3b6fe..22cce91 100644
--- a/linux/CGroupUtils.c
+++ b/linux/CGroupUtils.c
@@ -33,7 +33,7 @@ static bool StrBuf_putc_write(StrBuf_state* p, char c) {
}
static bool StrBuf_putsn(StrBuf_state* p, StrBuf_putc_t w, const char* s, size_t count) {
- while (count--)
+ for (; count; count--)
if (!w(p, *s++))
return false;
@@ -66,6 +66,7 @@ static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrB
const char* str_user_slice = "user.slice";
const char* str_machine_slice = "machine.slice";
const char* str_user_slice_prefix = "/user-";
+ const char* str_system_slice_prefix = "/system-";
const char* str_lxc_monitor_legacy = "lxc.monitor";
const char* str_lxc_payload_legacy = "lxc.payload";
@@ -76,6 +77,8 @@ static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrB
const char* str_nspawn_monitor_label = "/supervisor";
const char* str_nspawn_payload_label = "/payload";
+ const char* str_snap_scope_prefix = "snap.";
+
const char* str_service_suffix = ".service";
const char* str_scope_suffix = ".scope";
@@ -100,6 +103,11 @@ static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrB
if (!StrBuf_putsz(s, w, "[S]"))
return false;
+ if (String_startsWith(cgroup, str_system_slice_prefix)) {
+ cgroup = strchrnul(cgroup + 1, '/');
+ continue;
+ }
+
continue;
}
@@ -267,6 +275,22 @@ static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrB
cgroup += strlen(str_nspawn_payload_label);
continue;
+ } else if(Label_checkPrefix(labelStart, scopeNameLen, str_snap_scope_prefix)) {
+ const char* nextDot = strchrnul(labelStart + strlen(str_snap_scope_prefix), '.');
+
+ if (!StrBuf_putsz(s, w, "!snap:"))
+ return false;
+
+ if (nextDot >= labelStart + scopeNameLen) {
+ nextDot = labelStart + scopeNameLen;
+ }
+
+ if (!StrBuf_putsn(s, w, labelStart + strlen(str_snap_scope_prefix), nextDot - (labelStart + strlen(str_snap_scope_prefix))))
+ return false;
+
+ cgroup = nextSlash;
+
+ continue;
}
if (!w(s, '!'))
diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c
index ba2dbd4..299b167 100644
--- a/linux/LinuxProcess.c
+++ b/linux/LinuxProcess.c
@@ -57,8 +57,8 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
[M_DRS] = { .name = "M_DRS", .title = " DATA ", .description = "Size of the data segment plus stack usage of the process", .flags = 0, .defaultSortDesc = true, },
[M_LRS] = { .name = "M_LRS", .title = " LIB ", .description = "The library size of the process (calculated from memory maps)", .flags = PROCESS_FLAG_LINUX_LRS_FIX, .defaultSortDesc = true, },
[ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, },
- [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, },
- [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, },
+ [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, },
+ [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, .autoWidth = true, },
[PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, },
[USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, },
[TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, },
@@ -81,8 +81,8 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
[IO_READ_RATE] = { .name = "IO_READ_RATE", .title = " DISK READ ", .description = "The I/O rate of read(2) in bytes per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, },
[IO_WRITE_RATE] = { .name = "IO_WRITE_RATE", .title = " DISK WRITE ", .description = "The I/O rate of write(2) in bytes per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, },
[IO_RATE] = { .name = "IO_RATE", .title = " DISK R/W ", .description = "Total I/O rate in bytes per second", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, },
- [CGROUP] = { .name = "CGROUP", .title = "CGROUP (raw) ", .description = "Which cgroup the process is in", .flags = PROCESS_FLAG_LINUX_CGROUP, },
- [CCGROUP] = { .name = "CCGROUP", .title = "CGROUP (compressed) ", .description = "Which cgroup the process is in (condensed to essentials)", .flags = PROCESS_FLAG_LINUX_CGROUP, },
+ [CGROUP] = { .name = "CGROUP", .title = "CGROUP (raw)", .description = "Which cgroup the process is in", .flags = PROCESS_FLAG_LINUX_CGROUP, .autoWidth = true, },
+ [CCGROUP] = { .name = "CCGROUP", .title = "CGROUP (compressed)", .description = "Which cgroup the process is in (condensed to essentials)", .flags = PROCESS_FLAG_LINUX_CGROUP, .autoWidth = true, },
[OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, .defaultSortDesc = true, },
[IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, },
#ifdef HAVE_DELAYACCT
@@ -94,7 +94,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
[M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, },
[M_PSSWP] = { .name = "M_PSSWP", .title = " PSSWP ", .description = "shows proportional swap share of this mapping, unlike \"Swap\", this does not take into account swapped out page of underlying shmem objects", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, },
[CTXT] = { .name = "CTXT", .title = " CTXT ", .description = "Context switches (incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches)", .flags = PROCESS_FLAG_LINUX_CTXT, .defaultSortDesc = true, },
- [SECATTR] = { .name = "SECATTR", .title = "Security Attribute ", .description = "Security attribute of the process (e.g. SELinux or AppArmor)", .flags = PROCESS_FLAG_LINUX_SECATTR, },
+ [SECATTR] = { .name = "SECATTR", .title = "Security Attribute", .description = "Security attribute of the process (e.g. SELinux or AppArmor)", .flags = PROCESS_FLAG_LINUX_SECATTR, .autoWidth = true, },
[PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process from /proc/[pid]/comm", .flags = 0, },
[PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process from /proc/[pid]/exe", .flags = 0, },
[CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, },
@@ -248,8 +248,8 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
#ifdef HAVE_VSERVER
case VXID: xSnprintf(buffer, n, "%5u ", lp->vxid); break;
#endif
- case CGROUP: xSnprintf(buffer, n, "%-35.35s ", lp->cgroup ? lp->cgroup : "N/A"); break;
- case CCGROUP: xSnprintf(buffer, n, "%-35.35s ", lp->cgroup_short ? lp->cgroup_short : (lp->cgroup ? lp->cgroup : "N/A")); break;
+ case CGROUP: xSnprintf(buffer, n, "%-*.*s ", Process_fieldWidths[CGROUP], Process_fieldWidths[CGROUP], lp->cgroup ? lp->cgroup : "N/A"); break;
+ case CCGROUP: xSnprintf(buffer, n, "%-*.*s ", Process_fieldWidths[CCGROUP], Process_fieldWidths[CCGROUP], lp->cgroup_short ? lp->cgroup_short : (lp->cgroup ? lp->cgroup : "N/A")); break;
case OOM: xSnprintf(buffer, n, "%4u ", lp->oom); break;
case IO_PRIORITY: {
int klass = IOPriority_class(lp->ioPriority);
@@ -270,9 +270,9 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
break;
}
#ifdef HAVE_DELAYACCT
- case PERCENT_CPU_DELAY: Process_printPercentage(lp->cpu_delay_percent, buffer, n, &attr); break;
- case PERCENT_IO_DELAY: Process_printPercentage(lp->blkio_delay_percent, buffer, n, &attr); break;
- case PERCENT_SWAP_DELAY: Process_printPercentage(lp->swapin_delay_percent, buffer, n, &attr); break;
+ case PERCENT_CPU_DELAY: Process_printPercentage(lp->cpu_delay_percent, buffer, n, 4, &attr); break;
+ case PERCENT_IO_DELAY: Process_printPercentage(lp->blkio_delay_percent, buffer, n, 4, &attr); break;
+ case PERCENT_SWAP_DELAY: Process_printPercentage(lp->swapin_delay_percent, buffer, n, 4, &attr); break;
#endif
case CTXT:
if (lp->ctxt_diff > 1000) {
@@ -280,7 +280,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
}
xSnprintf(buffer, n, "%5lu ", lp->ctxt_diff);
break;
- case SECATTR: snprintf(buffer, n, "%-30.30s ", lp->secattr ? lp->secattr : "?"); break;
+ case SECATTR: snprintf(buffer, n, "%-*.*s ", Process_fieldWidths[SECATTR], Process_fieldWidths[SECATTR], lp->secattr ? lp->secattr : "N/A"); break;
case AUTOGROUP_ID:
if (lp->autogroup_id != -1) {
xSnprintf(buffer, n, "%4ld ", lp->autogroup_id);
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
index 3bfe7db..5e18f6d 100644
--- a/linux/LinuxProcessList.c
+++ b/linux/LinuxProcessList.c
@@ -174,21 +174,24 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super) {
LinuxProcessList* this = (LinuxProcessList*) super;
unsigned int existing = 0, active = 0;
- DIR* dir = opendir("/sys/devices/system/cpu");
- if (!dir) {
- this->cpuData = xReallocArrayZero(this->cpuData, super->existingCPUs ? (super->existingCPUs + 1) : 0, 2, sizeof(CPUData));
+ // Initialize the cpuData array before anything else.
+ if (!this->cpuData) {
+ this->cpuData = xCalloc(2, sizeof(CPUData));
this->cpuData[0].online = true; /* average is always "online" */
this->cpuData[1].online = true;
super->activeCPUs = 1;
super->existingCPUs = 1;
- return;
}
+ DIR* dir = opendir("/sys/devices/system/cpu");
+ if (!dir)
+ return;
+
unsigned int currExisting = super->existingCPUs;
const struct dirent* entry;
while ((entry = readdir(dir)) != NULL) {
- if (entry->d_type != DT_DIR)
+ if (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN)
continue;
if (!String_startsWith(entry->d_name, "cpu"))
@@ -233,6 +236,10 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super) {
closedir(dir);
+ // return if no CPU is found
+ if (existing < 1)
+ return;
+
#ifdef HAVE_SENSORS_SENSORS_H
/* When started with offline CPUs, libsensors does not monitor those,
* even when they become online. */
@@ -493,6 +500,8 @@ static void LinuxProcessList_readIoFile(LinuxProcess* process, openat_arg_t proc
unsigned long long last_read = process->io_read_bytes;
unsigned long long last_write = process->io_write_bytes;
+ unsigned long long time_delta = realtimeMs > process->io_last_scan_time_ms ? realtimeMs - process->io_last_scan_time_ms : 0;
+
char* buf = buffer;
const char* line;
while ((line = strsep(&buf, "\n")) != NULL) {
@@ -502,7 +511,7 @@ static void LinuxProcessList_readIoFile(LinuxProcess* process, openat_arg_t proc
process->io_rchar = strtoull(line + 7, NULL, 10);
} else if (String_startsWith(line + 1, "ead_bytes: ")) {
process->io_read_bytes = strtoull(line + 12, NULL, 10);
- process->io_rate_read_bps = (process->io_read_bytes - last_read) * /*ms to s*/1000 / (realtimeMs - process->io_last_scan_time_ms);
+ process->io_rate_read_bps = time_delta ? (process->io_read_bytes - last_read) * /*ms to s*/1000. / time_delta : NAN;
}
break;
case 'w':
@@ -510,7 +519,7 @@ static void LinuxProcessList_readIoFile(LinuxProcess* process, openat_arg_t proc
process->io_wchar = strtoull(line + 7, NULL, 10);
} else if (String_startsWith(line + 1, "rite_bytes: ")) {
process->io_write_bytes = strtoull(line + 13, NULL, 10);
- process->io_rate_write_bps = (process->io_write_bytes - last_write) * /*ms to s*/1000 / (realtimeMs - process->io_last_scan_time_ms);
+ process->io_rate_write_bps = time_delta ? (process->io_write_bytes - last_write) * /*ms to s*/1000. / time_delta : NAN;
}
break;
case 's':
@@ -900,16 +909,27 @@ static void LinuxProcessList_readCGroupFile(LinuxProcess* process, openat_arg_t
bool changed = !process->cgroup || !String_eq(process->cgroup, output);
+ Process_updateFieldWidth(CGROUP, strlen(output));
free_and_xStrdup(&process->cgroup, output);
- if (!changed)
+ if (!changed) {
+ if(process->cgroup_short) {
+ Process_updateFieldWidth(CCGROUP, strlen(process->cgroup_short));
+ } else {
+ //CCGROUP is alias to normal CGROUP if shortening fails
+ Process_updateFieldWidth(CCGROUP, strlen(process->cgroup));
+ }
return;
+ }
char* cgroup_short = CGroup_filterName(process->cgroup);
if (cgroup_short) {
+ Process_updateFieldWidth(CCGROUP, strlen(cgroup_short));
free_and_xStrdup(&process->cgroup_short, cgroup_short);
free(cgroup_short);
} else {
+ //CCGROUP is alias to normal CGROUP if shortening fails
+ Process_updateFieldWidth(CCGROUP, strlen(process->cgroup));
free(process->cgroup_short);
process->cgroup_short = NULL;
}
@@ -1027,6 +1047,9 @@ static void LinuxProcessList_readSecattrData(LinuxProcess* process, openat_arg_t
if (newline) {
*newline = '\0';
}
+
+ Process_updateFieldWidth(SECATTR, strlen(buffer));
+
if (process->secattr && String_eq(process->secattr, buffer)) {
return;
}
@@ -1370,6 +1393,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
ProcessList* pl = (ProcessList*) this;
const struct dirent* entry;
const Settings* settings = pl->settings;
+ const ScreenSettings* ss = settings->ss;
#ifdef HAVE_OPENAT
int dirFd = openat(parentFd, dirname, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
@@ -1463,7 +1487,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
continue;
}
- if (settings->flags & PROCESS_FLAG_IO)
+ if (ss->flags & PROCESS_FLAG_IO)
LinuxProcessList_readIoFile(lp, procFd, pl->realtimeMs);
if (!LinuxProcessList_readStatmFile(lp, procFd))
@@ -1472,8 +1496,9 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
{
bool prev = proc->usesDeletedLib;
- if ((settings->flags & PROCESS_FLAG_LINUX_LRS_FIX) ||
- (settings->highlightDeletedExe && !proc->procExeDeleted && !proc->isKernelThread && !proc->isUserlandThread)) {
+ if (!proc->isKernelThread && !proc->isUserlandThread &&
+ ((ss->flags & PROCESS_FLAG_LINUX_LRS_FIX) || (settings->highlightDeletedExe && !proc->procExeDeleted))) {
+
// Check if we really should recalculate the M_LRS value for this process
uint64_t passedTimeInMs = pl->realtimeMs - lp->last_mlrs_calctime;
@@ -1481,17 +1506,18 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
if (passedTimeInMs > recheck) {
lp->last_mlrs_calctime = pl->realtimeMs;
- LinuxProcessList_readMaps(lp, procFd, settings->flags & PROCESS_FLAG_LINUX_LRS_FIX, settings->highlightDeletedExe);
+ LinuxProcessList_readMaps(lp, procFd, ss->flags & PROCESS_FLAG_LINUX_LRS_FIX, settings->highlightDeletedExe);
}
} else {
/* Copy from process structure in threads and reset if setting got disabled */
proc->usesDeletedLib = (proc->isUserlandThread && parent) ? parent->usesDeletedLib : false;
+ lp->m_lrs = (proc->isUserlandThread && parent) ? ((const LinuxProcess*)parent)->m_lrs : 0;
}
proc->mergedCommand.exeChanged |= prev ^ proc->usesDeletedLib;
}
- if ((settings->flags & PROCESS_FLAG_LINUX_SMAPS) && !Process_isKernelThread(proc)) {
+ if ((ss->flags & PROCESS_FLAG_LINUX_SMAPS) && !Process_isKernelThread(proc)) {
if (!parent) {
// Read smaps file of each process only every second pass to improve performance
static int smaps_flag = 0;
@@ -1521,7 +1547,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
proc->tty_name = LinuxProcessList_updateTtyDevice(this->ttyDrivers, proc->tty_nr);
}
- if (settings->flags & PROCESS_FLAG_LINUX_IOPRIO) {
+ if (ss->flags & PROCESS_FLAG_LINUX_IOPRIO) {
LinuxProcess_updateIOPriority(lp);
}
@@ -1529,6 +1555,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
float percent_cpu = (period < 1E-6) ? 0.0F : ((lp->utime + lp->stime - lasttimes) / period * 100.0);
proc->percent_cpu = CLAMP(percent_cpu, 0.0F, activeCPUs * 100.0F);
proc->percent_mem = proc->m_resident / (double)(pl->totalMem) * 100.0;
+ Process_updateCPUFieldWidths(proc->percent_cpu);
if (! LinuxProcessList_updateUser(pl, proc, procFd))
goto errorReadingProcess;
@@ -1536,13 +1563,13 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
if (!preExisting) {
#ifdef HAVE_OPENVZ
- if (settings->flags & PROCESS_FLAG_LINUX_OPENVZ) {
+ if (ss->flags & PROCESS_FLAG_LINUX_OPENVZ) {
LinuxProcessList_readOpenVZData(lp, procFd);
}
#endif
#ifdef HAVE_VSERVER
- if (settings->flags & PROCESS_FLAG_LINUX_VSERVER) {
+ if (ss->flags & PROCESS_FLAG_LINUX_VSERVER) {
LinuxProcessList_readVServerData(lp, procFd);
}
#endif
@@ -1567,32 +1594,32 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
}
#ifdef HAVE_DELAYACCT
- if (settings->flags & PROCESS_FLAG_LINUX_DELAYACCT) {
+ if (ss->flags & PROCESS_FLAG_LINUX_DELAYACCT) {
LinuxProcessList_readDelayAcctData(this, lp);
}
#endif
- if (settings->flags & PROCESS_FLAG_LINUX_CGROUP) {
+ if (ss->flags & PROCESS_FLAG_LINUX_CGROUP) {
LinuxProcessList_readCGroupFile(lp, procFd);
}
- if (settings->flags & PROCESS_FLAG_LINUX_OOM) {
+ if (ss->flags & PROCESS_FLAG_LINUX_OOM) {
LinuxProcessList_readOomData(lp, procFd);
}
- if (settings->flags & PROCESS_FLAG_LINUX_CTXT) {
+ if (ss->flags & PROCESS_FLAG_LINUX_CTXT) {
LinuxProcessList_readCtxtData(lp, procFd);
}
- if (settings->flags & PROCESS_FLAG_LINUX_SECATTR) {
+ if (ss->flags & PROCESS_FLAG_LINUX_SECATTR) {
LinuxProcessList_readSecattrData(lp, procFd);
}
- if (settings->flags & PROCESS_FLAG_CWD) {
+ if (ss->flags & PROCESS_FLAG_CWD) {
LinuxProcessList_readCwd(lp, procFd);
}
- if ((settings->flags & PROCESS_FLAG_LINUX_AUTOGROUP) && this->haveAutogroup) {
+ if ((ss->flags & PROCESS_FLAG_LINUX_AUTOGROUP) && this->haveAutogroup) {
LinuxProcessList_readAutogroup(lp, procFd);
}
@@ -1994,7 +2021,7 @@ static inline double LinuxProcessList_scanCPUTime(ProcessList* super) {
return period;
}
-static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
+static int scanCPUFrequencyFromSysCPUFreq(LinuxProcessList* this) {
unsigned int existingCPUs = this->super.existingCPUs;
int numCPUsWithFrequency = 0;
unsigned long totalFrequency = 0;
@@ -2057,7 +2084,7 @@ static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
return 0;
}
-static void scanCPUFreqencyFromCPUinfo(LinuxProcessList* this) {
+static void scanCPUFrequencyFromCPUinfo(LinuxProcessList* this) {
FILE* file = fopen(PROCCPUINFOFILE, "r");
if (file == NULL)
return;
@@ -2114,11 +2141,11 @@ static void LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
this->cpuData[i].frequency = NAN;
}
- if (scanCPUFreqencyFromSysCPUFreq(this) == 0) {
+ if (scanCPUFrequencyFromSysCPUFreq(this) == 0) {
return;
}
- scanCPUFreqencyFromCPUinfo(this);
+ scanCPUFrequencyFromCPUinfo(this);
}
void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
@@ -2146,7 +2173,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
return;
}
- if (settings->flags & PROCESS_FLAG_LINUX_AUTOGROUP) {
+ if (settings->ss->flags & PROCESS_FLAG_LINUX_AUTOGROUP) {
// Refer to sched(7) 'autogroup feature' section
// The kernel feature can be enabled/disabled through procfs at
// any time, so check for it at the start of each sample - only
diff --git a/linux/Platform.c b/linux/Platform.c
index 93953e8..775f9ae 100644
--- a/linux/Platform.c
+++ b/linux/Platform.c
@@ -70,6 +70,10 @@ in the source distribution for its full text.
#include "LibSensors.h"
#endif
+#ifndef O_PATH
+#define O_PATH 010000000 // declare for ancient glibc versions
+#endif
+
#ifdef HAVE_LIBCAP
enum CapMode {
@@ -79,7 +83,22 @@ enum CapMode {
};
#endif
-const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 };
+bool Running_containerized = false;
+
+const ScreenDefaults Platform_defaultScreens[] = {
+ {
+ .name = "Main",
+ .columns = "PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_CPU PERCENT_MEM TIME Command",
+ .sortKey = "PERCENT_CPU",
+ },
+ {
+ .name = "I/O",
+ .columns = "PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command",
+ .sortKey = "IO_RATE",
+ },
+};
+
+const unsigned int Platform_numberOfDefaultScreens = ARRAYSIZE(Platform_defaultScreens);
const SignalItem Platform_signals[] = {
{ .name = " 0 Cancel", .number = 0 },
@@ -338,7 +357,7 @@ void Platform_setMemoryValues(Meter* this) {
this->values[3] = pl->cachedMem;
this->values[4] = pl->availableMem;
- if (lpl->zfs.enabled != 0) {
+ if (lpl->zfs.enabled != 0 && !Running_containerized) {
this->values[0] -= lpl->zfs.size;
this->values[3] += lpl->zfs.size;
}
@@ -712,18 +731,47 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) {
uint64_t totalFull = 0;
uint64_t totalRemain = 0;
- struct dirent* dirEntry = NULL;
+ const struct dirent* dirEntry;
while ((dirEntry = readdir(dir))) {
const char* entryName = dirEntry->d_name;
+#ifdef HAVE_OPENAT
+ int entryFd = openat(dirfd(dir), entryName, O_DIRECTORY | O_PATH);
+ if (entryFd < 0)
+ continue;
+#else
+ char entryFd[4096];
+ xSnprintf(entryFd, sizeof(entryFd), SYS_POWERSUPPLY_DIR "/%s", entryName);
+#endif
+
+ enum { AC, BAT } type;
if (String_startsWith(entryName, "BAT")) {
- char buffer[1024] = {0};
- char filePath[256];
- xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/uevent", entryName);
+ type = BAT;
+ } else if (String_startsWith(entryName, "AC")) {
+ type = AC;
+ } else {
+ char buffer[32];
+ ssize_t ret = xReadfileat(entryFd, "type", buffer, sizeof(buffer));
+ if (ret <= 0)
+ goto next;
+
+ /* drop optional trailing newlines */
+ for (char* buf = &buffer[(size_t)ret - 1]; *buf == '\n'; buf--)
+ *buf = '\0';
+
+ if (String_eq(buffer, "Battery"))
+ type = BAT;
+ else if (String_eq(buffer, "Mains"))
+ type = AC;
+ else
+ goto next;
+ }
- ssize_t r = xReadfile(filePath, buffer, sizeof(buffer));
+ if (type == BAT) {
+ char buffer[1024];
+ ssize_t r = xReadfileat(entryFd, "uevent", buffer, sizeof(buffer));
if (r < 0)
- continue;
+ goto next;
bool full = false;
bool now = false;
@@ -765,18 +813,15 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) {
if (!now && full && !isnan(capacityLevel))
totalRemain += capacityLevel * fullCharge;
- } else if (String_startsWith(entryName, "AC")) {
- char buffer[2] = {0};
+ } else if (type == AC) {
if (*isOnAC != AC_ERROR)
- continue;
-
- char filePath[256];
- xSnprintf(filePath, sizeof(filePath), SYS_POWERSUPPLY_DIR "/%s/online", entryName);
+ goto next;
- ssize_t r = xReadfile(filePath, buffer, sizeof(buffer));
+ char buffer[2];
+ ssize_t r = xReadfileat(entryFd, "online", buffer, sizeof(buffer));
if (r < 1) {
*isOnAC = AC_ERROR;
- continue;
+ goto next;
}
if (buffer[0] == '0')
@@ -784,6 +829,9 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) {
else if (buffer[0] == '1')
*isOnAC = AC_PRESENT;
}
+
+next:
+ Compat_openatArgClose(entryFd);
}
closedir(dir);
@@ -971,6 +1019,30 @@ bool Platform_init(void) {
LibSensors_init();
#endif
+ char target[PATH_MAX];
+ ssize_t ret = readlink(PROCDIR "/self/ns/pid", target, sizeof(target) - 1);
+ if (ret > 0) {
+ target[ret] = '\0';
+
+ if (!String_eq("pid:[4026531836]", target)) { // magic constant PROC_PID_INIT_INO from include/linux/proc_ns.h#L46
+ Running_containerized = true;
+ return true; // early return
+ }
+ }
+
+ FILE* fd = fopen(PROCDIR "/1/mounts", "r");
+ if (fd) {
+ char lineBuffer[256];
+ while (fgets(lineBuffer, sizeof(lineBuffer), fd)) {
+ // detect lxc or overlayfs and guess that this means we are running containerized
+ if (String_startsWith(lineBuffer, "lxcfs ") || String_startsWith(lineBuffer, "overlay ")) {
+ Running_containerized = true;
+ break;
+ }
+ }
+ fclose(fd);
+ } // if (fd)
+
return true;
}
diff --git a/linux/Platform.h b/linux/Platform.h
index 2e2fb3e..f2c314f 100644
--- a/linux/Platform.h
+++ b/linux/Platform.h
@@ -38,7 +38,9 @@ in the source distribution for its full text.
#endif
-extern const ProcessField Platform_defaultFields[];
+extern const ScreenDefaults Platform_defaultScreens[];
+
+extern const unsigned int Platform_numberOfDefaultScreens;
extern const SignalItem Platform_signals[];

© 2014-2024 Faster IT GmbH | imprint | privacy policy