summaryrefslogtreecommitdiffstats
path: root/linux/LinuxProcessList.c
diff options
context:
space:
mode:
authorKirill Tkhai <tkhai@ya.ru>2023-03-31 00:10:40 +0300
committerBenBE <BenBE@geshi.org>2023-03-31 22:39:27 +0200
commitb618c379e13e7a2bb688cd54a64d199a267c0438 (patch)
tree8af3a91de85685367f60ded5cf6988009e1197fd /linux/LinuxProcessList.c
parentf66f04e6e0e6350ff8ea8242031ad43ce06a0a2b (diff)
This patch is for "Hide userland process threads mode is off" case.
Below is a small example of two threads program, whose main thread statistics is incorrect in htop. Despite main thread is permanently sleeping, its CPU load is 100% (must be 0%). CPU load of secondary thread is correct (100%). void *thread_func(void *data) { while(1) { } return NULL; } int main() { pthread_t thread; pthread_create(&thread, NULL, thread_func, NULL); pthread_join(thread, NULL); } The reason is in there is a difference in behavior of some files in /proc/pid and /proc/pid/task/pid directories. For example, /proc/pid/stat shows agregated user and sys times for all threads of a process. For the details please see do_task_stat() implementation and this function behavior difference in dependence of last argument: https://elixir.bootlin.com/linux/v6.2.8/source/fs/proc/array.c#L652 So, the problem occurs because of user and sys times of main thread are polluted by secondary thread statistics. This patch fixes the problem by reading correct stat from /proc/pid/task/pid/stat for main thread. Looking at other files from /proc/pid directory I found /proc/pid/io file with the same problem: https://elixir.bootlin.com/linux/v6.2.8/source/fs/proc/base.c#L3029 This problem is also fixed in this patch by reading correct data from /proc/pid/task/pid/io file for main thread. /proc/pid directory files are declared in tgid_base_stuff, while /proc/pid/task/tid directory files are declared in tid_base_stuff in kernel's fs/proc/base.c file: https://elixir.bootlin.com/linux/v6.2.8/source/fs/proc/base.c#L3238 I checked the difference between rest of declarations and it looks like there is no more problems of such type affecting htop.
Diffstat (limited to 'linux/LinuxProcessList.c')
-rw-r--r--linux/LinuxProcessList.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
index f8d56b70..b94c24a1 100644
--- a/linux/LinuxProcessList.c
+++ b/linux/LinuxProcessList.c
@@ -14,6 +14,7 @@ in the source distribution for its full text.
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
@@ -382,11 +383,15 @@ static inline ProcessState LinuxProcessList_getProcessState(char state) {
}
}
-static bool LinuxProcessList_readStatFile(Process* process, openat_arg_t procFd, char* command, size_t commLen) {
- LinuxProcess* lp = (LinuxProcess*) process;
+static bool LinuxProcessList_readStatFile(LinuxProcess* lp, openat_arg_t procFd, bool scanMainThread, char* command, size_t commLen) {
+ Process* process = &lp->super;
char buf[MAX_READ + 1];
- ssize_t r = xReadfileat(procFd, "stat", buf, sizeof(buf));
+ char path[22] = "stat";
+ if (scanMainThread) {
+ xSnprintf(path, sizeof(path), "task/%"PRIi32"/stat", (int32_t)process->pid);
+ }
+ ssize_t r = xReadfileat(procFd, path, buf, sizeof(buf));
if (r < 0)
return false;
@@ -607,9 +612,14 @@ static bool LinuxProcessList_updateUser(ProcessList* processList, Process* proce
return true;
}
-static void LinuxProcessList_readIoFile(LinuxProcess* process, openat_arg_t procFd, unsigned long long realtimeMs) {
+static void LinuxProcessList_readIoFile(LinuxProcess* process, openat_arg_t procFd, bool scanMainThread, unsigned long long realtimeMs) {
+ Process *proc = &process->super;
+ char path[20] = "io";
char buffer[1024];
- ssize_t r = xReadfileat(procFd, "io", buffer, sizeof(buffer));
+ if (scanMainThread) {
+ xSnprintf(path, sizeof(path), "task/%"PRIi32"/io", (int32_t)proc->pid);
+ }
+ ssize_t r = xReadfileat(procFd, path, buffer, sizeof(buffer));
if (r < 0) {
process->io_rate_read_bps = NAN;
process->io_rate_write_bps = NAN;
@@ -1531,8 +1541,9 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
continue;
}
+ bool scanMainThread = !hideUserlandThreads && !Process_isKernelThread(proc) && !parent;
if (ss->flags & PROCESS_FLAG_IO)
- LinuxProcessList_readIoFile(lp, procFd, pl->realtimeMs);
+ LinuxProcessList_readIoFile(lp, procFd, scanMainThread, pl->realtimeMs);
if (!LinuxProcessList_readStatmFile(lp, procFd))
goto errorReadingProcess;
@@ -1580,7 +1591,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
char statCommand[MAX_NAME + 1];
unsigned long long int lasttimes = (lp->utime + lp->stime);
unsigned long int tty_nr = proc->tty_nr;
- if (!LinuxProcessList_readStatFile(proc, procFd, statCommand, sizeof(statCommand)))
+ if (!LinuxProcessList_readStatFile(lp, procFd, scanMainThread, statCommand, sizeof(statCommand)))
goto errorReadingProcess;
if (lp->flags & PF_KTHREAD) {

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