OpenFilesScreen update

- Remove local types and function from header file
- Reduce OpenFiles_Data to neccessary size
- Print file access mode (r/w/u)
- Fix memory leak on consecutive items without an intermediate file item:

    ==15257==ERROR: LeakSanitizer: detected memory leaks

    Direct leak of 120 byte(s) in 12 object(s) allocated from:
        #0 0x48c864 in strdup (htop/htop+0x48c864)
        #1 0x542f68 in xStrdup htop/XAlloc.c:71:17
        #2 0x50e225 in OpenFilesScreen_getProcessData htop/OpenFilesScreen.c:112:25
        #3 0x50cd17 in OpenFilesScreen_scan htop/OpenFilesScreen.c:141:35
        #4 0x4fd3eb in InfoScreen_run htop/InfoScreen.c:81:35
        #5 0x4d58bb in actionLsof htop/Action.c:361:4
        #6 0x501766 in MainPanel_eventHandler htop/MainPanel.c:80:19
        #7 0x5289fa in ScreenManager_run htop/ScreenManager.c:227:19
        #8 0x4f748e in main htop/htop.c:300:4
        #9 0x7ff73e0d8cc9 in __libc_start_main csu/../csu/libc-start.c:308:16

    SUMMARY: AddressSanitizer: 120 byte(s) leaked in 12 allocation(s).
This commit is contained in:
Christian Göttsche 2020-10-07 19:02:23 +02:00 committed by cgzones
parent 79ad39c718
commit f8b9ced93f
2 changed files with 101 additions and 49 deletions

View File

@ -24,30 +24,63 @@ in the source distribution for its full text.
#include <sys/wait.h> #include <sys/wait.h>
const InfoScreenClass OpenFilesScreen_class = { typedef struct OpenFiles_Data_ {
.super = { char* data[7];
.extends = Class(Object), } OpenFiles_Data;
.delete = OpenFilesScreen_delete
},
.scan = OpenFilesScreen_scan,
.draw = OpenFilesScreen_draw
};
OpenFilesScreen* OpenFilesScreen_new(Process* process) { typedef struct OpenFiles_ProcessData_ {
OpenFiles_Data data;
int error;
struct OpenFiles_FileData_* files;
} OpenFiles_ProcessData;
typedef struct OpenFiles_FileData_ {
OpenFiles_Data data;
struct OpenFiles_FileData_* next;
} OpenFiles_FileData;
static size_t getIndexForType(char type) {
switch (type) {
case 'f':
return 0;
case 'a':
return 1;
case 'D':
return 2;
case 'i':
return 3;
case 'n':
return 4;
case 's':
return 5;
case 't':
return 6;
}
/* should never reach here */
abort();
}
static const char* getDataForType(const OpenFiles_Data* data, char type) {
size_t index = getIndexForType(type);
return data->data[index] ? data->data[index] : "";
}
OpenFilesScreen* OpenFilesScreen_new(const Process* process) {
OpenFilesScreen* this = xMalloc(sizeof(OpenFilesScreen)); OpenFilesScreen* this = xMalloc(sizeof(OpenFilesScreen));
Object_setClass(this, Class(OpenFilesScreen)); Object_setClass(this, Class(OpenFilesScreen));
if (Process_isThread(process)) if (Process_isThread(process))
this->pid = process->tgid; this->pid = process->tgid;
else else
this->pid = process->pid; this->pid = process->pid;
return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES-3, " FD TYPE DEVICE SIZE NODE NAME"); return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES-3, " FD TYPE MODE DEVICE SIZE NODE NAME");
} }
void OpenFilesScreen_delete(Object* this) { void OpenFilesScreen_delete(Object* this) {
free(InfoScreen_done((InfoScreen*)this)); free(InfoScreen_done((InfoScreen*)this));
} }
void OpenFilesScreen_draw(InfoScreen* this) { static void OpenFilesScreen_draw(InfoScreen* this) {
InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, this->process->comm); InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, this->process->comm);
} }
@ -99,7 +132,9 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
} }
unsigned char cmd = line[0]; unsigned char cmd = line[0];
if (cmd == 'f') { switch (cmd) {
case 'f': /* file descriptor */
{
OpenFiles_FileData* nextFile = xCalloc(1, sizeof(OpenFiles_FileData)); OpenFiles_FileData* nextFile = xCalloc(1, sizeof(OpenFiles_FileData));
if (fdata == NULL) { if (fdata == NULL) {
pdata->files = nextFile; pdata->files = nextFile;
@ -108,8 +143,35 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
} }
fdata = nextFile; fdata = nextFile;
item = &(fdata->data); item = &(fdata->data);
} /* FALLTHRU */
case 'a': /* file access mode */
case 'D': /* file's major/minor device number */
case 'i': /* file's inode number */
case 'n': /* file name, comment, Internet address */
case 's': /* file's size */
case 't': /* file's type */
{
size_t index = getIndexForType(cmd);
free(item->data[index]);
item->data[index] = xStrdup(line + 1);
break;
}
case 'c': /* process command name */
case 'd': /* file's device character code */
case 'g': /* process group ID */
case 'G': /* file flags */
case 'k': /* link count */
case 'l': /* file's lock status */
case 'L': /* process login name */
case 'o': /* file's offset */
case 'p': /* process ID */
case 'P': /* protocol name */
case 'R': /* parent process ID */
case 'T': /* TCP/TPI information, identified by prefixes */
case 'u': /* process user ID */
/* ignore */
break;
} }
item->data[cmd] = xStrdup(line + 1);
free(line); free(line);
} }
fclose(fd); fclose(fd);
@ -128,13 +190,12 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
return pdata; return pdata;
} }
static inline void OpenFiles_Data_clear(OpenFiles_Data* data) { static void OpenFiles_Data_clear(OpenFiles_Data* data) {
for (int i = 0; i < 255; i++) for (size_t i = 0; i < ARRAYSIZE(data->data); i++)
if (data->data[i])
free(data->data[i]); free(data->data[i]);
} }
void OpenFilesScreen_scan(InfoScreen* this) { static void OpenFilesScreen_scan(InfoScreen* this) {
Panel* panel = this->display; Panel* panel = this->display;
int idx = Panel_getSelectedIndex(panel); int idx = Panel_getSelectedIndex(panel);
Panel_prune(panel); Panel_prune(panel);
@ -146,19 +207,20 @@ void OpenFilesScreen_scan(InfoScreen* this) {
} else { } else {
OpenFiles_FileData* fdata = pdata->files; OpenFiles_FileData* fdata = pdata->files;
while (fdata) { while (fdata) {
char** data = fdata->data.data; OpenFiles_Data* data = &fdata->data;
int lenN = data['n'] ? strlen(data['n']) : 0; size_t lenN = strlen(getDataForType(data, 'n'));
int sizeEntry = 5 + 7 + 10 + 10 + 10 + lenN + 5 /*spaces*/ + 1 /*null*/; size_t sizeEntry = 5 + 7 + 4 + 10 + 10 + 10 + lenN + 7 /*spaces*/ + 1 /*null*/;
char entry[sizeEntry]; char entry[sizeEntry];
xSnprintf(entry, sizeEntry, "%5.5s %7.7s %10.10s %10.10s %10.10s %s", xSnprintf(entry, sizeof(entry), "%5.5s %-7.7s %-4.4s %-10.10s %10.10s %10.10s %s",
data['f'] ? data['f'] : "", getDataForType(data, 'f'),
data['t'] ? data['t'] : "", getDataForType(data, 't'),
data['D'] ? data['D'] : "", getDataForType(data, 'a'),
data['s'] ? data['s'] : "", getDataForType(data, 'D'),
data['i'] ? data['i'] : "", getDataForType(data, 's'),
data['n'] ? data['n'] : ""); getDataForType(data, 'i'),
getDataForType(data, 'n'));
InfoScreen_addLine(this, entry); InfoScreen_addLine(this, entry);
OpenFiles_Data_clear(&fdata->data); OpenFiles_Data_clear(data);
OpenFiles_FileData* old = fdata; OpenFiles_FileData* old = fdata;
fdata = fdata->next; fdata = fdata->next;
free(old); free(old);
@ -170,3 +232,12 @@ void OpenFilesScreen_scan(InfoScreen* this) {
Vector_insertionSort(panel->items); Vector_insertionSort(panel->items);
Panel_setSelected(panel, idx); Panel_setSelected(panel, idx);
} }
const InfoScreenClass OpenFilesScreen_class = {
.super = {
.extends = Class(Object),
.delete = OpenFilesScreen_delete
},
.scan = OpenFilesScreen_scan,
.draw = OpenFilesScreen_draw
};

View File

@ -9,21 +9,6 @@ in the source distribution for its full text.
#include "InfoScreen.h" #include "InfoScreen.h"
typedef struct OpenFiles_Data_ {
char* data[256];
} OpenFiles_Data;
typedef struct OpenFiles_ProcessData_ {
OpenFiles_Data data;
int error;
struct OpenFiles_FileData_* files;
} OpenFiles_ProcessData;
typedef struct OpenFiles_FileData_ {
OpenFiles_Data data;
struct OpenFiles_FileData_* next;
} OpenFiles_FileData;
typedef struct OpenFilesScreen_ { typedef struct OpenFilesScreen_ {
InfoScreen super; InfoScreen super;
pid_t pid; pid_t pid;
@ -31,12 +16,8 @@ typedef struct OpenFilesScreen_ {
extern const InfoScreenClass OpenFilesScreen_class; extern const InfoScreenClass OpenFilesScreen_class;
OpenFilesScreen* OpenFilesScreen_new(Process* process); OpenFilesScreen* OpenFilesScreen_new(const Process* process);
void OpenFilesScreen_delete(Object* this); void OpenFilesScreen_delete(Object* this);
void OpenFilesScreen_draw(InfoScreen* this);
void OpenFilesScreen_scan(InfoScreen* this);
#endif #endif