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
*/
#include <config.h>
#include <stdlib.h>
#include <libOSC/OSC-common.h>
#include <libOSC/OSC-timetag.h>
#include <libOSC/OSC-address-space.h>
@@ -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");

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-timetag.h>
#include <libOSC/OSC-address-space.h>
#include <libOSC/OSC-dispatch.h>
#include <libOSC/OSC-callbacklist.h>
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

View File

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

View File

@@ -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;

View File

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

View File

@@ -61,12 +61,20 @@ static vevo_port_t **osc_clients = NULL;
#include <libvevo/vevo.h>
#include <libvevo/libvevo.h>
#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;
}