From ddcc2af3adab158592f195aa6b9e9d73be3f37a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 29 Mar 2010 13:37:29 +0000 Subject: sender/receiver dtors can now be called recursively without double freeing resources (hopefully) svn path=/trunk/externals/iem/iemnet/; revision=13299 --- iemnet.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) (limited to 'iemnet.c') diff --git a/iemnet.c b/iemnet.c index 76f48e6..1d44144 100644 --- a/iemnet.c +++ b/iemnet.c @@ -372,7 +372,7 @@ struct _iemnet_sender { int sockfd; /* owned outside; must call iemnet__sender_destroy() before freeing socket yourself */ t_queue*queue; - int cont; // indicates whether we want to thread to continue or to terminate + int keepsending; // indicates whether we want to thread to continue or to terminate }; /* the workhorse of the family */ @@ -400,7 +400,7 @@ static void*iemnet__sender_sendthread(void*arg) { int sockfd=sender->sockfd; t_queue*q=sender->queue; - while(sender->cont) { + while(sender->keepsending) { if(!iemnet__sender_dosend(sockfd, q))break; } //fprintf(stderr, "write thread terminated\n"); @@ -418,8 +418,14 @@ int iemnet__sender_send(t_iemnet_sender*s, t_iemnet_chunk*c) { } void iemnet__sender_destroy(t_iemnet_sender*s) { + /* simple protection against recursive calls: + * s->keepsending is only set to "0" in here, + * so if it is false, we know that we are already being called + */ + if(!s->keepsending)return; + DEBUG("destroy sender %x", s); - s->cont=0; + s->keepsending=0; queue_finish(s->queue); DEBUG("queue finished"); s->sockfd = -1; @@ -441,7 +447,7 @@ t_iemnet_sender*iemnet__sender_create(int sock) { result->queue = queue_create(); result->sockfd = sock; - result->cont =1; + result->keepsending =1; res=pthread_create(&result->thread, 0, iemnet__sender_sendthread, result); @@ -493,6 +499,8 @@ struct _iemnet_receiver { t_clock *clock; t_iemnet_floatlist*flist; + int keepreceiving; + int newdataflag; pthread_mutex_t newdatamtx; }; @@ -574,7 +582,10 @@ static void iemnet__receiver_tick(t_iemnet_receiver *x) if(!x->running) { // read terminated - x->callback(x->userdata, NULL, 0, NULL); + + /* keepreceiving is set, if receiver is not yet in shutdown mode */ + if(x->keepreceiving) + x->callback(x->userdata, NULL, 0, NULL); } } @@ -592,6 +603,7 @@ t_iemnet_receiver*iemnet__receiver_create(int sock, void*userdata, t_iemnet_rece DEBUG("create receiver failed"); return NULL; } + rec->keepreceiving=1; rec->sockfd=sock; rec->userdata=userdata; rec->data=data; @@ -611,17 +623,34 @@ t_iemnet_receiver*iemnet__receiver_create(int sock, void*userdata, t_iemnet_rece return rec; } void iemnet__receiver_destroy(t_iemnet_receiver*rec) { + static int instance=0; + int inst=instance++; + int sockfd; - DEBUG("destroy receiver %x", rec); + DEBUG("[%d] destroy receiver %x", inst, rec); if(NULL==rec)return; + if(!rec->keepreceiving)return; + rec->keepreceiving=0; + + sockfd=rec->sockfd; rec->sockfd=-1; - shutdown(sockfd, 2); /* needed on linux, since the recv won't shutdown on sys_closesocket() alone */ - sys_closesocket(sockfd); + DEBUG("[%d] really destroying receiver %x -> %d", inst, rec, sockfd); + + if(sockfd>=0) { + shutdown(sockfd, 2); /* needed on linux, since the recv won't shutdown on sys_closesocket() alone */ + sys_closesocket(sockfd); + } + DEBUG("[%d] closed socket %d", inst, sockfd); pthread_join(rec->thread, NULL); + + + // empty the queue + DEBUG("[%d] tick %d", inst, rec->running); iemnet__receiver_tick(rec); + DEBUG("[%d] tack", inst); if(rec->data)iemnet__chunk_destroy(rec->data); if(rec->flist)iemnet__floatlist_destroy(rec->flist); @@ -638,7 +667,7 @@ void iemnet__receiver_destroy(t_iemnet_receiver*rec) { freebytes(rec, sizeof(t_iemnet_receiver)); rec=NULL; - DEBUG("destroyed receiver"); + DEBUG("[%d] destroyed receiver", inst); } -- cgit v1.2.1