Fixed memory leaks

This commit is contained in:
Arnout Engelen
2005-01-15 15:03:20 +00:00
parent 4ce9f4fb1f
commit a142648f45
8 changed files with 112 additions and 68 deletions

View File

@@ -7,7 +7,7 @@ man8 := $(DESTDIR)/usr/share/man/man8/
all: nethogs all: nethogs
CFLAGS=-g -Wall -pg CFLAGS=-g -Wall
#CFLAGS=-O2 #CFLAGS=-O2
OBJS=structs.o packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o OBJS=structs.o packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o
GCC=g++ GCC=g++

View File

@@ -31,6 +31,7 @@ void PackList::add (Packet * p)
return; return;
} }
/* store copy of packet, so that original may be freed */
content = new PackListNode(new Packet (*p), content); content = new PackListNode(new Packet (*p), content);
} }
@@ -60,6 +61,7 @@ u_int32_t PackList::sumanddel (timeval t)
return retval; return retval;
} }
/* packet may be deleted by caller */
Connection::Connection (Packet * packet) Connection::Connection (Packet * packet)
{ {
if (ROBUST) if (ROBUST)

View File

@@ -44,6 +44,7 @@ public:
/* sums up the total bytes used and removes 'old' packets */ /* sums up the total bytes used and removes 'old' packets */
u_int32_t sumanddel (timeval t); u_int32_t sumanddel (timeval t);
/* calling code may delete packet */
void add (Packet * p); void add (Packet * p);
private: private:
PackListNode * content; PackListNode * content;
@@ -55,6 +56,7 @@ public:
/* constructs a connection, makes a copy of /* constructs a connection, makes a copy of
* the packet as 'refpacket', and adds the * the packet as 'refpacket', and adds the
* packet to the packlist */ * packet to the packlist */
/* packet may be deleted by caller */
Connection (Packet * packet); Connection (Packet * packet);
~Connection(); ~Connection();
@@ -83,6 +85,7 @@ private:
}; };
/* Find the connection this packet belongs to */ /* Find the connection this packet belongs to */
/* (the calling code may free the packet afterwards) */
Connection * findConnection (Packet * packet); Connection * findConnection (Packet * packet);
#endif #endif

111
cui.cpp
View File

@@ -17,8 +17,13 @@ extern Process * unknownproc;
class Line class Line
{ {
public: public:
Line (const char * name, double n_sent_kbps, double n_recv_kbps, int pid, uid_t uid, const char * n_devicename) Line (const char * name, double n_sent_kbps, double n_recv_kbps, pid_t pid, uid_t uid, const char * n_devicename)
{ {
if (ROBUST)
{
assert (uid >= 0);
assert (pid >= 0);
}
m_name = name; m_name = name;
sent_kbps = n_sent_kbps; sent_kbps = n_sent_kbps;
recv_kbps = n_recv_kbps; recv_kbps = n_recv_kbps;
@@ -39,22 +44,23 @@ public:
private: private:
const char * m_name; const char * m_name;
const char * devicename; const char * devicename;
int m_pid; pid_t m_pid;
int m_uid; uid_t m_uid;
}; };
char * uid2username (int uid) char * uid2username (uid_t uid)
{ {
struct passwd * pwd = NULL; struct passwd * pwd = NULL;
/* getpwuid() allocates space for this itself, /* getpwuid() allocates space for this itself,
* which we shouldn't free */ * which we shouldn't free */
pwd = getpwuid(uid); pwd = getpwuid(uid);
if (ROBUST)
assert (pwd != NULL);
if (pwd == NULL) if (pwd == NULL)
{ {
if (ROBUST)
{
assert(false);
}
return strdup ("unlisted"); return strdup ("unlisted");
} else { } else {
return strdup(pwd->pw_name); return strdup(pwd->pw_name);
@@ -169,7 +175,7 @@ void do_refresh()
double sent_global = 0; double sent_global = 0;
double recv_global = 0; double recv_global = 0;
if (DEBUG) if (ROBUST)
{ {
// initialise to null pointers // initialise to null pointers
for (int i = 0; i < nproc; i++) for (int i = 0; i < nproc; i++)
@@ -185,6 +191,7 @@ void do_refresh()
{ {
assert (curproc != NULL); assert (curproc != NULL);
assert (curproc->getVal() != NULL); assert (curproc->getVal() != NULL);
assert (nproc == processes->size());
} }
/* do not remove the unknown process */ /* do not remove the unknown process */
if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknownproc)) if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknownproc))
@@ -207,48 +214,62 @@ void do_refresh()
nproc--; nproc--;
//continue; //continue;
} }
else{ else
u_int32_t sum_sent = 0,
sum_recv = 0;
/* walk though all this process's connections, and sum them
* up */
ConnList * curconn = curproc->getVal()->connections;
ConnList * previous = NULL;
while (curconn != NULL)
{ {
if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT)
u_int32_t sum_sent = 0,
sum_recv = 0;
/* walk though all this process's connections, and sum them
* up */
ConnList * curconn = curproc->getVal()->connections;
ConnList * previous = NULL;
while (curconn != NULL)
{ {
/* stalled connection, remove. */ if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT)
ConnList * todelete = curconn; {
Connection * conn_todelete = curconn->getVal(); /* stalled connection, remove. */
curconn = curconn->getNext(); ConnList * todelete = curconn;
if (todelete == curproc->getVal()->connections) Connection * conn_todelete = curconn->getVal();
curproc->getVal()->connections = curconn; curconn = curconn->getNext();
if (previous != NULL) if (todelete == curproc->getVal()->connections)
previous->setNext(curconn); curproc->getVal()->connections = curconn;
delete (todelete); if (previous != NULL)
delete (conn_todelete); previous->setNext(curconn);
delete (todelete);
delete (conn_todelete);
}
else
{
u_int32_t sent = 0, recv = 0;
curconn->getVal()->sumanddel(curtime, &sent, &recv);
sum_sent += sent;
sum_recv += recv;
previous = curconn;
curconn = curconn->getNext();
}
} }
else uid_t uid = curproc->getVal()->getUid();
if (ROBUST)
{ {
u_int32_t sent = 0, recv = 0; assert (getpwuid(uid) != NULL);
curconn->getVal()->sumanddel(curtime, &sent, &recv); assert (curproc->getVal()->pid >= 0);
sum_sent += sent; assert (n < nproc);
sum_recv += recv; }
previous = curconn; lines[n] = new Line (curproc->getVal()->name, tokbps(sum_sent), tokbps(sum_recv),
curconn = curconn->getNext(); curproc->getVal()->pid, uid, curproc->getVal()->devicename);
previousproc = curproc;
curproc = curproc->next;
n++;
if (ROBUST)
{
assert (nproc == processes->size());
if (curproc == NULL)
assert (n-1 < nproc);
else
assert (n < nproc);
} }
}
uid_t uid = curproc->getVal()->getUid();
if (ROBUST)
assert (uid >= 0);
lines[n] = new Line (curproc->getVal()->name, tokbps(sum_sent), tokbps(sum_recv),
curproc->getVal()->pid, uid, curproc->getVal()->devicename);
previousproc = curproc;
curproc = curproc->next;
n++;
} }
} }

View File

@@ -55,6 +55,7 @@ char * getprogname (char * pid) {
int fd = open(filename, O_RDONLY); int fd = open(filename, O_RDONLY);
if (fd < 0) { if (fd < 0) {
fprintf (stderr, "Error opening %s: %s\n", filename, strerror(errno)); fprintf (stderr, "Error opening %s: %s\n", filename, strerror(errno));
free (filename);
exit(3); exit(3);
return NULL; return NULL;
} }
@@ -63,6 +64,7 @@ char * getprogname (char * pid) {
cout << "Error closing file: " << strerror(errno) << endl; cout << "Error closing file: " << strerror(errno) << endl;
exit(34); exit(34);
} }
free (filename);
if (length < bufsize - 1) if (length < bufsize - 1)
buffer[length]='\0'; buffer[length]='\0';
@@ -76,6 +78,13 @@ char * getprogname (char * pid) {
return strdup(retval); return strdup(retval);
} }
void setnode (unsigned long inode, prg_node * newnode)
{
if (inodeproc[inode] != NULL)
free (inodeproc[inode]);
inodeproc[inode] = newnode;
}
void get_info_by_linkname (char * pid, char * linkname) { void get_info_by_linkname (char * pid, char * linkname) {
if (strncmp(linkname, "socket:[", 8) == 0) { if (strncmp(linkname, "socket:[", 8) == 0) {
char * ptr = linkname + 8; char * ptr = linkname + 8;
@@ -90,7 +99,7 @@ void get_info_by_linkname (char * pid, char * linkname) {
// TODO progname could be more memory-efficient // TODO progname could be more memory-efficient
strncpy (newnode->name, progname, PROGNAME_WIDTH); strncpy (newnode->name, progname, PROGNAME_WIDTH);
free (progname); free (progname);
inodeproc[inode] = newnode; setnode (inode, newnode);
} else { } else {
//std::cout << "Linkname looked like: " << linkname << endl; //std::cout << "Linkname looked like: " << linkname << endl;
} }
@@ -128,6 +137,11 @@ void get_info_for_pid(char * pid) {
int linklen = 80; int linklen = 80;
char linkname [linklen]; char linkname [linklen];
int usedlen = readlink(fromname, linkname, linklen-1); int usedlen = readlink(fromname, linkname, linklen-1);
if (usedlen == -1)
{
free (fromname);
continue;
}
if (ROBUST) if (ROBUST)
assert (usedlen < linklen); assert (usedlen < linklen);
linkname[usedlen] = '\0'; linkname[usedlen] = '\0';

View File

@@ -107,12 +107,12 @@ int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_p
{ {
/* add packet to the connection */ /* add packet to the connection */
connection->add(packet); connection->add(packet);
delete packet;
} else { } else {
/* else: unknown connection, create new */ /* else: unknown connection, create new */
connection = new Connection (packet); connection = new Connection (packet);
getProcess(connection, currentdevice); getProcess(connection, currentdevice);
} }
delete packet;
if (needrefresh) if (needrefresh)
{ {

View File

@@ -28,7 +28,7 @@ extern local_addr * local_addrs;
* key contains source ip, source port, destination ip, destination * key contains source ip, source port, destination ip, destination
* port in format: '1.2.3.4:5-1.2.3.4:5' * port in format: '1.2.3.4:5-1.2.3.4:5'
*/ */
std::map <std::string, unsigned long *> conninode; std::map <std::string, unsigned long> conninode;
/* /*
* Initialise the global process-list with `the' unknown process * Initialise the global process-list with `the' unknown process
@@ -82,18 +82,19 @@ void addtoconninode (char * buffer)
struct in6_addr in6_local; struct in6_addr in6_local;
struct in6_addr in6_remote; struct in6_addr in6_remote;
// the following leaks some memory. // this leaked memory
unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long)); //unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long));
unsigned long inode;
int matches = sscanf(buffer, "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %*512s\n", int matches = sscanf(buffer, "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %*512s\n",
local_addr, &local_port, rem_addr, &rem_port, inode); local_addr, &local_port, rem_addr, &rem_port, &inode);
if (matches != 5) { if (matches != 5) {
fprintf(stderr,"Unexpected buffer: '%s'\n",buffer); fprintf(stderr,"Unexpected buffer: '%s'\n",buffer);
exit(0); exit(0);
} }
if (*inode == 0) { if (inode == 0) {
/* connection is in TIME_WAIT state. We rely on /* connection is in TIME_WAIT state. We rely on
* the old data still in the table. */ * the old data still in the table. */
return; return;
@@ -229,14 +230,14 @@ void reviewUnknown ()
ConnList * previous_conn = NULL; ConnList * previous_conn = NULL;
while (curr_conn != NULL) { while (curr_conn != NULL) {
unsigned long * inode = conninode[curr_conn->getVal()->refpacket->gethashstring()]; unsigned long inode = conninode[curr_conn->getVal()->refpacket->gethashstring()];
if (inode != NULL) if (inode != 0)
{ {
Process * proc = findProcess (*inode); Process * proc = findProcess (inode);
if (proc != unknownproc && proc != NULL) if (proc != unknownproc && proc != NULL)
{ {
if (DEBUG) if (DEBUG)
std::cout << "ITP: WARNING: Previously unknown inode " << *inode << " now got process...??\n"; std::cout << "ITP: WARNING: Previously unknown inode " << inode << " now got process...??\n";
/* Yay! - but how could this happen? */ /* Yay! - but how could this happen? */
//assert(false); //assert(false);
if (previous_conn != NULL) if (previous_conn != NULL)
@@ -315,7 +316,7 @@ Process * getProcess (unsigned long inode, char * devicename)
if (proc != NULL) if (proc != NULL)
return proc; return proc;
Process * newproc = new Process (inode, strdup(devicename)); Process * newproc = new Process (inode, devicename);
newproc->name = strdup(node->name); newproc->name = strdup(node->name);
newproc->pid = node->pid; newproc->pid = node->pid;
@@ -325,6 +326,7 @@ Process * getProcess (unsigned long inode, char * devicename)
stat(procdir, &stats); stat(procdir, &stats);
newproc->setUid(stats.st_uid); newproc->setUid(stats.st_uid);
assert (getpwuid(stats.st_uid) != NULL);
processes = new ProcList (newproc, processes); processes = new ProcList (newproc, processes);
return newproc; return newproc;
} }
@@ -338,9 +340,9 @@ Process * getProcess (unsigned long inode, char * devicename)
*/ */
Process * getProcess (Connection * connection, char * devicename) Process * getProcess (Connection * connection, char * devicename)
{ {
unsigned long * inode = conninode[connection->refpacket->gethashstring()]; unsigned long inode = conninode[connection->refpacket->gethashstring()];
if (inode == NULL) if (inode == 0)
{ {
// no? refresh and check conn/inode table // no? refresh and check conn/inode table
#if DEBUG #if DEBUG
@@ -348,7 +350,7 @@ Process * getProcess (Connection * connection, char * devicename)
#endif #endif
refreshconninode(); refreshconninode();
inode = conninode[connection->refpacket->gethashstring()]; inode = conninode[connection->refpacket->gethashstring()];
if (inode == NULL) if (inode == 0)
{ {
/* HACK: the following is a hack for cases where the /* HACK: the following is a hack for cases where the
* 'local' addresses aren't properly recognised, as is * 'local' addresses aren't properly recognised, as is
@@ -360,7 +362,7 @@ Process * getProcess (Connection * connection, char * devicename)
Packet * reversepacket = connection->refpacket->newInverted(); Packet * reversepacket = connection->refpacket->newInverted();
inode = conninode[reversepacket->gethashstring()]; inode = conninode[reversepacket->gethashstring()];
if (inode == NULL) if (inode == 0)
{ {
delete reversepacket; delete reversepacket;
if (DEBUG) if (DEBUG)
@@ -374,7 +376,7 @@ Process * getProcess (Connection * connection, char * devicename)
} }
} }
Process * proc = getProcess(*inode, devicename); Process * proc = getProcess(inode, devicename);
proc->connections = new ConnList (connection, proc->connections); proc->connections = new ConnList (connection, proc->connections);
return proc; return proc;
} }

View File

@@ -66,16 +66,18 @@ public:
assert (uid >= 0); assert (uid >= 0);
} }
} }
/* TODO free m_name and m_devicename again in constructor */
~Process () ~Process ()
{ {
free (name);
free (devicename);
if (DEBUG) if (DEBUG)
std::cout << "PROC: Process deleted at " << this << std::endl; std::cout << "PROC: Process deleted at " << this << std::endl;
} }
int getLastPacket (); int getLastPacket ();
const char * name; char * name;
const char * devicename; char * devicename;
int pid; int pid;
unsigned long inode; unsigned long inode;