fix leaks (on exit) in libOSC and vj-osc

This commit is contained in:
niels
2015-06-23 23:46:21 +02:00
parent c1dabda949
commit bfeeaac6a6
7 changed files with 160 additions and 31 deletions

View File

@@ -32,6 +32,7 @@ The OpenSound Control WWW page is
Matt Wright, 3/16/98 Matt Wright, 3/16/98
*/ */
#include <config.h> #include <config.h>
#include <stdlib.h>
#include <libOSC/OSC-common.h> #include <libOSC/OSC-common.h>
#include <libOSC/OSC-timetag.h> #include <libOSC/OSC-timetag.h>
#include <libOSC/OSC-address-space.h> #include <libOSC/OSC-address-space.h>
@@ -66,9 +67,11 @@ struct OSCMethodStruct {
/* Globals */ /* Globals */
static Boolean Initialized = FALSE; static Boolean Initialized = FALSE;
static OSCcontainer OSCTopLevelContainer; static OSCcontainer OSCTopLevelContainer = 0;
static OSCcontainer freeContainers; /* Linked list via next field. */ static OSCcontainer freeContainers = 0; /* Linked list via next field. */
static OSCMethod freeMethods; /* 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); static void *(*RealTimeMemoryAllocator)(int numBytes);
@@ -105,6 +108,18 @@ static void MakeFreeMethodsList(int n) {
freeMethods[n-1].next = 0; 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) { OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) {
int bytesNeeded; int bytesNeeded;
@@ -116,8 +131,10 @@ OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) {
bytesNeeded = (1 + t->initNumContainers) * sizeof(*freeContainers); bytesNeeded = (1 + t->initNumContainers) * sizeof(*freeContainers);
freeContainers = (OSCcontainer) (*(t->InitTimeMemoryAllocator))(bytesNeeded); freeContainers = (OSCcontainer) (*(t->InitTimeMemoryAllocator))(bytesNeeded);
if (freeContainers == 0) { safePtrFreeContainers = freeContainers;
fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d containers",
if (freeContainers == 0) {
fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d containers",
bytesNeeded, t->initNumContainers); bytesNeeded, t->initNumContainers);
} }
@@ -130,6 +147,9 @@ OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) {
fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d methods", fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d methods",
bytesNeeded, t->initNumMethods); bytesNeeded, t->initNumMethods);
} }
safePtrFreeMethods = freeMethods;
MakeFreeMethodsList(t->initNumMethods); MakeFreeMethodsList(t->initNumMethods);
/* Initialize the top-level container */ /* Initialize the top-level container */
@@ -179,8 +199,8 @@ static OSCMethod AllocMethod(void) {
if (freeMethods != 0) { if (freeMethods != 0) {
result = freeMethods; result = freeMethods;
freeMethods = freeMethods->next; freeMethods = freeMethods->next;
return result; return result;
} }
OSCWarning("Out of memory for methods; trying to allocate more in real time"); OSCWarning("Out of memory for methods; trying to allocate more in real time");

View File

@@ -361,4 +361,5 @@ main() {
} }
*/ */
void OSCDestroyAddressSpace();

View File

@@ -38,15 +38,15 @@ The OpenSound Control WWW page is
*/ */
#include <stdlib.h>
#include <libOSC/OSC-common.h> #include <libOSC/OSC-common.h>
#include <libOSC/OSC-timetag.h> #include <libOSC/OSC-timetag.h>
#include <libOSC/OSC-address-space.h> #include <libOSC/OSC-address-space.h>
#include <libOSC/OSC-dispatch.h> #include <libOSC/OSC-dispatch.h>
#include <libOSC/OSC-callbacklist.h> #include <libOSC/OSC-callbacklist.h>
static callbackList allNodes; static callbackList allNodes = NULL;
static callbackList freeNodes; static callbackList freeNodes = NULL;
/* Call this before you call anything else */ /* Call this before you call anything else */
Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes)) { Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes)) {
@@ -85,6 +85,11 @@ callbackList AllocCallbackListNode(methodCallback callback, void *context,
return result; return result;
} }
void OSCDestroyCallbackListNodes()
{
if( allNodes )
free( allNodes );
}
void FreeCallbackListNode(callbackList cb) { void FreeCallbackListNode(callbackList cb) {
#ifdef DEBUG_CBL #ifdef DEBUG_CBL

View File

@@ -46,4 +46,5 @@ callbackList AllocCallbackListNode(methodCallback callback, void *context,
void FreeCallbackListNode(callbackList); void FreeCallbackListNode(callbackList);
void OSCDestroyCallbackListNodes();

View File

@@ -160,8 +160,7 @@ Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t) {
globals.lastTimeTag = OSCTT_Immediately(); globals.lastTimeTag = OSCTT_Immediately();
globals.timePassed = TRUE; globals.timePassed = TRUE;
if (InitPackets(t->receiveBufferSize, SizeOfNetworkReturnAddress(), if (InitPackets(t->receiveBufferSize, SizeOfNetworkReturnAddress(),t->numReceiveBuffers) == FALSE) return FALSE;
t->numReceiveBuffers) == FALSE) return FALSE;
if (InitQueuedData(t->numQueuedObjects) == FALSE) return FALSE; if (InitQueuedData(t->numQueuedObjects) == FALSE) return FALSE;
if (InitCallbackListNodes(t->numCallbackListNodes, t->InitTimeMemoryAllocator) if (InitCallbackListNodes(t->numCallbackListNodes, t->InitTimeMemoryAllocator)
== FALSE) return FALSE; == FALSE) return FALSE;
@@ -174,7 +173,8 @@ Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t) {
Managing packet data structures 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 #ifdef DEBUG_PACKET_MEM
static void PrintPacketFreeList(void) { static void PrintPacketFreeList(void) {
@@ -220,8 +220,10 @@ static Boolean InitPackets(int receiveBufferSize, int clientAddrSize, int numRec
allPackets[i].nextFree = &(allPackets[i+1]); allPackets[i].nextFree = &(allPackets[i+1]);
} }
allPackets[numReceiveBuffers-1].nextFree = ((struct OSCPacketBuffer_struct *) 0); allPackets[numReceiveBuffers-1].nextFree = ((struct OSCPacketBuffer_struct *) 0);
freePackets = allPackets; freePackets = allPackets;
safePtrFreePackets = allPackets;
return TRUE; return TRUE;
} }
@@ -295,7 +297,7 @@ void OSCFreePacket(OSCPacketBuffer p) {
making the messages take effect. making the messages take effect.
**************************************************/ **************************************************/
static queuedData *freeQDList; static queuedData *freeQDList = NULL;
#ifdef DEBUG_QD_MEM #ifdef DEBUG_QD_MEM
static void PrintQDFreeList(void) { static void PrintQDFreeList(void) {
@@ -311,6 +313,38 @@ static void PrintQDFreeList(void) {
} }
#endif #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) { static Boolean InitQueuedData(int numQueuedObjects) {
int i; int i;
queuedData *allQD; queuedData *allQD;

View File

@@ -210,6 +210,8 @@ void GoMultiCast(const char *groupname);
int IsMultiCast( char *dst); int IsMultiCast( char *dst);
void OSCDestroyDataQueues(int nReceiveBuffers);
/************************************************** /**************************************************
How to use this stuff How to use this stuff
**************************************************/ **************************************************/

View File

@@ -61,12 +61,20 @@ static vevo_port_t **osc_clients = NULL;
#include <libvevo/vevo.h> #include <libvevo/vevo.h>
#include <libvevo/libvevo.h> #include <libvevo/libvevo.h>
#define NUM_RECEIVE_BUFFERS 100
typedef struct osc_arg_t { typedef struct osc_arg_t {
int a; int a;
int b; int b;
int c; int c;
} osc_arg; } 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 { typedef struct vj_osc_t {
struct OSCAddressSpaceMemoryTuner t; struct OSCAddressSpaceMemoryTuner t;
struct OSCReceiveMemoryTuner rt; struct OSCReceiveMemoryTuner rt;
@@ -82,6 +90,8 @@ typedef struct vj_osc_t {
osc_arg *osc_args; osc_arg *osc_args;
void *index; void *index;
void *clients; void *clients;
osc_tokens **addr;
int n_addr;
} vj_osc; } 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 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; } #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); void vj_osc_set_veejay_t(veejay_t *t);
@@ -213,11 +224,33 @@ void vj_osc_free(void *d)
{ {
if(!d) return; if(!d) return;
vj_osc *c = (vj_osc*) d; vj_osc *c = (vj_osc*) d;
void *addr = OSCPacketBufferGetClientAddr(c->packet );
if(addr) // void *addr = OSCPacketBufferGetClientAddr(c->packet );
free(addr); // if(addr)
//if(c->osc_args) free(c->osc_args); // free(addr);
if(c->leaves) free(c->leaves);
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) if(c->index)
vevo_port_recursive_free( c->index ); vevo_port_recursive_free( c->index );
if(c) free(c); if(c) free(c);
@@ -672,13 +705,14 @@ static void free_token( char **arr ) {
int i = 0; int i = 0;
for( i = 0; arr[i] != NULL ; i ++ ) { for( i = 0; arr[i] != NULL ; i ++ ) {
free(arr[i]); free(arr[i]);
arr[i] = NULL;
} }
free(arr); free(arr);
arr = NULL; arr = NULL;
} }
#define MAX_ADDR 1024
int vj_osc_build_cont( vj_osc *o ) //FIXME never freed int vj_osc_build_cont( vj_osc *o ) //FIXME never freed
{ {
int i; int i;
@@ -689,9 +723,17 @@ int vj_osc_build_cont( vj_osc *o ) //FIXME never freed
int err = 0; int err = 0;
int t = 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; int ntokens = 0;
//FIXME: arr never freed but should be, leaking memory here
char **arr = string_tokenize( '/', osc_method_layout[i].name, &ntokens); char **arr = string_tokenize( '/', osc_method_layout[i].name, &ntokens);
if( arr == NULL || ntokens == 0 ) { if( arr == NULL || ntokens == 0 ) {
continue; continue;
@@ -703,21 +745,31 @@ int vj_osc_build_cont( vj_osc *o ) //FIXME never freed
continue; continue;
} }
o->leaves[next_id] = OSCNewContainer( arr[0], o->container, &(o->cqinfo) ); 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); err = vevo_property_set(o->index, arr[0], VEVO_ATOM_TYPE_INT , 1, &next_id);
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 ntokens = 0;
int exists = 0; int exists = 0;
int attach_id = 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); char **arr = string_tokenize( '/', osc_method_layout[i].name, &ntokens);
if( arr == NULL || ntokens == 0 ) { if( arr == NULL || ntokens == 0 ) {
continue; continue;
} }
int containers = ntokens - 1; 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 ++ ) { for( t = 1; t < containers; t ++ ) {
int is_method = (t == (containers-1)) ? 1: 0; int is_method = (t == (containers-1)) ? 1: 0;
if( is_method ) 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); //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; int ntokens = 0;
/* /*
* arr is never freed; the OSCNewMethod copies the pointer to elements in arr * 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); free_token(arr);
continue; continue;
} }
int method = containers - 1; 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 ); err = vevo_property_get( o->index, arr[method-1], 0, &leave_id );
#ifdef HAVE_LIBLO #ifdef HAVE_LIBLO
if( osc_method_layout[i].vims_id == -2 ) { 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)); OSCNewMethod( arr[ method ], o->leaves[ leave_id ], osc_vims_method, &(osc_method_layout[i].vims_id),&(o->ris));
#endif #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; return 1;
} }
@@ -798,7 +864,7 @@ void* vj_osc_allocate(int port_id) {
o->rt.InitTimeMemoryAllocator = _vj_osc_time_malloc; o->rt.InitTimeMemoryAllocator = _vj_osc_time_malloc;
o->rt.RealTimeMemoryAllocator = _vj_osc_rt_malloc; o->rt.RealTimeMemoryAllocator = _vj_osc_rt_malloc;
o->rt.receiveBufferSize = 1024; o->rt.receiveBufferSize = 1024;
o->rt.numReceiveBuffers = 100; o->rt.numReceiveBuffers = NUM_RECEIVE_BUFFERS;
o->rt.numQueuedObjects = 100; o->rt.numQueuedObjects = 100;
o->rt.numCallbackListNodes = 300; o->rt.numCallbackListNodes = 300;
o->leaves = (OSCcontainer*) vj_malloc(sizeof(OSCcontainer) * 300); o->leaves = (OSCcontainer*) vj_malloc(sizeof(OSCcontainer) * 300);
@@ -863,11 +929,11 @@ void vj_osc_dump()
/* dump the OSC address space to screen */ /* dump the OSC address space to screen */
int vj_osc_setup_addr_space(void *d) { int vj_osc_setup_addr_space(void *d) {
char addr[100]; char addr[255];
vj_osc *o = (vj_osc*) d; vj_osc *o = (vj_osc*) d;
//struct OSCMethodQueryResponseInfoStruct qri; //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"); veejay_msg(VEEJAY_MSG_ERROR, "Cannot get address space of OSC");
return -1; return -1;
} }