argus 3.0.0 rc.28 memory leaks
Gabriel L. Somlo
somlo at cmu.edu
Thu Aug 31 14:39:11 EDT 2006
Carter,
I've been running argus on a box with 1Gig of memory, and an
Endace card to capture several hundred Mbps from our core. Argus
becomes unresponsive in cca 20-30 minutes, because its memory
image grows to the point where it starts swapping, and I can't
get any more flow records from it beyond that point.
I bumped the memory to two Gigs, and now it takes longer but it still
maxes out eventually and argus has to be restarted.
I've started looking for possible memory leaks, and the attached patch
fixes the ones I found so far. I also fixed a couple of places where
the code allowed a null pointer to be de-referenced (didn't see those
being tickled in a real-life situation, but better safe than sorry :)
Please apply, and I'll try to find more once these changes are in :)
Thanks,
Gabriel
-------------- next part --------------
diff -NarU5 argus-3.0.0.rc.28.orig/argus/argus.c argus-3.0.0.rc.28/argus/argus.c
--- argus-3.0.0.rc.28.orig/argus/argus.c 2006-08-18 13:15:14.000000000 -0400
+++ argus-3.0.0.rc.28/argus/argus.c 2006-08-31 11:29:11.000000000 -0400
@@ -522,14 +522,16 @@
ArgusDebug (1, "ArgusShutDown(%s)\n\n", ArgusSignalTable[sig]);
#endif
if (!(ArgusShutDownStarted++)) {
+ clearArgusConfiguration(ArgusModel);
ArgusCloseSource (ArgusSourceTask);
ArgusCloseModeler(ArgusModel);
ArgusCloseOutput(ArgusOutputTask);
ArgusComplete ();
+ ArgusShutdownRecordAllocator();
} else {
#ifdef ARGUSDEBUG
ArgusDebug (2, "ArgusShutDown() returning\n");
#endif
@@ -1022,12 +1024,19 @@
void
clearArgusWfile(void)
{
+ if (ArgusOutputTask->ArgusWfileList != NULL) {
+ struct ArgusWfileStruct *wfile;
+ while ((wfile = (struct ArgusWfileStruct *) ArgusPopFrontList(ArgusOutputTask->ArgusWfileList, ARGUS_NOLOCK)) != NULL) {
+ if (wfile->filename != NULL) free(wfile->filename);
+ ArgusFree(wfile);
+ }
ArgusDeleteList (ArgusOutputTask->ArgusWfileList);
ArgusOutputTask->ArgusWfileList = NULL;
+ }
}
void
setArgusWfile(char *file, char *filter)
{
diff -NarU5 argus-3.0.0.rc.28.orig/argus/ArgusModeler.c argus-3.0.0.rc.28/argus/ArgusModeler.c
--- argus-3.0.0.rc.28.orig/argus/ArgusModeler.c 2006-08-28 22:31:58.000000000 -0400
+++ argus-3.0.0.rc.28/argus/ArgusModeler.c 2006-08-31 11:29:11.000000000 -0400
@@ -94,12 +94,14 @@
/* align the ArgusThisFlow buffer */
if ((retn->ArgusThisFlow = (struct ArgusSystemFlow *) ArgusCalloc (1, sizeof (struct ArgusSystemFlow) + 32)) == NULL)
ArgusLog (LOG_ERR, "ArgusNewModeler () ArgusCalloc error %s\n", strerror(errno));
+/* ArgusCalloc already aligns on a 128-bit multiple -- GLS
retn->ArgusThisFlow = (struct ArgusSystemFlow *) ((char *)retn->ArgusThisFlow + ((long)retn->ArgusThisFlow & 0x0F));
retn->ArgusThisFlow = (struct ArgusSystemFlow *) ((char *)retn->ArgusThisFlow + 12);
+*/
gettimeofday (tvp, 0L);
retn->ArgusGlobalTime = *tvp;
retn->ArgusThisLLC = &ArgusThisLLCBuffer;
@@ -143,10 +145,11 @@
model->ArgusTCPTimeout = ARGUS_TCPTIMEOUT;
model->ArgusICMPTimeout = ARGUS_ICMPTIMEOUT;
model->ArgusIGMPTimeout = ARGUS_IGMPTIMEOUT;
model->ArgusFRAGTimeout = ARGUS_FRAGTIMEOUT;
+ /* FIXME: maybe we need an explicit ArgusInitRecordAllocator() method :) -- GLS */
if ((retn = (struct ArgusRecordStruct *) ArgusMallocListRecord(sizeof(struct ArgusRecordStruct))) != NULL)
ArgusFreeListRecord(retn);
#ifdef ARGUSDEBUG
ArgusDebug (1, "ArgusInitModeler() done\n");
@@ -168,14 +171,25 @@
if (htbl->array)
ArgusFree(htbl->array);
ArgusFree(htbl);
}
+ /* FIXME: we're shutting down, so why push another record onto the list ? -- GLS */
if ((argus = ArgusGenerateListRecord (model, NULL, ARGUS_STOP)) != NULL) {
model->ArgusTotalSends++;
ArgusPushBackList (model->ArgusOutputList, (struct ArgusListRecord *) argus, ARGUS_LOCK);
}
+
+ if (model->ArgusOutputList != NULL) {
+ while ((argus = (struct ArgusRecordStruct *) ArgusPopFrontList(model->ArgusOutputList, ARGUS_NOLOCK)) != NULL) {
+ ArgusFreeListRecord(argus);
+ }
+ ArgusDeleteList(model->ArgusOutputList);
+ }
+ ArgusFree(model->hstruct);
+ ArgusFree(model->ArgusThisFlow);
+ ArgusFree(model);
}
#ifdef ARGUSDEBUG
ArgusDebug (1, "ArgusCloseModeler(0x%x)\n", model);
#endif
@@ -2463,12 +2477,12 @@
ArgusCopyRecordStruct (struct ArgusRecordStruct *rec)
{
struct ArgusRecordStruct *retn = NULL;
int i;
- if ((retn = (struct ArgusRecordStruct *) ArgusMallocListRecord (sizeof(*retn))) != NULL) {
- if (rec) {
+ if (rec) {
+ if ((retn = (struct ArgusRecordStruct *) ArgusMallocListRecord (sizeof(*retn))) != NULL) {
bcopy ((char *)&rec->hdr, (char *)&retn->hdr, sizeof (rec->hdr));
bcopy ((char *)&rec->canon, (char *)&retn->canon, sizeof (rec->canon));
if ((retn->dsrindex = rec->dsrindex)) {
for (i = 0; i < ARGUSMAXFLOWTYPE; i++) {
@@ -2510,16 +2524,16 @@
retn->dsrs[i] = NULL;
retn->dsrindex &= ~(0x01 << i);
}
}
}
- }
- retn->hdr.type = ARGUS_FAR;
- retn->status = rec->status;
- retn->trans = rec->trans;
- retn->timeout = rec->timeout;
+ retn->hdr.type = ARGUS_FAR;
+ retn->status = rec->status;
+ retn->trans = rec->trans;
+ retn->timeout = rec->timeout;
+ }
}
#ifdef ARGUSDEBUG
ArgusDebug (8, "ArgusCopyRecordStruct (0x%x) done\n", rec);
#endif
diff -NarU5 argus-3.0.0.rc.28.orig/argus/ArgusOutput.c argus-3.0.0.rc.28/argus/ArgusOutput.c
--- argus-3.0.0.rc.28.orig/argus/ArgusOutput.c 2006-08-23 22:45:34.000000000 -0400
+++ argus-3.0.0.rc.28/argus/ArgusOutput.c 2006-08-31 11:29:11.000000000 -0400
@@ -136,10 +136,14 @@
if (strcmp(wfile->filename, "/dev/null"))
output->clients[ind].sock->filename = strdup(wfile->filename);
output->clients[ind].ArgusClientStart++;
+
+ if (wfile->filename != NULL) free(wfile->filename);
+ if (wfile->filter != NULL) free(wfile->filter);
+ ArgusFree(wfile);
}
}
ArgusDeleteList(ArgusWfileList);
}
@@ -190,10 +194,14 @@
#endif
ArgusOutputProcess(output);
}
#endif /* ARGUS_THREADS */
+ ArgusFree(output->ArgusInitMar);
+ ArgusDeleteList(ArgusOutputTask->ArgusOutputList);
+ ArgusFree(output);
+
#ifdef ARGUSDEBUG
ArgusDebug (1, "ArgusCloseOutput() done\n");
#endif
}
diff -NarU5 argus-3.0.0.rc.28.orig/argus/ArgusSource.c argus-3.0.0.rc.28/argus/ArgusSource.c
--- argus-3.0.0.rc.28.orig/argus/ArgusSource.c 2006-08-28 23:14:45.000000000 -0400
+++ argus-3.0.0.rc.28/argus/ArgusSource.c 2006-08-31 14:25:21.000000000 -0400
@@ -198,20 +198,37 @@
if (src) {
if (src->ArgusInputFilter)
ArgusFree (src->ArgusInputFilter);
- if (src->ArgusDeviceList)
+ if (src->ArgusDeviceList != NULL) {
+ struct ArgusDeviceStruct *device;
+ while ((device = (struct ArgusDeviceStruct *) ArgusPopFrontList(src->ArgusDeviceList, ARGUS_NOLOCK)) != NULL) {
+ if (device->name != NULL) free(device->name);
+ ArgusFree(device);
+ }
ArgusDeleteList(src->ArgusDeviceList);
+ }
if (src->ArgusPcapOutFile)
pcap_dump_close(src->ArgusPcapOutFile);
- }
+
+ if (src->ArgusRfileList != NULL) {
+ struct ArgusRfileStruct *rfile;
+ while ((rfile = (struct ArgusRfileStruct *) ArgusPopFrontList(src->ArgusRfileList, ARGUS_NOLOCK)) != NULL) {
+ if (rfile->name != NULL) free(rfile->name);
+ ArgusFree(rfile);
+ }
+ ArgusDeleteList(src->ArgusRfileList);
+ }
#ifdef ARGUSDEBUG
ArgusDebug (1, "ArgusCloseSource(0x%x) deleting source\n", src);
#endif
+ ArgusFree(src);
+ }
+
return (0);
}
unsigned char
@@ -331,10 +348,15 @@
void
clearArgusDevice (struct ArgusSourceStruct *src)
{
if (src->ArgusDeviceList != NULL) {
+ struct ArgusDeviceStruct *device = NULL;
+ while ((device = (struct ArgusDeviceStruct *) ArgusPopFrontList(src->ArgusDeviceList, ARGUS_NOLOCK)) != NULL) {
+ if (device->name != NULL) free(device->name);
+ ArgusFree(device);
+ }
ArgusDeleteList(src->ArgusDeviceList);
src->ArgusDeviceList = NULL;
}
#ifdef ARGUSDEBUG
diff -NarU5 argus-3.0.0.rc.28.orig/argus/ArgusUtil.c argus-3.0.0.rc.28/argus/ArgusUtil.c
--- argus-3.0.0.rc.28.orig/argus/ArgusUtil.c 2006-08-23 22:36:06.000000000 -0400
+++ argus-3.0.0.rc.28/argus/ArgusUtil.c 2006-08-31 11:29:11.000000000 -0400
@@ -105,11 +105,12 @@
void
ArgusDeleteList (struct ArgusListStruct *list)
{
if (list) {
while (list->start)
- ArgusPopFrontList(list, ARGUS_LOCK);
+ /* FIXME: last-ditch effort, since list elements might contain further dynamically allocated data -- GLS */
+ ArgusFree(ArgusPopFrontList(list, ARGUS_LOCK));
ArgusFree (list);
}
#ifdef ARGUSDEBUG
diff -NarU5 argus-3.0.0.rc.28.orig/common/argus_util.c argus-3.0.0.rc.28/common/argus_util.c
--- argus-3.0.0.rc.28.orig/common/argus_util.c 2006-08-18 13:14:48.000000000 -0400
+++ argus-3.0.0.rc.28/common/argus_util.c 2006-08-31 13:54:56.000000000 -0400
@@ -1033,13 +1033,14 @@
int ArgusAllocTotal = 0;
int ArgusAllocBytes = 0;
int ArgusFreeTotal = 0;
+#if defined(ARGUSMEMDEBUG)
struct ArgusMemoryList memory = {NULL, 0};
-
#define ARGUS_ALLOC 0x45672381
+#endif
void *
ArgusMalloc (int bytes)
{
void *retn = NULL;
@@ -1052,11 +1053,11 @@
#if defined(ARGUS_ALIGN_128)
offset = 128;
#endif
#if defined(ARGUSMEMDEBUG)
- if ((retn = (u_int *) malloc (bytes + sizeof(struct ArgusMemoryHeader) + offset)) != NULL) {
+ if ((retn = malloc (bytes + sizeof(struct ArgusMemoryHeader) + offset)) != NULL) {
struct ArgusMemoryHeader *mem = (struct ArgusMemoryHeader *)retn;
mem->tag = ARGUS_ALLOC;
mem->len = bytes;
mem->offset = offset;
#if defined(__GNUC__)
@@ -1079,22 +1080,22 @@
memory.count++;
memory.total++;
retn = (void *)(mem + 1);
}
#else
- retn = (void *) malloc (bytes + offset);
+ retn = malloc (bytes + offset);
#endif
- if (retn != NULL) {
#if defined(ARGUS_ALIGN_128)
+ if (retn != NULL) {
unsigned short toff;
toff = ((unsigned long)retn & (offset - 1));
toff = offset - toff;
retn = (void *)((char *)retn + toff);
((unsigned short *)retn)[-1] = toff;
-#endif
}
+#endif
}
#ifdef ARGUSDEBUG
ArgusDebug (6, "ArgusMalloc (%d) returning 0x%x\n", bytes, retn);
#endif
return (retn);
@@ -1102,25 +1103,26 @@
void *
ArgusCalloc (int nitems, int bytes)
{
void *retn = NULL;
+ int totbytes = nitems * bytes;
int offset = 0;
if (bytes) {
ArgusAllocTotal++;
- ArgusAllocBytes += bytes;
+ ArgusAllocBytes += totbytes;
#if defined(ARGUS_ALIGN_128)
offset = 128;
#endif
#if defined(ARGUSMEMDEBUG)
- if ((retn = (u_int *) calloc (1, (nitems * bytes) + sizeof(struct ArgusMemoryHeader) + offset)) != NULL) {
- struct ArgusMemoryHeader *mem = retn;
+ if ((retn = calloc (1, totbytes + sizeof(struct ArgusMemoryHeader) + offset)) != NULL) {
+ struct ArgusMemoryHeader *mem = (struct ArgusMemoryHeader *)retn;
mem->tag = ARGUS_ALLOC;
- mem->len = bytes;
+ mem->len = totbytes;
mem->offset = offset;
#if defined(__GNUC__)
mem->frame[0] = __builtin_return_address(0);
mem->frame[1] = __builtin_return_address(1);
mem->frame[2] = __builtin_return_address(2);
@@ -1140,28 +1142,28 @@
memory.total++;
memory.count++;
retn = (void *)(mem + 1);
}
#else
- retn = calloc (1, (nitems * bytes) + offset);
+ retn = calloc (1, totbytes + offset);
#endif
- if (retn != NULL) {
#if defined(ARGUS_ALIGN_128)
+ if (retn != NULL) {
unsigned short toff;
toff = ((unsigned long)retn & (offset - 1));
toff = offset - toff;
retn = (void *)((char *)retn + toff);
((unsigned short *)retn)[-1] = toff;
-#endif
}
+#endif
}
#ifdef ARGUSDEBUG
ArgusDebug (6, "ArgusCalloc (%d, %d) returning 0x%x\n", nitems, bytes, retn);
#endif
- return ((void *) retn);
+ return (retn);
}
void
ArgusFree (void *buf)
@@ -1264,10 +1266,25 @@
ArgusDebug (6, "ArgusMallocListRecord (%d) returning 0x%x\n", length, retn);
#endif
return (retn);
}
+void ArgusShutdownRecordAllocator(void) {
+ struct ArgusMemoryHeader *crt, *rel;
+
+ if (ArgusMallocList != NULL) {
+ crt = ArgusMallocList->start;
+ while (crt != NULL) {
+ rel = crt;
+ crt = crt->nxt;
+ ArgusFree(rel);
+ }
+ ArgusFree(ArgusMallocList);
+ ArgusMallocList = NULL;
+ }
+}
+
void
ArgusFreeListRecord (void *buf)
{
struct ArgusMemoryHeader *mem = (struct ArgusMemoryHeader *)buf;
struct ArgusRecordStruct *rec = buf;
@@ -1280,27 +1297,30 @@
if (rec->dsrs[ARGUS_DSTUSERDATA_INDEX] != NULL) {
ArgusFree(rec->dsrs[ARGUS_DSTUSERDATA_INDEX]);
rec->dsrs[ARGUS_DSTUSERDATA_INDEX] = NULL;
}
- if ((ArgusMallocList == NULL) || (ArgusMallocList->count >= ARGUS_MEMORY_HI_THRESH)) {
+ if (ArgusMallocList == NULL)
ArgusFree(rec);
- ArgusMallocList->total--;
-
- } else {
- mem->nxt = NULL;
- if (ArgusMallocList->end)
- ArgusMallocList->end->nxt = mem;
+ else {
+ if (ArgusMallocList->count < ARGUS_MEMORY_HI_THRESH) {
+ mem->nxt = NULL;
+ if (ArgusMallocList->end != NULL)
+ ArgusMallocList->end->nxt = mem;
- ArgusMallocList->end = mem;
+ ArgusMallocList->end = mem;
- if (!(ArgusMallocList->start))
+ if (ArgusMallocList->start == NULL)
ArgusMallocList->start = mem;
- ArgusMallocList->count++;
+ ArgusMallocList->count++;
+ } else {
+ ArgusMallocList->total--;
+ ArgusFree(rec);
+ }
}
-
+
#ifdef ARGUSDEBUG
ArgusDebug (6, "ArgusFreeListRecord (0x%x) returning\n", buf);
#endif
return;
}
More information about the argus
mailing list