Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions Process.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ void Process_makeCommandStr(Process *this) {

const int baseAttr = Process_isThread(this) ? CRT_colors[PROCESS_THREAD_BASENAME] : CRT_colors[PROCESS_BASENAME];
const int commAttr = Process_isThread(this) ? CRT_colors[PROCESS_THREAD_COMM] : CRT_colors[PROCESS_COMM];
const int delAttr = CRT_colors[FAILED_READ];
const int delExeAttr = CRT_colors[FAILED_READ];
const int delLibAttr = CRT_colors[PROCESS_TAG];

/* Establish some shortcuts to data we need */
const char *cmdline = this->cmdline;
Expand Down Expand Up @@ -529,14 +530,18 @@ void Process_makeCommandStr(Process *this) {
WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM);
WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME);
if (this->procExeDeleted)
WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, delAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED);
WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, delExeAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED);
else if (this->usesDeletedLib)
WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, delLibAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED);
str = stpcpy(str, procExe);
} else {
if (haveCommInExe)
WRITE_HIGHLIGHT(0, exeBasenameLen, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM);
WRITE_HIGHLIGHT(0, exeBasenameLen, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME);
if (this->procExeDeleted)
WRITE_HIGHLIGHT(0, exeBasenameLen, delAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED);
WRITE_HIGHLIGHT(0, exeBasenameLen, delExeAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED);
else if (this->usesDeletedLib)
WRITE_HIGHLIGHT(0, exeBasenameLen, delLibAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED);
str = stpcpy(str, procExe + exeBasenameOffset);
}

Expand Down
3 changes: 3 additions & 0 deletions Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ typedef struct Process_ {
/* Tells if the executable has been replaced in the filesystem since start */
bool procExeDeleted;

/* Tells if the process uses replaced shared libraries since start */
bool usesDeletedLib;

/* CPU number last executed on */
int processor;

Expand Down
102 changes: 66 additions & 36 deletions linux/LinuxProcessList.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,18 +517,24 @@ static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED ht_key_t key, void*
*d += v->size;
}

static uint64_t LinuxProcessList_calcLibSize(openat_arg_t procFd) {
static void LinuxProcessList_readMaps(LinuxProcess* process, openat_arg_t procFd, bool calcSize, bool checkDeletedLib) {
Process* proc = (Process*)process;

proc->usesDeletedLib = false;

FILE* mapsfile = fopenat(procFd, "maps", "r");
if (!mapsfile)
return 0;
return;

Hashtable* ht = Hashtable_new(64, true);
Hashtable* ht = NULL;
if (calcSize)
ht = Hashtable_new(64, true);

char buffer[1024];
while (fgets(buffer, sizeof(buffer), mapsfile)) {
uint64_t map_start;
uint64_t map_end;
char map_perm[5];
bool map_execute;
unsigned int map_devmaj;
unsigned int map_devmin;
uint64_t map_inode;
Expand All @@ -548,8 +554,7 @@ static uint64_t LinuxProcessList_calcLibSize(openat_arg_t procFd) {
if (' ' != *readptr++)
continue;

memcpy(map_perm, readptr, 4);
map_perm[4] = '\0';
map_execute = (readptr[2] == 'x');
readptr += 4;
if (' ' != *readptr++)
continue;
Expand All @@ -575,61 +580,65 @@ static uint64_t LinuxProcessList_calcLibSize(openat_arg_t procFd) {
if (!map_inode)
continue;

LibraryData* libdata = Hashtable_get(ht, map_inode);
if (!libdata) {
libdata = xCalloc(1, sizeof(LibraryData));
Hashtable_put(ht, map_inode, libdata);
if (calcSize) {
LibraryData* libdata = Hashtable_get(ht, map_inode);
if (!libdata) {
libdata = xCalloc(1, sizeof(LibraryData));
Hashtable_put(ht, map_inode, libdata);
}

libdata->size += map_end - map_start;
libdata->exec |= map_execute;
}

libdata->size += map_end - map_start;
libdata->exec |= 'x' == map_perm[2];
if (checkDeletedLib && map_execute && !proc->usesDeletedLib) {
while (*readptr == ' ')
readptr++;

if (*readptr != '/')
continue;

if (String_startsWith(readptr, "/memfd:"))
continue;

if (strstr(readptr, " (deleted)\n")) {
proc->usesDeletedLib = true;
if (!calcSize)
break;
}
}
}

fclose(mapsfile);

uint64_t total_size = 0;
Hashtable_foreach(ht, LinuxProcessList_calcLibSize_helper, &total_size);
if (calcSize) {
uint64_t total_size = 0;
Hashtable_foreach(ht, LinuxProcessList_calcLibSize_helper, &total_size);

Hashtable_delete(ht);
Hashtable_delete(ht);

return total_size / pageSize;
process->m_lrs = total_size / pageSize;
}
}

static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t procFd, bool performLookup, unsigned long long realtimeMs) {
static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t procFd) {
FILE* statmfile = fopenat(procFd, "statm", "r");
if (!statmfile)
return false;

long tmp_m_lrs = 0;
int r = fscanf(statmfile, "%ld %ld %ld %ld %ld %ld %ld",
&process->super.m_virt,
&process->super.m_resident,
&process->m_share,
&process->m_trs,
&tmp_m_lrs,
&process->m_lrs,
&process->m_drs,
&process->m_dt);
fclose(statmfile);

if (r == 7) {
process->super.m_virt *= pageSizeKB;
process->super.m_resident *= pageSizeKB;

if (tmp_m_lrs) {
process->m_lrs = tmp_m_lrs;
} else if (performLookup) {
// Check if we really should recalculate the M_LRS value for this process
uint64_t passedTimeInMs = realtimeMs - process->last_mlrs_calctime;

uint64_t recheck = ((uint64_t)rand()) % 2048;

if(passedTimeInMs > 2000 || passedTimeInMs > recheck) {
process->last_mlrs_calctime = realtimeMs;
process->m_lrs = LinuxProcessList_calcLibSize(procFd);
}
} else {
// Keep previous value
}
}

return r == 7;
Expand Down Expand Up @@ -1340,9 +1349,30 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
if (settings->flags & PROCESS_FLAG_IO)
LinuxProcessList_readIoFile(lp, procFd, pl->realtimeMs);

if (!LinuxProcessList_readStatmFile(lp, procFd, !!(settings->flags & PROCESS_FLAG_LINUX_LRS_FIX), pl->realtimeMs))
if (!LinuxProcessList_readStatmFile(lp, procFd))
goto errorReadingProcess;

{
bool prev = proc->usesDeletedLib;

if ((lp->m_lrs == 0 && (settings->flags & PROCESS_FLAG_LINUX_LRS_FIX)) || settings->highlightDeletedExe) {
// Check if we really should recalculate the M_LRS value for this process
uint64_t passedTimeInMs = pl->realtimeMs - lp->last_mlrs_calctime;

uint64_t recheck = ((uint64_t)rand()) % 2048;

if (passedTimeInMs > 2000 || passedTimeInMs > recheck) {
lp->last_mlrs_calctime = pl->realtimeMs;
LinuxProcessList_readMaps(lp, procFd, settings->flags & PROCESS_FLAG_LINUX_LRS_FIX, settings->highlightDeletedExe);
}
} else {
/* reset if setting got disabled */
proc->usesDeletedLib = false;
}

proc->mergedCommand.exeChanged |= prev ^ proc->usesDeletedLib;
}

if ((settings->flags & PROCESS_FLAG_LINUX_SMAPS) && !Process_isKernelThread(proc)) {
if (!parent) {
// Read smaps file of each process only every second pass to improve performance
Expand Down