From 4e2c2d79271bfecffcbe3166dde2d2fa04bdc746 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:29:20 -0300 Subject: [PATCH 01/11] Fix resource leak. --- Settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Settings.c b/Settings.c index 3198cb6b..d95f8d02 100644 --- a/Settings.c +++ b/Settings.c @@ -265,7 +265,6 @@ Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) { // Transition to new location and delete old configuration file if (Settings_write(this)) unlink(legacyDotfile); - free(legacyDotfile); } } else { this->changed = true; @@ -280,5 +279,6 @@ Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) { pl->highlightThreads = false; } } + free(legacyDotfile); return this; } From e0209da88faf3b390d71ff174065abd407abfdfd Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:40:47 -0300 Subject: [PATCH 02/11] Support pagefaults stats. Closes #45. --- ChangeLog | 1 + Process.c | 8 ++++++-- Process.h | 2 +- ProcessList.c | 12 ++++++++---- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4e1c3149..1aafc65d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ What's new in version 1.0.3 of IO data depending on selected fields. * Better consistency in coloring. * Increase limit of buffer when tracing a deep nested process tree. +* Display pagefault stats. * BUGFIX: Fix crash when adding meters and toggling detailed CPU time. (thanks to Dawid Gajownik) * Add column to track the OOM-killer score of processes diff --git a/Process.c b/Process.c index efaf3f68..4efd8545 100644 --- a/Process.c +++ b/Process.c @@ -168,11 +168,11 @@ typedef struct Process_ { int basenameOffset; bool updated; - #ifdef DEBUG unsigned long int minflt; unsigned long int cminflt; unsigned long int majflt; unsigned long int cmajflt; + #ifdef DEBUG long int itrealvalue; unsigned long int vsize; long int rss; @@ -254,7 +254,7 @@ const int Process_fieldFlags[] = { const char *Process_fieldTitles[] = { "", " PID ", "Command ", "S ", " PPID ", " PGRP ", " SESN ", - " TTY ", " TPGID ", "- ", "- ", "- ", "- ", "- ", + " TTY ", " TPGID ", "- ", " MINFLT ", " CMINFLT ", " MAJFLT ", " CMAJFLT ", " UTIME+ ", " STIME+ ", " CUTIME+ ", " CSTIME+ ", "PRI ", " NI ", "- ", "START ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", "- ", @@ -483,6 +483,10 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel case TTY_NR: snprintf(buffer, n, "%5u ", this->tty_nr); break; case TGID: snprintf(buffer, n, Process_pidFormat, this->tgid); break; case TPGID: snprintf(buffer, n, Process_tpgidFormat, this->tpgid); break; + case MINFLT: Process_colorNumber(str, this->minflt, coloring); return; + case CMINFLT: Process_colorNumber(str, this->cminflt, coloring); return; + case MAJFLT: Process_colorNumber(str, this->majflt, coloring); return; + case CMAJFLT: Process_colorNumber(str, this->cmajflt, coloring); return; case PROCESSOR: snprintf(buffer, n, "%3d ", ProcessList_cpuId(this->pl, this->processor)); break; case NLWP: snprintf(buffer, n, "%4ld ", this->nlwp); break; case COMM: { diff --git a/Process.h b/Process.h index 774b50ac..19083fde 100644 --- a/Process.h +++ b/Process.h @@ -147,11 +147,11 @@ typedef struct Process_ { int basenameOffset; bool updated; - #ifdef DEBUG unsigned long int minflt; unsigned long int cminflt; unsigned long int majflt; unsigned long int cmajflt; + #ifdef DEBUG long int itrealvalue; unsigned long int vsize; long int rss; diff --git a/ProcessList.c b/ProcessList.c index 908d88fc..d3621155 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -444,10 +444,14 @@ static bool ProcessList_readStatFile(Process *process, const char* dirname, cons location += 1; process->flags = strtoul(location, &location, 10); location += 1; - location = strchr(location, ' ')+1; - location = strchr(location, ' ')+1; - location = strchr(location, ' ')+1; - location = strchr(location, ' ')+1; + process->minflt = strtoull(location, &location, 10); + location += 1; + process->cminflt = strtoull(location, &location, 10); + location += 1; + process->majflt = strtoull(location, &location, 10); + location += 1; + process->cmajflt = strtoull(location, &location, 10); + location += 1; process->utime = strtoull(location, &location, 10); location += 1; process->stime = strtoull(location, &location, 10); From 659251c501b0634ff49c0438970532b188633e95 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:43:27 -0300 Subject: [PATCH 03/11] Fix array limit. --- BatteryMeter.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/BatteryMeter.c b/BatteryMeter.c index aed5f232..76ccbdaf 100644 --- a/BatteryMeter.c +++ b/BatteryMeter.c @@ -56,13 +56,14 @@ static unsigned long int parseBatInfo(const char *fileName, const unsigned short if (!batteryDir) return 0; - char* batteries[64]; + #define MAX_BATTERIES 64 + char* batteries[MAX_BATTERIES]; unsigned int nBatteries = 0; - memset(batteries, sizeof batteries, sizeof (char*)); + memset(batteries, MAX_BATTERIES, sizeof (char*)); struct dirent result; struct dirent* dirEntry; - while (nBatteries < sizeof batteries) { + while (nBatteries < MAX_BATTERIES) { readdir_r(batteryDir, &result, &dirEntry); if (!dirEntry) break; From 814ce89b45c8e10a5bb2c8ca458ebcc9c56cdcae Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:44:41 -0300 Subject: [PATCH 04/11] Oops, fix use of memset. --- BatteryMeter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BatteryMeter.c b/BatteryMeter.c index 76ccbdaf..4f591264 100644 --- a/BatteryMeter.c +++ b/BatteryMeter.c @@ -59,7 +59,7 @@ static unsigned long int parseBatInfo(const char *fileName, const unsigned short #define MAX_BATTERIES 64 char* batteries[MAX_BATTERIES]; unsigned int nBatteries = 0; - memset(batteries, MAX_BATTERIES, sizeof (char*)); + memset(batteries, 0, MAX_BATTERIES * sizeof(char*)); struct dirent result; struct dirent* dirEntry; From 50b701258d0aacca2b857b285e88cd9f03fa4b96 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:46:10 -0300 Subject: [PATCH 05/11] Make static analyzers happy. --- BatteryMeter.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/BatteryMeter.c b/BatteryMeter.c index 4f591264..fcdfb8ad 100644 --- a/BatteryMeter.c +++ b/BatteryMeter.c @@ -64,8 +64,8 @@ static unsigned long int parseBatInfo(const char *fileName, const unsigned short struct dirent result; struct dirent* dirEntry; while (nBatteries < MAX_BATTERIES) { - readdir_r(batteryDir, &result, &dirEntry); - if (!dirEntry) + int err = readdir_r(batteryDir, &result, &dirEntry); + if (err || !dirEntry) break; char* entryName = dirEntry->d_name; if (strncmp(entryName, "BAT", 3)) @@ -117,8 +117,8 @@ static ACPresence procAcpiCheck() { struct dirent result; struct dirent* dirEntry; for (;;) { - readdir_r((DIR *) power_supplyDir, &result, &dirEntry); - if (!dirEntry) + int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry); + if (err || !dirEntry) break; char* entryName = (char *) dirEntry->d_name; @@ -170,8 +170,8 @@ static ACPresence sysCheck() { struct dirent result; struct dirent* dirEntry; for (;;) { - readdir_r((DIR *) power_supplyDir, &result, &dirEntry); - if (!dirEntry) + int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry); + if (err || !dirEntry) break; char* entryName = (char *) dirEntry->d_name; @@ -233,8 +233,8 @@ static double getSysBatData() { struct dirent result; struct dirent* dirEntry; for (;;) { - readdir_r((DIR *) power_supplyDir, &result, &dirEntry); - if (!dirEntry) + int err = readdir_r((DIR *) power_supplyDir, &result, &dirEntry); + if (err || !dirEntry) break; char* entryName = (char *) dirEntry->d_name; From 616ee966d7eea1cdf24889c7a4e9a9fab3136202 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:48:34 -0300 Subject: [PATCH 06/11] Fix out-of-bounds write. --- IncSet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IncSet.c b/IncSet.c index f38ba6dc..40aa9233 100644 --- a/IncSet.c +++ b/IncSet.c @@ -29,7 +29,7 @@ typedef enum { #define IncSet_filter(inc_) (inc_->filtering ? inc_->modes[INC_FILTER].buffer : NULL) typedef struct IncMode_ { - char buffer[INCMODE_MAX]; + char buffer[INCMODE_MAX+1]; int index; FunctionBar* bar; bool isFilter; From d5b3b6d6924aa68941337aabc331cdb4f7f2365f Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:50:03 -0300 Subject: [PATCH 07/11] Add corresponding .h file. --- IncSet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IncSet.h b/IncSet.h index fe425330..c528f18c 100644 --- a/IncSet.h +++ b/IncSet.h @@ -24,7 +24,7 @@ typedef enum { #define IncSet_filter(inc_) (inc_->filtering ? inc_->modes[INC_FILTER].buffer : NULL) typedef struct IncMode_ { - char buffer[INCMODE_MAX]; + char buffer[INCMODE_MAX+1]; int index; FunctionBar* bar; bool isFilter; From 27da00f339649078fd1c8f5f957095d47e47513b Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:50:33 -0300 Subject: [PATCH 08/11] Improve function prototype, helping analysis. --- Settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Settings.c b/Settings.c index d95f8d02..cd9e6c13 100644 --- a/Settings.c +++ b/Settings.c @@ -61,7 +61,7 @@ static void Settings_readMeterModes(Settings* this, char* line, HeaderSide side) String_freeArray(ids); } -static bool Settings_read(Settings* this, char* fileName, int cpuCount) { +static bool Settings_read(Settings* this, const char* fileName, int cpuCount) { FILE* fd = fopen(fileName, "r"); if (!fd) return false; From 9eec37c432035b5a484731cbdaed0e95c7228939 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:54:06 -0300 Subject: [PATCH 09/11] More sanity checks. --- BatteryMeter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/BatteryMeter.c b/BatteryMeter.c index fcdfb8ad..f2dfa6ab 100644 --- a/BatteryMeter.c +++ b/BatteryMeter.c @@ -85,9 +85,10 @@ static unsigned long int parseBatInfo(const char *fileName, const unsigned short break; } - char line[50]; + char line[50] = ""; for (unsigned short int i = 0; i < lineNum; i++) { - fgets(line, sizeof line, file); + char* ok = fgets(line, sizeof line, file); + if (!ok) break; } fclose(file); From 43c3e4d3d9df4bcdf52cb5c83da6d51da688d093 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 24 Apr 2014 19:54:35 -0300 Subject: [PATCH 10/11] Preparing release 1.0.3. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ef57ebdc..2b934e8a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.65) -AC_INIT([htop],[1.0.2],[hisham@gobolinux.org]) +AC_INIT([htop],[1.0.3],[hisham@gobolinux.org]) # The following two lines are required by hwloc scripts AC_USE_SYSTEM_EXTENSIONS From 88c3758051e4f9b93cc4912a7f75078901869f0e Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Fri, 25 Apr 2014 16:05:25 -0300 Subject: [PATCH 11/11] =?UTF-8?q?Now,=20when=20you=20disable=20a=20filter?= =?UTF-8?q?=20(F4=20=E2=86=92=20Esc),=20it=20will=20go=20back=20to=20unfil?= =?UTF-8?q?tered=20mode=20but=20the=20current=20process=20will=20remain=20?= =?UTF-8?q?selected=20(so=20you=20can=20filter,=20choose=20and=20then=20go?= =?UTF-8?q?=20back=20to=20unfiltered=20mode=20to=20see=20the=20children=20?= =?UTF-8?q?of=20that=20process).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspired by feedback at http://www.reddit.com/r/linux/comments/23wpc7/announcing_htop_103_with_new_features_bugfixes/ch1paos --- htop.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htop.c b/htop.c index b3438097..6b56727a 100644 --- a/htop.c +++ b/htop.c @@ -623,6 +623,9 @@ int main(int argc, char** argv) { if (inc->active) { doRefresh = IncSet_handleKey(inc, ch, panel, getMainPanelValue, NULL); + if (!inc->active) { + follow = true; + } continue; }