aboutsummaryrefslogtreecommitdiffstats
path: root/linux
diff options
context:
space:
mode:
authorDaniel Lange <DLange@git.local>2022-06-03 08:55:20 +0200
committerDaniel Lange <DLange@git.local>2022-06-03 08:55:20 +0200
commit937052b231259a47d881d539ad5748245ef55b99 (patch)
tree41071229fa007d8cf6902bb9253d2acd8cc66979 /linux
parent1b805a31720727008b32b1129a167758519fd4db (diff)
downloaddebian_htop-937052b231259a47d881d539ad5748245ef55b99.tar.gz
debian_htop-937052b231259a47d881d539ad5748245ef55b99.tar.bz2
debian_htop-937052b231259a47d881d539ad5748245ef55b99.zip
New upstream version 3.2.1upstream/3.2.1
Diffstat (limited to 'linux')
-rw-r--r--linux/LinuxProcess.c14
-rw-r--r--linux/LinuxProcessList.c87
-rw-r--r--linux/Platform.c11
-rw-r--r--linux/Platform.h2
-rw-r--r--linux/SystemdMeter.c21
5 files changed, 96 insertions, 39 deletions
diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c
index 299b167..92be326 100644
--- a/linux/LinuxProcess.c
+++ b/linux/LinuxProcess.c
@@ -57,7 +57,7 @@ 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, .autoWidth = 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, },
@@ -86,9 +86,9 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
[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
- [PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD%", .description = "CPU delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
- [PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
- [PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWPD%", .description = "Swapin delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
+ [PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
+ [PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = " IOD% ", .description = "Block I/O delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
+ [PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWPD% ", .description = "Swapin delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
#endif
[M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, },
[M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, },
@@ -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, 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;
+ case PERCENT_CPU_DELAY: Process_printPercentage(lp->cpu_delay_percent, buffer, n, 5, &attr); break;
+ case PERCENT_IO_DELAY: Process_printPercentage(lp->blkio_delay_percent, buffer, n, 5, &attr); break;
+ case PERCENT_SWAP_DELAY: Process_printPercentage(lp->swapin_delay_percent, buffer, n, 5, &attr); break;
#endif
case CTXT:
if (lp->ctxt_diff > 1000) {
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
index 5e18f6d..45b045c 100644
--- a/linux/LinuxProcessList.c
+++ b/linux/LinuxProcessList.c
@@ -166,6 +166,28 @@ static void LinuxProcessList_initNetlinkSocket(LinuxProcessList* this) {
#endif
+static unsigned int scanAvailableCPUsFromCPUinfo(LinuxProcessList* this) {
+ FILE* file = fopen(PROCCPUINFOFILE, "r");
+ if (file == NULL)
+ return this->super.existingCPUs;
+
+ unsigned int availableCPUs = 0;
+
+ while (!feof(file)) {
+ char buffer[PROC_LINE_LENGTH];
+
+ if (fgets(buffer, PROC_LINE_LENGTH, file) == NULL)
+ break;
+
+ if (String_startsWith(buffer, "processor"))
+ availableCPUs++;
+ }
+
+ fclose(file);
+
+ return availableCPUs ? availableCPUs : 1;
+}
+
static void LinuxProcessList_updateCPUcount(ProcessList* super) {
/* Similar to get_nprocs_conf(3) / _SC_NPROCESSORS_CONF
* https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getsysstats.c;hb=HEAD
@@ -240,6 +262,12 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super) {
if (existing < 1)
return;
+ if (Running_containerized) {
+ /* LXC munges /proc/cpuinfo but not the /sys/devices/system/cpu/ files,
+ * so limit the visible CPUs to what the guest has been configured to see: */
+ currExisting = active = scanAvailableCPUsFromCPUinfo(this);
+ }
+
#ifdef HAVE_SENSORS_SENSORS_H
/* When started with offline CPUs, libsensors does not monitor those,
* even when they become online. */
@@ -248,7 +276,7 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super) {
#endif
super->activeCPUs = active;
- assert(existing == currExisting);
+ assert(Running_containerized || (existing == currExisting));
super->existingCPUs = currExisting;
}
@@ -1323,7 +1351,8 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t proc
if (process->procExeDeleted)
filename[filenameLen - markerLen] = '\0';
- process->mergedCommand.exeChanged |= oldExeDeleted ^ process->procExeDeleted;
+ if (oldExeDeleted != process->procExeDeleted)
+ process->mergedCommand.lastUpdate = 0;
}
Process_updateExe(process, filename);
@@ -1389,6 +1418,21 @@ static char* LinuxProcessList_updateTtyDevice(TtyDriver* ttyDrivers, unsigned lo
return out;
}
+static bool isOlderThan(const ProcessList* pl, const Process* proc, unsigned int seconds) {
+ assert(pl->realtimeMs > 0);
+
+ /* Starttime might not yet be parsed */
+ if (proc->starttime_ctime <= 0)
+ return false;
+
+ uint64_t realtime = pl->realtimeMs / 1000;
+
+ if (realtime < (uint64_t)proc->starttime_ctime)
+ return false;
+
+ return realtime - proc->starttime_ctime > seconds;
+}
+
static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_t parentFd, const char* dirname, const Process* parent, double period) {
ProcessList* pl = (ProcessList*) this;
const struct dirent* entry;
@@ -1446,22 +1490,22 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
if (parent && pid == parent->pid)
continue;
- bool preExisting;
- Process* proc = ProcessList_getProcess(pl, pid, &preExisting, LinuxProcess_new);
- LinuxProcess* lp = (LinuxProcess*) proc;
-
- proc->tgid = parent ? parent->pid : pid;
- proc->isUserlandThread = proc->pid != proc->tgid;
-
#ifdef HAVE_OPENAT
int procFd = openat(dirFd, entry->d_name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
if (procFd < 0)
- goto errorReadingProcess;
+ continue;
#else
char procFd[4096];
xSnprintf(procFd, sizeof(procFd), "%s/%s", dirFd, entry->d_name);
#endif
+ bool preExisting;
+ Process* proc = ProcessList_getProcess(pl, pid, &preExisting, LinuxProcess_new);
+ LinuxProcess* lp = (LinuxProcess*) proc;
+
+ proc->tgid = parent ? parent->pid : pid;
+ proc->isUserlandThread = proc->pid != proc->tgid;
+
LinuxProcessList_recurseProcTree(this, procFd, "task", proc, period);
/*
@@ -1497,7 +1541,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
bool prev = proc->usesDeletedLib;
if (!proc->isKernelThread && !proc->isUserlandThread &&
- ((ss->flags & PROCESS_FLAG_LINUX_LRS_FIX) || (settings->highlightDeletedExe && !proc->procExeDeleted))) {
+ ((ss->flags & PROCESS_FLAG_LINUX_LRS_FIX) || (settings->highlightDeletedExe && !proc->procExeDeleted && isOlderThan(pl, proc, 10)))) {
// Check if we really should recalculate the M_LRS value for this process
uint64_t passedTimeInMs = pl->realtimeMs - lp->last_mlrs_calctime;
@@ -1514,7 +1558,8 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
lp->m_lrs = (proc->isUserlandThread && parent) ? ((const LinuxProcess*)parent)->m_lrs : 0;
}
- proc->mergedCommand.exeChanged |= prev ^ proc->usesDeletedLib;
+ if (prev != proc->usesDeletedLib)
+ proc->mergedCommand.lastUpdate = 0;
}
if ((ss->flags & PROCESS_FLAG_LINUX_SMAPS) && !Process_isKernelThread(proc)) {
@@ -1653,8 +1698,13 @@ errorReadingProcess:
#endif
if (preExisting) {
- ProcessList_remove(pl, proc);
+ /*
+ * The only real reason for coming here (apart from Linux violating the /proc API)
+ * would be the process going away with its /proc files disappearing (!HAVE_OPENAT).
+ * However, we want to keep in the process list for now for the "highlight dying" mode.
+ */
} else {
+ /* A really short-lived process that we don't have full info about */
Process_delete((Object*)proc);
}
}
@@ -1874,6 +1924,7 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) {
switch (buffer[0]) {
case 'c':
+ tryRead("c_min", &lpl->zfs.min);
tryRead("c_max", &lpl->zfs.max);
tryReadFlag("compressed_size", &lpl->zfs.compressed, lpl->zfs.isCompressed);
break;
@@ -1908,6 +1959,7 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) {
lpl->zfs.enabled = (lpl->zfs.size > 0 ? 1 : 0);
lpl->zfs.size /= 1024;
+ lpl->zfs.min /= 1024;
lpl->zfs.max /= 1024;
lpl->zfs.MFU /= 1024;
lpl->zfs.MRU /= 1024;
@@ -2101,16 +2153,11 @@ static void scanCPUFrequencyFromCPUinfo(LinuxProcessList* this) {
if (fgets(buffer, PROC_LINE_LENGTH, file) == NULL)
break;
- if (
- (sscanf(buffer, "processor : %d", &cpuid) == 1) ||
- (sscanf(buffer, "processor: %d", &cpuid) == 1)
- ) {
+ if (sscanf(buffer, "processor : %d", &cpuid) == 1) {
continue;
} else if (
(sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
- (sscanf(buffer, "cpu MHz: %lf", &frequency) == 1) ||
- (sscanf(buffer, "clock : %lfMHz", &frequency) == 1) ||
- (sscanf(buffer, "clock: %lfMHz", &frequency) == 1)
+ (sscanf(buffer, "clock : %lfMHz", &frequency) == 1)
) {
if (cpuid < 0 || (unsigned int)cpuid > (existingCPUs - 1)) {
continue;
diff --git a/linux/Platform.c b/linux/Platform.c
index 775f9ae..38b66e8 100644
--- a/linux/Platform.c
+++ b/linux/Platform.c
@@ -358,8 +358,13 @@ void Platform_setMemoryValues(Meter* this) {
this->values[4] = pl->availableMem;
if (lpl->zfs.enabled != 0 && !Running_containerized) {
- this->values[0] -= lpl->zfs.size;
- this->values[3] += lpl->zfs.size;
+ // ZFS does not shrink below the value of zfs_arc_min.
+ unsigned long long int shrinkableSize = 0;
+ if (lpl->zfs.size > lpl->zfs.min)
+ shrinkableSize = lpl->zfs.size - lpl->zfs.min;
+ this->values[0] -= shrinkableSize;
+ this->values[3] += shrinkableSize;
+ this->values[4] += shrinkableSize;
}
}
@@ -1035,7 +1040,7 @@ bool Platform_init(void) {
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 ")) {
+ if (String_startsWith(lineBuffer, "lxcfs /proc") || String_startsWith(lineBuffer, "overlay ")) {
Running_containerized = true;
break;
}
diff --git a/linux/Platform.h b/linux/Platform.h
index f2c314f..e6fa161 100644
--- a/linux/Platform.h
+++ b/linux/Platform.h
@@ -51,6 +51,8 @@ extern const MeterClass* const Platform_meterTypes[];
bool Platform_init(void);
void Platform_done(void);
+extern bool Running_containerized;
+
void Platform_setBindings(Htop_Action* keys);
int Platform_getUptime(void);
diff --git a/linux/SystemdMeter.c b/linux/SystemdMeter.c
index 567cfc7..53ae2d2 100644
--- a/linux/SystemdMeter.c
+++ b/linux/SystemdMeter.c
@@ -219,15 +219,18 @@ static void updateViaExec(void) {
exit(1);
dup2(fdnull, STDERR_FILENO);
close(fdnull);
- execlp("systemctl",
- "systemctl",
- "show",
- "--property=SystemState",
- "--property=NFailedUnits",
- "--property=NNames",
- "--property=NJobs",
- "--property=NInstalledJobs",
- NULL);
+ // Use of NULL in variadic functions must have a pointer cast.
+ // The NULL constant is not required by standard to have a pointer type.
+ execlp(
+ "systemctl",
+ "systemctl",
+ "show",
+ "--property=SystemState",
+ "--property=NFailedUnits",
+ "--property=NNames",
+ "--property=NJobs",
+ "--property=NInstalledJobs",
+ (char *)NULL);
exit(127);
}
close(fdpair[1]);

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