From 07496eafb0166aafd9c33a6a95e16bcbc64c34d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rin=20Cat=20=28=E9=88=B4=E7=8C=AB=29?= Date: Mon, 8 Nov 2021 09:42:12 -0500 Subject: Linux: use proper way to detect kernel threads Use PF_KTHREAD flag in /proc/[pid]/stat to detect kernel threads. This fixed an issue when a process's cmdline is empty, htop think it is a kernel thread. --- linux/LinuxProcess.h | 3 +++ linux/LinuxProcessList.c | 35 ++++++++++++++++++++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index 577b903d..b4e1a8bf 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -48,6 +48,9 @@ typedef struct LinuxProcess_ { long m_drs; long m_lrs; + /* Process flags */ + unsigned long int flags; + /* Data read (in bytes) */ unsigned long long io_rchar; diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 377dd7e6..a2d3d2be 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -62,6 +62,10 @@ in the source distribution for its full text. #define O_PATH 010000000 // declare for ancient glibc versions #endif +/* Not exposed yet. Defined at include/linux/sched.h */ +#ifndef PF_KTHREAD +#define PF_KTHREAD 0x00200000 +#endif static long long btime = -1; @@ -374,8 +378,9 @@ static bool LinuxProcessList_readStatFile(Process* process, openat_arg_t procFd, process->tpgid = strtol(location, &location, 10); location += 1; - /* Skip (9) flags - %u */ - location = strchr(location, ' ') + 1; + /* (9) flags - %u */ + lp->flags = strtoul(location, &location, 10); + location += 1; /* (10) minflt - %lu */ process->minflt = strtoull(location, &location, 10); @@ -1110,17 +1115,9 @@ delayacct_failure: static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t procFd) { char command[4096 + 1]; // max cmdline length on Linux ssize_t amtRead = xReadfileat(procFd, "cmdline", command, sizeof(command)); - if (amtRead < 0) + if (amtRead <= 0) return false; - if (amtRead == 0) { - if (process->state != ZOMBIE) { - process->isKernelThread = true; - } - Process_updateCmdline(process, NULL, 0, 0); - return true; - } - int tokenEnd = 0; int tokenStart = 0; int lastChar = 0; @@ -1488,6 +1485,10 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ if (! LinuxProcessList_readStatFile(proc, procFd, statCommand, sizeof(statCommand))) goto errorReadingProcess; + if (lp->flags & PF_KTHREAD) { + proc->isKernelThread = true; + } + if (tty_nr != proc->tty_nr && this->ttyDrivers) { free(proc->tty_name); proc->tty_name = LinuxProcessList_updateTtyDevice(this->ttyDrivers, proc->tty_nr); @@ -1519,8 +1520,10 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ } #endif - if (! LinuxProcessList_readCmdlineFile(proc, procFd)) { - goto errorReadingProcess; + if (proc->isKernelThread) { + Process_updateCmdline(proc, NULL, 0, 0); + } else if (!LinuxProcessList_readCmdlineFile(proc, procFd)) { + Process_updateCmdline(proc, statCommand, 0, strlen(statCommand)); } Process_fillStarttimeBuffer(proc); @@ -1528,8 +1531,10 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ ProcessList_add(pl, proc); } else { if (settings->updateProcessNames && proc->state != ZOMBIE) { - if (! LinuxProcessList_readCmdlineFile(proc, procFd)) { - goto errorReadingProcess; + if (proc->isKernelThread) { + Process_updateCmdline(proc, NULL, 0, 0); + } else if (!LinuxProcessList_readCmdlineFile(proc, procFd)) { + Process_updateCmdline(proc, statCommand, 0, strlen(statCommand)); } } } -- cgit v1.2.3