* make debug target

* Support for generating a /proc trace for debugging purposes.
This commit is contained in:
Hisham Muhammad 2006-03-24 03:39:04 +00:00
parent a3a8a3b24b
commit 86d6313560
3 changed files with 151 additions and 39 deletions

View File

@ -27,3 +27,5 @@ ColorsListBox.c ColorsListBox.h TraceScreen.c TraceScreen.h \
AvailableColumnsListBox.c AvailableColumnsListBox.h ColumnsListBox.c \ AvailableColumnsListBox.c AvailableColumnsListBox.h ColumnsListBox.c \
ColumnsListBox.h ColumnsListBox.h
debug:
$(MAKE) all CFLAGS="-g -DDEBUG"

View File

@ -25,6 +25,7 @@ in the source distribution for its full text.
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <stdarg.h>
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
@ -43,7 +44,11 @@ in the source distribution for its full text.
#endif #endif
#ifndef MAX_NAME #ifndef MAX_NAME
#define MAX_NAME 128; #define MAX_NAME 128
#endif
#ifndef MAX_READ
#define MAX_READ 8192
#endif #endif
}*/ }*/
@ -92,6 +97,9 @@ typedef struct ProcessList_ {
bool treeView; bool treeView;
bool highlightBaseName; bool highlightBaseName;
bool highlightMegabytes; bool highlightMegabytes;
#ifdef DEBUG
FILE* traceFile;
#endif
} ProcessList; } ProcessList;
}*/ }*/
@ -99,6 +107,64 @@ typedef struct ProcessList_ {
/* private property */ /* private property */
ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, LAST_PROCESSFIELD, 0 }; ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, LAST_PROCESSFIELD, 0 };
#ifdef DEBUG
/* private property */
typedef int(*vxscanf)(void*, const char*, va_list);
#define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ )
#define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
/* private */
FILE* ProcessList_fopen(ProcessList* this, const char* path, const char* mode) {
fprintf(this->traceFile, "[%s]\n", path);
return fopen(path, mode);
}
/* private */
static inline int ProcessList_xread(ProcessList* this, vxscanf fn, void* buffer, char* format, ...) {
va_list ap;
va_start(ap, format);
int num = fn(buffer, format, ap);
va_end(format);
va_start(ap, format);
while (*format) {
char ch = *format;
char* c; int* d; long int* ld; unsigned long int* lu; char** s;
if (ch != '%') {
fprintf(this->traceFile, "%c", ch);
format++;
continue;
}
format++;
switch(*format) {
case 'c': c = va_arg(ap, char*); fprintf(this->traceFile, "%c", *c); break;
case 'd': d = va_arg(ap, int*); fprintf(this->traceFile, "%d", *d); break;
case 's': s = va_arg(ap, char**); fprintf(this->traceFile, "%s", *s); break;
case 'l':
format++;
switch (*format) {
case 'd': ld = va_arg(ap, long int*); fprintf(this->traceFile, "%ld", *ld); break;
case 'u': lu = va_arg(ap, unsigned long int*); fprintf(this->traceFile, "%lu", *lu); break;
}
}
format++;
}
fprintf(this->traceFile, "\n");
va_end(format);
return num;
}
#else
#ifndef ProcessList_read
#define ProcessList_fopen(this, path, mode) fopen(path, mode)
#define ProcessList_read(this, buffer, format, ...) sscanf(buffer, format, ## __VA_ARGS__ )
#define ProcessList_fread(this, file, format, ...) fscanf(file, format, ## __VA_ARGS__ )
#endif
#endif
ProcessList* ProcessList_new(UsersTable* usersTable) { ProcessList* ProcessList_new(UsersTable* usersTable) {
ProcessList* this; ProcessList* this;
this = malloc(sizeof(ProcessList)); this = malloc(sizeof(ProcessList));
@ -109,6 +175,10 @@ ProcessList* ProcessList_new(UsersTable* usersTable) {
/* tree-view auxiliary buffers */ /* tree-view auxiliary buffers */
this->processes2 = TypedVector_new(PROCESS_CLASS, true, DEFAULT_SIZE); this->processes2 = TypedVector_new(PROCESS_CLASS, true, DEFAULT_SIZE);
#ifdef DEBUG
this->traceFile = fopen("/tmp/htop-proc-trace", "w");
#endif
FILE* status = fopen(PROCSTATFILE, "r"); FILE* status = fopen(PROCSTATFILE, "r");
assert(status != NULL); assert(status != NULL);
@ -171,6 +241,10 @@ void ProcessList_delete(ProcessList* this) {
free(this->nicePeriod); free(this->nicePeriod);
free(this->idlePeriod); free(this->idlePeriod);
#ifdef DEBUG
fclose(this->traceFile);
#endif
free(this->fields); free(this->fields);
free(this); free(this);
} }
@ -231,7 +305,7 @@ void ProcessList_buildTree(ProcessList* this, int pid, int level, int indent, in
if (process->ppid == pid) { if (process->ppid == pid) {
Process* process = (Process*) (TypedVector_take(this->processes, i)); Process* process = (Process*) (TypedVector_take(this->processes, i));
TypedVector_add(children, process); TypedVector_add(children, process);
i--; i--;
} }
} }
int size = TypedVector_size(children); int size = TypedVector_size(children);
@ -273,8 +347,7 @@ void ProcessList_sort(ProcessList* this) {
} }
/* private */ /* private */
int ProcessList_readStatFile(Process *proc, FILE *f, char *command) { int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, char *command) {
#define MAX_READ 8192
static char buf[MAX_READ]; static char buf[MAX_READ];
long int zero; long int zero;
@ -294,7 +367,7 @@ int ProcessList_readStatFile(Process *proc, FILE *f, char *command) {
command[commsize] = '\0'; command[commsize] = '\0';
location = end + 2; location = end + 2;
int num = sscanf(location, int num = ProcessList_read(this, location,
"%c %d %d %d %d %d %lu %lu %lu %lu " "%c %d %d %d %d %d %lu %lu %lu %lu "
"%lu %lu %lu %ld %ld %ld %ld %ld %ld " "%lu %lu %lu %ld %ld %ld %ld %ld %ld "
"%lu %lu %ld %lu %lu %lu %lu %lu " "%lu %lu %ld %lu %lu %lu %lu %lu "
@ -318,11 +391,11 @@ int ProcessList_readStatFile(Process *proc, FILE *f, char *command) {
return 1; return 1;
} }
bool ProcessList_readStatusFile(Process* proc, char* dirname, char* name) { bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name) {
char statusfilename[MAX_NAME+1]; char statusfilename[MAX_NAME+1];
statusfilename[MAX_NAME] = '\0'; statusfilename[MAX_NAME] = '\0';
snprintf(statusfilename, MAX_NAME, "%s/%s/status", dirname, name); snprintf(statusfilename, MAX_NAME, "%s/%s/status", dirname, name);
FILE* status = fopen(statusfilename, "r"); FILE* status = ProcessList_fopen(this, statusfilename, "r");
bool success = false; bool success = false;
if (status) { if (status) {
char buffer[1024]; char buffer[1024];
@ -334,7 +407,7 @@ bool ProcessList_readStatusFile(Process* proc, char* dirname, char* name) {
if (String_startsWith(buffer, "Uid:")) { if (String_startsWith(buffer, "Uid:")) {
int uid1, uid2, uid3, uid4; int uid1, uid2, uid3, uid4;
// TODO: handle other uid's. // TODO: handle other uid's.
int ok = sscanf(buffer, "Uid:\t%d\t%d\t%d\t%d\n", &uid1, &uid2, &uid3, &uid4); int ok = ProcessList_read(this, buffer, "Uid:\t%d\t%d\t%d\t%d", &uid1, &uid2, &uid3, &uid4);
if (ok >= 1) { if (ok >= 1) {
proc->st_uid = uid1; proc->st_uid = uid1;
success = true; success = true;
@ -386,8 +459,8 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
if (access(subdirname, X_OK) == 0) { if (access(subdirname, X_OK) == 0) {
ProcessList_processEntries(this, subdirname, pid, period); ProcessList_processEntries(this, subdirname, pid, period);
} }
} }
FILE* status; FILE* status;
char statusfilename[MAX_NAME+1]; char statusfilename[MAX_NAME+1];
char command[PROCESS_COMM_LEN + 1]; char command[PROCESS_COMM_LEN + 1];
@ -398,7 +471,7 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
process = Process_clone(prototype); process = Process_clone(prototype);
process->pid = pid; process->pid = pid;
ProcessList_add(this, process); ProcessList_add(this, process);
if (! ProcessList_readStatusFile(process, dirname, name)) if (! ProcessList_readStatusFile(this, process, dirname, name))
goto errorReadingProcess; goto errorReadingProcess;
} else { } else {
process = existingProcess; process = existingProcess;
@ -415,11 +488,12 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
int lasttimes = (process->utime + process->stime); int lasttimes = (process->utime + process->stime);
snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name); snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
status = fopen(statusfilename, "r");
status = ProcessList_fopen(this, statusfilename, "r");
if (status == NULL) if (status == NULL)
goto errorReadingProcess; goto errorReadingProcess;
int success = ProcessList_readStatFile(process, status, command); int success = ProcessList_readStatFile(this, process, status, command);
fclose(status); fclose(status);
if(!success) { if(!success) {
goto errorReadingProcess; goto errorReadingProcess;
@ -430,7 +504,7 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
if(!existingProcess) { if(!existingProcess) {
snprintf(statusfilename, MAX_NAME, "%s/%s/cmdline", dirname, name); snprintf(statusfilename, MAX_NAME, "%s/%s/cmdline", dirname, name);
status = fopen(statusfilename, "r"); status = ProcessList_fopen(this, statusfilename, "r");
if (!status) { if (!status) {
goto errorReadingProcess; goto errorReadingProcess;
} }
@ -448,14 +522,16 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
} }
snprintf(statusfilename, MAX_NAME, "%s/%s/statm", dirname, name); snprintf(statusfilename, MAX_NAME, "%s/%s/statm", dirname, name);
status = fopen(statusfilename, "r"); status = ProcessList_fopen(this, statusfilename, "r");
if(!status) { if(!status) {
goto errorReadingProcess; goto errorReadingProcess;
} }
int num = fscanf(status, "%d %d %d %d %d %d %d", int num = ProcessList_fread(this, status, "%d %d %d %d %d %d %d",
&process->m_size, &process->m_resident, &process->m_share, &process->m_size, &process->m_resident, &process->m_share,
&process->m_trs, &process->m_drs, &process->m_lrs, &process->m_trs, &process->m_drs, &process->m_lrs,
&process->m_dt); &process->m_dt);
fclose(status); fclose(status);
if(num != 7) if(num != 7)
goto errorReadingProcess; goto errorReadingProcess;
@ -465,9 +541,9 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
100.0; 100.0;
this->totalTasks++; this->totalTasks++;
if (process->state == 'R') { if (process->state == 'R') {
this->runningTasks++; this->runningTasks++;
} }
if (this->hideKernelThreads && process->m_size == 0) if (this->hideKernelThreads && process->m_size == 0)
ProcessList_remove(this, process); ProcessList_remove(this, process);
@ -489,7 +565,7 @@ void ProcessList_scan(ProcessList* this) {
FILE* status; FILE* status;
char buffer[128]; char buffer[128];
status = fopen(PROCMEMINFOFILE, "r"); status = ProcessList_fopen(this, PROCMEMINFOFILE, "r");
assert(status != NULL); assert(status != NULL);
while (!feof(status)) { while (!feof(status)) {
fgets(buffer, 128, status); fgets(buffer, 128, status);
@ -497,33 +573,35 @@ void ProcessList_scan(ProcessList* this) {
switch (buffer[0]) { switch (buffer[0]) {
case 'M': case 'M':
if (String_startsWith(buffer, "MemTotal:")) if (String_startsWith(buffer, "MemTotal:"))
sscanf(buffer, "MemTotal: %ld kB", &this->totalMem); ProcessList_read(this, buffer, "MemTotal: %ld kB", &this->totalMem);
else if (String_startsWith(buffer, "MemFree:")) else if (String_startsWith(buffer, "MemFree:"))
sscanf(buffer, "MemFree: %ld kB", &this->freeMem); ProcessList_read(this, buffer, "MemFree: %ld kB", &this->freeMem);
else if (String_startsWith(buffer, "MemShared:")) else if (String_startsWith(buffer, "MemShared:"))
sscanf(buffer, "MemShared: %ld kB", &this->sharedMem); ProcessList_read(this, buffer, "MemShared: %ld kB", &this->sharedMem);
break; break;
case 'B': case 'B':
if (String_startsWith(buffer, "Buffers:")) if (String_startsWith(buffer, "Buffers:"))
sscanf(buffer, "Buffers: %ld kB", &this->buffersMem); ProcessList_read(this, buffer, "Buffers: %ld kB", &this->buffersMem);
break; break;
case 'C': case 'C':
if (String_startsWith(buffer, "Cached:")) if (String_startsWith(buffer, "Cached:"))
sscanf(buffer, "Cached: %ld kB", &this->cachedMem); ProcessList_read(this, buffer, "Cached: %ld kB", &this->cachedMem);
break; break;
case 'S': case 'S':
if (String_startsWith(buffer, "SwapTotal:")) if (String_startsWith(buffer, "SwapTotal:"))
sscanf(buffer, "SwapTotal: %ld kB", &this->totalSwap); ProcessList_read(this, buffer, "SwapTotal: %ld kB", &this->totalSwap);
if (String_startsWith(buffer, "SwapFree:")) if (String_startsWith(buffer, "SwapFree:"))
sscanf(buffer, "SwapFree: %ld kB", &swapFree); ProcessList_read(this, buffer, "SwapFree: %ld kB", &swapFree);
break; break;
} }
} }
this->usedMem = this->totalMem - this->freeMem; this->usedMem = this->totalMem - this->freeMem;
this->usedSwap = this->totalSwap - swapFree; this->usedSwap = this->totalSwap - swapFree;
fclose(status); fclose(status);
status = fopen(PROCSTATFILE, "r"); status = ProcessList_fopen(this, PROCSTATFILE, "r");
assert(status != NULL); assert(status != NULL);
for (int i = 0; i <= this->processorCount; i++) { for (int i = 0; i <= this->processorCount; i++) {
char buffer[256]; char buffer[256];
@ -535,9 +613,9 @@ void ProcessList_scan(ProcessList* this) {
// The rest will remain at zero. // The rest will remain at zero.
fgets(buffer, 255, status); fgets(buffer, 255, status);
if (i == 0) if (i == 0)
sscanf(buffer, "cpu %ld %ld %ld %ld %ld %ld %ld %ld\n", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal); ProcessList_read(this, buffer, "cpu %ld %ld %ld %ld %ld %ld %ld %ld", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal);
else { else {
sscanf(buffer, "cpu%d %ld %ld %ld %ld %ld %ld %ld %ld\n", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal); ProcessList_read(this, buffer, "cpu%d %ld %ld %ld %ld %ld %ld %ld %ld", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal);
assert(cpuid == i - 1); assert(cpuid == i - 1);
} }
// Fields existing on kernels >= 2.6 // Fields existing on kernels >= 2.6

View File

@ -1,14 +1,19 @@
/* Do not edit this file. It was automatically genarated. */ /* Do not edit this file. It was automatically generated. */
#ifndef HEADER_ProcessList #ifndef HEADER_ProcessList
#define HEADER_ProcessList #define HEADER_ProcessList
/* /*
htop - ProcessList.h htop - ProcessList.c
(C) 2004-2006 Hisham H. Muhammad (C) 2004,2005 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#ifndef CONFIG_H
#define CONFIG_H
#include "config.h"
#endif
#include "Process.h" #include "Process.h"
#include "TypedVector.h" #include "TypedVector.h"
#include "UsersTable.h" #include "UsersTable.h"
@ -23,6 +28,7 @@ in the source distribution for its full text.
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <stdarg.h>
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
@ -43,6 +49,12 @@ in the source distribution for its full text.
#define MAX_NAME 128 #define MAX_NAME 128
#endif #endif
#ifndef MAX_READ
#define MAX_READ 8192
#endif
typedef struct ProcessList_ { typedef struct ProcessList_ {
TypedVector* processes; TypedVector* processes;
TypedVector* processes2; TypedVector* processes2;
@ -75,11 +87,6 @@ typedef struct ProcessList_ {
long int usedSwap; long int usedSwap;
long int freeSwap; long int freeSwap;
int kernelMajor;
int kernelMiddle;
int kernelMinor;
int kernelTiny;
ProcessField* fields; ProcessField* fields;
ProcessField sortKey; ProcessField sortKey;
int direction; int direction;
@ -90,10 +97,30 @@ typedef struct ProcessList_ {
bool treeView; bool treeView;
bool highlightBaseName; bool highlightBaseName;
bool highlightMegabytes; bool highlightMegabytes;
#ifdef DEBUG
FILE* traceFile;
#endif
} ProcessList; } ProcessList;
#ifdef DEBUG
#define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ )
#define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
#else
#ifndef ProcessList_read
#define ProcessList_fopen(this, path, mode) fopen(path, mode)
#define ProcessList_read(this, buffer, format, ...) sscanf(buffer, format, ## __VA_ARGS__ )
#define ProcessList_fread(this, file, format, ...) fscanf(file, format, ## __VA_ARGS__ )
#endif
#endif
ProcessList* ProcessList_new(UsersTable* usersTable); ProcessList* ProcessList_new(UsersTable* usersTable);
@ -103,6 +130,7 @@ void ProcessList_invertSortOrder(ProcessList* this);
RichString ProcessList_printHeader(ProcessList* this); RichString ProcessList_printHeader(ProcessList* this);
void ProcessList_prune(ProcessList* this); void ProcessList_prune(ProcessList* this);
void ProcessList_add(ProcessList* this, Process* p); void ProcessList_add(ProcessList* this, Process* p);
@ -117,6 +145,10 @@ int ProcessList_size(ProcessList* this);
void ProcessList_sort(ProcessList* this); void ProcessList_sort(ProcessList* this);
bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name);
void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, float period);
void ProcessList_scan(ProcessList* this); void ProcessList_scan(ProcessList* this);
void ProcessList_dontCrash(int signal); void ProcessList_dontCrash(int signal);