From bfeeaac6a68e6b25a7593ef8c4400585d7f9ed3a Mon Sep 17 00:00:00 2001 From: niels Date: Tue, 23 Jun 2015 23:46:21 +0200 Subject: [PATCH] fix leaks (on exit) in libOSC and vj-osc --- .../veejay-server/libOSC/OSC-address-space.c | 34 +++++-- .../veejay-server/libOSC/OSC-address-space.h | 3 +- .../veejay-server/libOSC/OSC-callbacklist.c | 11 ++- .../veejay-server/libOSC/OSC-callbacklist.h | 1 + .../veejay-server/libOSC/OSC-receive.c | 42 +++++++- .../veejay-server/libOSC/OSC-receive.h | 2 + veejay-current/veejay-server/veejay/vj-osc.c | 98 ++++++++++++++++--- 7 files changed, 160 insertions(+), 31 deletions(-) diff --git a/veejay-current/veejay-server/libOSC/OSC-address-space.c b/veejay-current/veejay-server/libOSC/OSC-address-space.c index 63437602..9506d18a 100644 --- a/veejay-current/veejay-server/libOSC/OSC-address-space.c +++ b/veejay-current/veejay-server/libOSC/OSC-address-space.c @@ -32,6 +32,7 @@ The OpenSound Control WWW page is Matt Wright, 3/16/98 */ #include +#include #include #include #include @@ -66,9 +67,11 @@ struct OSCMethodStruct { /* Globals */ static Boolean Initialized = FALSE; -static OSCcontainer OSCTopLevelContainer; -static OSCcontainer freeContainers; /* Linked list via next field. */ -static OSCMethod freeMethods; /* Linked list via next field. */ +static OSCcontainer OSCTopLevelContainer = 0; +static OSCcontainer freeContainers = 0; /* Linked list via next field. */ +static OSCcontainer safePtrFreeContainers = 0; +static OSCMethod freeMethods = 0; /* Linked list via next field. */ +static OSCMethod safePtrFreeMethods = 0; static void *(*RealTimeMemoryAllocator)(int numBytes); @@ -105,6 +108,18 @@ static void MakeFreeMethodsList(int n) { freeMethods[n-1].next = 0; } +void OSCDestroyAddressSpace() +{ + if( safePtrFreeContainers != 0) { + free( safePtrFreeContainers ); + safePtrFreeContainers = 0; + } + if( safePtrFreeMethods != 0 ) { + free( safePtrFreeMethods ); + safePtrFreeMethods = 0; + } +} + OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) { int bytesNeeded; @@ -116,8 +131,10 @@ OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) { bytesNeeded = (1 + t->initNumContainers) * sizeof(*freeContainers); freeContainers = (OSCcontainer) (*(t->InitTimeMemoryAllocator))(bytesNeeded); - if (freeContainers == 0) { - fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d containers", + safePtrFreeContainers = freeContainers; + + if (freeContainers == 0) { + fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d containers", bytesNeeded, t->initNumContainers); } @@ -130,6 +147,9 @@ OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) { fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d methods", bytesNeeded, t->initNumMethods); } + + safePtrFreeMethods = freeMethods; + MakeFreeMethodsList(t->initNumMethods); /* Initialize the top-level container */ @@ -179,8 +199,8 @@ static OSCMethod AllocMethod(void) { if (freeMethods != 0) { result = freeMethods; - freeMethods = freeMethods->next; - return result; + freeMethods = freeMethods->next; + return result; } OSCWarning("Out of memory for methods; trying to allocate more in real time"); diff --git a/veejay-current/veejay-server/libOSC/OSC-address-space.h b/veejay-current/veejay-server/libOSC/OSC-address-space.h index f25d623a..722b5370 100644 --- a/veejay-current/veejay-server/libOSC/OSC-address-space.h +++ b/veejay-current/veejay-server/libOSC/OSC-address-space.h @@ -361,4 +361,5 @@ main() { } */ - +void OSCDestroyAddressSpace(); + diff --git a/veejay-current/veejay-server/libOSC/OSC-callbacklist.c b/veejay-current/veejay-server/libOSC/OSC-callbacklist.c index 3193ae8f..99b16361 100644 --- a/veejay-current/veejay-server/libOSC/OSC-callbacklist.c +++ b/veejay-current/veejay-server/libOSC/OSC-callbacklist.c @@ -38,15 +38,15 @@ The OpenSound Control WWW page is */ - +#include #include #include #include #include #include -static callbackList allNodes; -static callbackList freeNodes; +static callbackList allNodes = NULL; +static callbackList freeNodes = NULL; /* Call this before you call anything else */ Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes)) { @@ -85,6 +85,11 @@ callbackList AllocCallbackListNode(methodCallback callback, void *context, return result; } +void OSCDestroyCallbackListNodes() +{ + if( allNodes ) + free( allNodes ); +} void FreeCallbackListNode(callbackList cb) { #ifdef DEBUG_CBL diff --git a/veejay-current/veejay-server/libOSC/OSC-callbacklist.h b/veejay-current/veejay-server/libOSC/OSC-callbacklist.h index 2e49fd24..4c292139 100644 --- a/veejay-current/veejay-server/libOSC/OSC-callbacklist.h +++ b/veejay-current/veejay-server/libOSC/OSC-callbacklist.h @@ -46,4 +46,5 @@ callbackList AllocCallbackListNode(methodCallback callback, void *context, void FreeCallbackListNode(callbackList); +void OSCDestroyCallbackListNodes(); diff --git a/veejay-current/veejay-server/libOSC/OSC-receive.c b/veejay-current/veejay-server/libOSC/OSC-receive.c index 216188f1..ada37657 100644 --- a/veejay-current/veejay-server/libOSC/OSC-receive.c +++ b/veejay-current/veejay-server/libOSC/OSC-receive.c @@ -160,8 +160,7 @@ Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t) { globals.lastTimeTag = OSCTT_Immediately(); globals.timePassed = TRUE; - if (InitPackets(t->receiveBufferSize, SizeOfNetworkReturnAddress(), - t->numReceiveBuffers) == FALSE) return FALSE; + if (InitPackets(t->receiveBufferSize, SizeOfNetworkReturnAddress(),t->numReceiveBuffers) == FALSE) return FALSE; if (InitQueuedData(t->numQueuedObjects) == FALSE) return FALSE; if (InitCallbackListNodes(t->numCallbackListNodes, t->InitTimeMemoryAllocator) == FALSE) return FALSE; @@ -174,7 +173,8 @@ Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t) { Managing packet data structures **************************************************/ -static struct OSCPacketBuffer_struct *freePackets; +static struct OSCPacketBuffer_struct *freePackets = 0; +static struct OSCPacketBuffer_struct *safePtrFreePackets = 0; #ifdef DEBUG_PACKET_MEM static void PrintPacketFreeList(void) { @@ -220,8 +220,10 @@ static Boolean InitPackets(int receiveBufferSize, int clientAddrSize, int numRec allPackets[i].nextFree = &(allPackets[i+1]); } + allPackets[numReceiveBuffers-1].nextFree = ((struct OSCPacketBuffer_struct *) 0); freePackets = allPackets; + safePtrFreePackets = allPackets; return TRUE; } @@ -295,7 +297,7 @@ void OSCFreePacket(OSCPacketBuffer p) { making the messages take effect. **************************************************/ -static queuedData *freeQDList; +static queuedData *freeQDList = NULL; #ifdef DEBUG_QD_MEM static void PrintQDFreeList(void) { @@ -311,6 +313,38 @@ static void PrintQDFreeList(void) { } #endif +void OSCDestroyDataQueues(int numReceiveBuffers) +{ + int i; + if( freeQDList ) { + free(freeQDList ); + freeQDList = 0; + } + + + + for (i = 0; i < numReceiveBuffers; ++i) { + + if( safePtrFreePackets[i].returnAddr ) + free( safePtrFreePackets[i].returnAddr ); + + if( safePtrFreePackets[i].buf ) + free( safePtrFreePackets[i].buf ); + } + + + if( safePtrFreePackets ) { + free( safePtrFreePackets ); + safePtrFreePackets = 0; + } + + if( globals.TheQueue ) { + free( globals.TheQueue ); + globals.TheQueue = 0; + } + +} + static Boolean InitQueuedData(int numQueuedObjects) { int i; queuedData *allQD; diff --git a/veejay-current/veejay-server/libOSC/OSC-receive.h b/veejay-current/veejay-server/libOSC/OSC-receive.h index d231390e..ab10c488 100644 --- a/veejay-current/veejay-server/libOSC/OSC-receive.h +++ b/veejay-current/veejay-server/libOSC/OSC-receive.h @@ -210,6 +210,8 @@ void GoMultiCast(const char *groupname); int IsMultiCast( char *dst); +void OSCDestroyDataQueues(int nReceiveBuffers); + /************************************************** How to use this stuff **************************************************/ diff --git a/veejay-current/veejay-server/veejay/vj-osc.c b/veejay-current/veejay-server/veejay/vj-osc.c index bb3f4444..c9bcec88 100644 --- a/veejay-current/veejay-server/veejay/vj-osc.c +++ b/veejay-current/veejay-server/veejay/vj-osc.c @@ -61,12 +61,20 @@ static vevo_port_t **osc_clients = NULL; #include #include +#define NUM_RECEIVE_BUFFERS 100 + typedef struct osc_arg_t { int a; int b; int c; } osc_arg; +typedef struct osc_tokens_t { + char **addr; + int n_addr; + char *descr; /* keep track of all pointers */ +} osc_tokens; + typedef struct vj_osc_t { struct OSCAddressSpaceMemoryTuner t; struct OSCReceiveMemoryTuner rt; @@ -82,6 +90,8 @@ typedef struct vj_osc_t { osc_arg *osc_args; void *index; void *clients; + osc_tokens **addr; + int n_addr; } vj_osc; @@ -94,6 +104,7 @@ extern char *vj_event_vevo_get_event_name( int id ); #define OPUSH(p) { _old_p_mode = osc_info->uc->playback_mode; osc_info->uc->playback_mode = p; } #define OPOP() { osc_info->uc->playback_mode = _old_p_mode; } +static void free_token( char **arr ); void vj_osc_set_veejay_t(veejay_t *t); @@ -213,11 +224,33 @@ void vj_osc_free(void *d) { if(!d) return; vj_osc *c = (vj_osc*) d; - void *addr = OSCPacketBufferGetClientAddr(c->packet ); - if(addr) - free(addr); - //if(c->osc_args) free(c->osc_args); - if(c->leaves) free(c->leaves); + +// void *addr = OSCPacketBufferGetClientAddr(c->packet ); +// if(addr) +// free(addr); + + OSCDestroyCallbackListNodes(); + OSCDestroyDataQueues(NUM_RECEIVE_BUFFERS); + OSCDestroyAddressSpace(); + + int i; + for ( i = 0; i < c->n_addr; i ++ ) { + osc_tokens *ot = c->addr[i]; + if(ot == NULL) + continue; + if( ot->addr ) { + free_token( ot->addr ); + } + if( ot->descr ) { + free(ot->descr); + } + free(ot); + } + free(c->addr); + + + if(c->leaves) + free(c->leaves); if(c->index) vevo_port_recursive_free( c->index ); if(c) free(c); @@ -672,13 +705,14 @@ static void free_token( char **arr ) { int i = 0; for( i = 0; arr[i] != NULL ; i ++ ) { free(arr[i]); - arr[i] = NULL; } free(arr); arr = NULL; } +#define MAX_ADDR 1024 + int vj_osc_build_cont( vj_osc *o ) //FIXME never freed { int i; @@ -689,9 +723,17 @@ int vj_osc_build_cont( vj_osc *o ) //FIXME never freed int err = 0; int t = 0; - for( i = 0; osc_method_layout[i].name != NULL ; i ++ ) { + int len = 1; + while ( osc_method_layout[len].name != NULL ) + len ++; + + o->addr = (osc_tokens**) vj_calloc (sizeof(osc_tokens*) * MAX_ADDR ); + o->n_addr = 0; + + int next_addr = 0; + + for( i = 0; osc_method_layout[i].name != NULL && next_addr < MAX_ADDR; i ++ ) { int ntokens = 0; - //FIXME: arr never freed but should be, leaking memory here char **arr = string_tokenize( '/', osc_method_layout[i].name, &ntokens); if( arr == NULL || ntokens == 0 ) { continue; @@ -703,21 +745,31 @@ int vj_osc_build_cont( vj_osc *o ) //FIXME never freed continue; } o->leaves[next_id] = OSCNewContainer( arr[0], o->container, &(o->cqinfo) ); + + o->addr[next_addr] = vj_calloc(sizeof(osc_tokens)); + o->addr[next_addr]->n_addr = ntokens; + o->addr[next_addr]->addr = arr; + err = vevo_property_set(o->index, arr[0], VEVO_ATOM_TYPE_INT , 1, &next_id); next_id ++; + next_addr ++; } - for( i = 0; osc_method_layout[i].name != NULL ; i ++ ) { + for( i = 0; osc_method_layout[i].name != NULL && next_addr < MAX_ADDR ; i ++ ) { int ntokens = 0; int exists = 0; int attach_id = 0; - //FIXME: arr never freed but should be, leaking memory here char **arr = string_tokenize( '/', osc_method_layout[i].name, &ntokens); if( arr == NULL || ntokens == 0 ) { continue; } int containers = ntokens - 1; + o->addr[next_addr] = vj_calloc(sizeof(osc_tokens)); + o->addr[next_addr]->n_addr = ntokens; + o->addr[next_addr]->addr = arr; + + for( t = 1; t < containers; t ++ ) { int is_method = (t == (containers-1)) ? 1: 0; if( is_method ) @@ -739,10 +791,13 @@ int vj_osc_build_cont( vj_osc *o ) //FIXME never freed //veejay_msg(0, "Added leave '%s'%d to container '%s'%d", arr[t],next_id-1,arr[t-1],attach_id); } - } + + next_addr ++; + + } - for( i = 0; osc_method_layout[i].name != NULL ; i ++ ) { + for( i = 0; osc_method_layout[i].name != NULL && next_id < MAX_ADDR; i ++ ) { int ntokens = 0; /* * arr is never freed; the OSCNewMethod copies the pointer to elements in arr @@ -755,9 +810,13 @@ int vj_osc_build_cont( vj_osc *o ) //FIXME never freed free_token(arr); continue; } - + int method = containers - 1; + o->addr[next_addr] = vj_calloc(sizeof(osc_tokens)); + o->addr[next_addr]->n_addr = ntokens; + o->addr[next_addr]->addr = arr; + err = vevo_property_get( o->index, arr[method-1], 0, &leave_id ); #ifdef HAVE_LIBLO if( osc_method_layout[i].vims_id == -2 ) { @@ -777,8 +836,15 @@ int vj_osc_build_cont( vj_osc *o ) //FIXME never freed OSCNewMethod( arr[ method ], o->leaves[ leave_id ], osc_vims_method, &(osc_method_layout[i].vims_id),&(o->ris)); #endif + + o->addr[next_addr]->descr = o->ris.description; + + next_addr ++; } + veejay_msg(0, "OSC: %d", next_addr ); + o->n_addr = next_addr; + return 1; } @@ -798,7 +864,7 @@ void* vj_osc_allocate(int port_id) { o->rt.InitTimeMemoryAllocator = _vj_osc_time_malloc; o->rt.RealTimeMemoryAllocator = _vj_osc_rt_malloc; o->rt.receiveBufferSize = 1024; - o->rt.numReceiveBuffers = 100; + o->rt.numReceiveBuffers = NUM_RECEIVE_BUFFERS; o->rt.numQueuedObjects = 100; o->rt.numCallbackListNodes = 300; o->leaves = (OSCcontainer*) vj_malloc(sizeof(OSCcontainer) * 300); @@ -863,11 +929,11 @@ void vj_osc_dump() /* dump the OSC address space to screen */ int vj_osc_setup_addr_space(void *d) { - char addr[100]; + char addr[255]; vj_osc *o = (vj_osc*) d; //struct OSCMethodQueryResponseInfoStruct qri; - if(OSCGetAddressString( addr, 100, o->container ) == FALSE) { + if(OSCGetAddressString( addr, 255, o->container ) == FALSE) { veejay_msg(VEEJAY_MSG_ERROR, "Cannot get address space of OSC"); return -1; }