From bd1d719a61bbca16f7dd373dcc1e234f3c8ea09b Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Sat, 18 Aug 2018 21:29:03 -0700 Subject: [PATCH] Linux: add process->starttime and use it for STARTTIME column (#700) this way a remount of /proc will not reset starttimes and we can also see startup times for processes started before the mount of /proc also record btime (boot time in seconds since epoch) as Linux semi-global --- linux/LinuxProcess.c | 17 +++++++++++++++++ linux/LinuxProcess.h | 3 +++ linux/LinuxProcessList.c | 35 +++++++++++++++++++---------------- linux/LinuxProcessList.h | 4 +++- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index 2caa3237..5f697078 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -15,6 +15,7 @@ in the source distribution for its full text. #include #include #include +#include /*{ @@ -106,6 +107,7 @@ typedef struct LinuxProcess_ { long m_drs; long m_lrs; long m_dt; + unsigned long long starttime; #ifdef HAVE_TASKSTATS unsigned long long io_rchar; unsigned long long io_wchar; @@ -152,6 +154,8 @@ typedef struct LinuxProcess_ { }*/ +long long btime; /* semi-global */ + ProcessFieldData Process_fields[] = { [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, [PID] = { .name = "PID", .title = " PID ", .description = "Process/thread ID", .flags = 0, }, @@ -344,6 +348,13 @@ void LinuxProcess_writeField(Process* this, RichString* str, ProcessField field) case STIME: Process_printTime(str, lp->stime); return; case CUTIME: Process_printTime(str, lp->cutime); return; case CSTIME: Process_printTime(str, lp->cstime); return; + case STARTTIME: { + struct tm date; + time_t starttimewall = btime + (lp->starttime / sysconf(_SC_CLK_TCK)); + (void) localtime_r(&starttimewall, &date); + strftime(buffer, n, ((starttimewall > time(NULL) - 86400) ? "%R " : "%b%d "), &date); + break; + } #ifdef HAVE_TASKSTATS case RCHAR: Process_colorNumber(str, lp->io_rchar, coloring); return; case WCHAR: Process_colorNumber(str, lp->io_wchar, coloring); return; @@ -428,6 +439,12 @@ long LinuxProcess_compare(const void* v1, const void* v2) { case CUTIME: diff = p2->cutime - p1->cutime; goto test_diff; case STIME: diff = p2->stime - p1->stime; goto test_diff; case CSTIME: diff = p2->cstime - p1->cstime; goto test_diff; + case STARTTIME: { + if (p1->starttime == p2->starttime) + return (p1->super.pid - p2->super.pid); + else + return (p1->starttime - p2->starttime); + } #ifdef HAVE_TASKSTATS case RCHAR: diff = p2->io_rchar - p1->io_rchar; goto test_diff; case WCHAR: diff = p2->io_wchar - p1->io_wchar; goto test_diff; diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index d75fe89d..6ce3037d 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -98,6 +98,7 @@ typedef struct LinuxProcess_ { long m_drs; long m_lrs; long m_dt; + unsigned long long starttime; #ifdef HAVE_TASKSTATS unsigned long long io_rchar; unsigned long long io_wchar; @@ -143,6 +144,8 @@ typedef struct LinuxProcess_ { #endif +long long btime; /* semi-global */ + extern ProcessFieldData Process_fields[]; extern ProcessPidColumn Process_pidColumns[]; diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 27ead28a..601b0e46 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -47,6 +47,8 @@ in the source distribution for its full text. #include "ProcessList.h" +extern long long btime; + typedef struct CPUData_ { unsigned long long int totalTime; unsigned long long int userTime; @@ -111,7 +113,7 @@ typedef struct LinuxProcessList_ { #endif #ifndef PROC_LINE_LENGTH -#define PROC_LINE_LENGTH 512 +#define PROC_LINE_LENGTH 4096 #endif }*/ @@ -230,8 +232,8 @@ static void LinuxProcessList_initNetlinkSocket(LinuxProcessList* this) { ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { LinuxProcessList* this = xCalloc(1, sizeof(LinuxProcessList)); ProcessList* pl = &(this->super); + ProcessList_init(pl, Class(LinuxProcess), usersTable, pidWhiteList, userId); - LinuxProcessList_initTtyDrivers(this); #ifdef HAVE_DELAYACCT @@ -243,13 +245,19 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui if (file == NULL) { CRT_fatalError("Cannot open " PROCSTATFILE); } - char buffer[PROC_LINE_LENGTH + 1]; int cpus = -1; do { - cpus++; - char * s = fgets(buffer, PROC_LINE_LENGTH, file); - (void) s; - } while (String_startsWith(buffer, "cpu")); + char buffer[PROC_LINE_LENGTH + 1]; + if (fgets(buffer, PROC_LINE_LENGTH + 1, file) == NULL) { + CRT_fatalError("No btime in " PROCSTATFILE); + } else if (String_startsWith(buffer, "cpu")) { + cpus++; + } else if (String_startsWith(buffer, "btime ")) { + sscanf(buffer, "btime %lld\n", &btime); + break; + } + } while(true); + fclose(file); pl->cpuCount = MAX(cpus - 1, 1); @@ -259,7 +267,6 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui this->cpus[i].totalTime = 1; this->cpus[i].totalPeriod = 1; } - return pl; } @@ -355,7 +362,10 @@ static bool LinuxProcessList_readStatFile(Process *process, const char* dirname, location += 1; process->nlwp = strtol(location, &location, 10); location += 1; - for (int i=0; i<17; i++) location = strchr(location, ' ')+1; + location = strchr(location, ' ')+1; + lp->starttime = strtoll(location, &location, 10); + location += 1; + for (int i=0; i<15; i++) location = strchr(location, ' ')+1; process->exit_signal = strtol(location, &location, 10); location += 1; assert(location != NULL); @@ -377,13 +387,6 @@ static bool LinuxProcessList_statProcessDir(Process* process, const char* dirnam if (statok == -1) return false; process->st_uid = sstat.st_uid; - - struct tm date; - time_t ctime = sstat.st_ctime; - process->starttime_ctime = ctime; - (void) localtime_r((time_t*) &ctime, &date); - strftime(process->starttime_show, 7, ((ctime > curTime - 86400) ? "%R " : "%b%d "), &date); - return true; } diff --git a/linux/LinuxProcessList.h b/linux/LinuxProcessList.h index 0851a102..f30b487d 100644 --- a/linux/LinuxProcessList.h +++ b/linux/LinuxProcessList.h @@ -20,6 +20,8 @@ in the source distribution for its full text. #include "ProcessList.h" +extern long long btime; + typedef struct CPUData_ { unsigned long long int totalTime; unsigned long long int userTime; @@ -84,7 +86,7 @@ typedef struct LinuxProcessList_ { #endif #ifndef PROC_LINE_LENGTH -#define PROC_LINE_LENGTH 512 +#define PROC_LINE_LENGTH 4096 #endif