r3132 - in trunk/libmsip: include/libmsip source

erik at minisip.org erik at minisip.org
Sat Jan 20 17:41:03 CET 2007


Author: erik
Date: 2007-01-20 17:41:03 +0100 (Sat, 20 Jan 2007)
New Revision: 3132

Modified:
   trunk/libmsip/include/libmsip/SipCommandDispatcher.h
   trunk/libmsip/include/libmsip/SipCommandString.h
   trunk/libmsip/include/libmsip/SipLayerTransport.h
   trunk/libmsip/include/libmsip/SipStackInternal.h
   trunk/libmsip/source/SipCommandDispatcher.cxx
   trunk/libmsip/source/SipCommandString.cxx
   trunk/libmsip/source/SipLayerTransport.cxx
   trunk/libmsip/source/SipSocketServer.cxx
   trunk/libmsip/source/SipStack.cxx
   trunk/libmsip/source/SipStackInternal.cxx
Log:

 * Fix memory leak in SipStack (loops prevented objects from being freed when
   deleteing a SipStack)
    - Stop threads
    - Break reference loops



Modified: trunk/libmsip/include/libmsip/SipCommandDispatcher.h
===================================================================
--- trunk/libmsip/include/libmsip/SipCommandDispatcher.h	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/include/libmsip/SipCommandDispatcher.h	2007-01-20 16:41:03 UTC (rev 3132)
@@ -65,6 +65,8 @@
 	public:
 		SipCommandDispatcher(MRef<SipStackInternal*> stack, MRef<SipLayerTransport*> transport);
 
+		void free();
+
 		void setCallback(MRef<CommandReceiver*> cb);
 		MRef<CommandReceiver*> getCallback();
 		

Modified: trunk/libmsip/include/libmsip/SipCommandString.h
===================================================================
--- trunk/libmsip/include/libmsip/SipCommandString.h	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/include/libmsip/SipCommandString.h	2007-01-20 16:41:03 UTC (rev 3132)
@@ -41,6 +41,7 @@
 		*/
 		static const std::string sip_stack_shutdown;
 		static const std::string sip_stack_shutdown_done;
+		static const std::string no_op;
 		static const std::string register_all_identities;
 		static const std::string register_all_identities_done;
 		static const std::string unregister_all_identities;

Modified: trunk/libmsip/include/libmsip/SipLayerTransport.h
===================================================================
--- trunk/libmsip/include/libmsip/SipLayerTransport.h	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/include/libmsip/SipLayerTransport.h	2007-01-20 16:41:03 UTC (rev 3132)
@@ -32,7 +32,6 @@
 #include<libmnetutil/DatagramSocket.h>
 #include<libmnetutil/StreamSocket.h>
 #include<libmutil/Mutex.h>
-#include<libmutil/Thread.h>
 #include<libmutil/Semaphore.h>
 #include<libmutil/MemObject.h>
 #include<libmcrypto/cert.h>
@@ -46,6 +45,7 @@
 
 class SipLayerTransport;
 class SipCommandDispatcher;
+class StreamThreadData;
 
 class SipLayerTransport : public SipSMCommandReceiver {
 	public:
@@ -117,6 +117,7 @@
                 
 		Mutex serversLock;
 		std::list<MRef<SipSocketServer *> > servers;
+		std::list<MRef<StreamThreadData *> > workers;
 
 		Mutex socksLock;
 		std::list<MRef<StreamSocket *> > socks;

Modified: trunk/libmsip/include/libmsip/SipStackInternal.h
===================================================================
--- trunk/libmsip/include/libmsip/SipStackInternal.h	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/include/libmsip/SipStackInternal.h	2007-01-20 16:41:03 UTC (rev 3132)
@@ -94,6 +94,8 @@
 		void startTcpServer();
 		void startTlsServer();
 
+		void free();
+
 	private:
 
 //		std::string getDialogDebugString(MRef<SipDialog*> d, list<MRef<SipTransaction*> > &trans,

Modified: trunk/libmsip/source/SipCommandDispatcher.cxx
===================================================================
--- trunk/libmsip/source/SipCommandDispatcher.cxx	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/source/SipCommandDispatcher.cxx	2007-01-20 16:41:03 UTC (rev 3132)
@@ -50,6 +50,16 @@
 
 }
 
+void SipCommandDispatcher::free(){
+	sipStackInternal=NULL;
+	callback=NULL;
+	managementHandler=NULL;
+	transportLayer->setDispatcher(NULL);
+	transportLayer=NULL;
+	dialogLayer=NULL;
+	transactionLayer=NULL;
+}
+
 void SipCommandDispatcher::setDialogManagement(MRef<SipDialog*> mgmt){
 	managementHandler = mgmt;
 }
@@ -63,6 +73,17 @@
 
 void SipCommandDispatcher::stopRunning(){
 	keepRunning=false;
+
+	transportLayer->stop();
+
+	//The SIP stack is blocking on a semaphore waiting for
+	//something to process. We wake it by sending it a
+	//no-operation command. It will then check
+	//the "keepRunning" flag and exit
+	CommandString c("",SipCommandString::no_op);
+	SipSMCommand sc(c, SipSMCommand::dispatcher, SipSMCommand::dispatcher);
+	enqueueCommand(sc, LOW_PRIO_QUEUE);
+
 }
 
 list<MRef<SipDialog *> > SipCommandDispatcher::getDialogs(){
@@ -120,7 +141,7 @@
 #endif
 		
 		if (item.type == TYPE_COMMAND){
-		
+
 			handled=handleCommand(**(item.command));
 			
 		}else{  // item.type == TYPE_TIMEOUT
@@ -278,6 +299,9 @@
 bool SipCommandDispatcher::maintainenceHandleCommand(const SipSMCommand &c){
 
 	if (c.getType()==SipSMCommand::COMMAND_STRING){	
+		if (c.getCommandString().getOp()==SipCommandString::no_op){
+			return true;
+		}
 
 		if (c.getCommandString().getOp()==SipCommandString::transaction_terminated){
 			transactionLayer->removeTerminatedTransactions();

Modified: trunk/libmsip/source/SipCommandString.cxx
===================================================================
--- trunk/libmsip/source/SipCommandString.cxx	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/source/SipCommandString.cxx	2007-01-20 16:41:03 UTC (rev 3132)
@@ -28,6 +28,7 @@
 
 const string SipCommandString::sip_stack_shutdown="sip_stack_shutdown";
 const string SipCommandString::sip_stack_shutdown_done="sip_stack_shutdown_done";
+const string SipCommandString::no_op="no_op";
 const string SipCommandString::register_all_identities="register_all_identities";
 const string SipCommandString::register_all_identities_done="register_all_identities_done";
 const string SipCommandString::unregister_all_identities="unregister_all_identities";

Modified: trunk/libmsip/source/SipLayerTransport.cxx
===================================================================
--- trunk/libmsip/source/SipLayerTransport.cxx	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/source/SipLayerTransport.cxx	2007-01-20 16:41:03 UTC (rev 3132)
@@ -269,20 +269,46 @@
 	return 0;
 }
 
-class StreamThreadData{
+class StreamThreadData : public MObject{
 	public:
 		StreamThreadData( MRef<SipLayerTransport *> );
+		void run();
+		void stop();
+		void join();
+		void streamSocketRead( MRef<StreamSocket *> socket );
+	private:
 		SipMessageParser parser;
 		MRef<SipLayerTransport  *> transport;
-		void run();
-		void streamSocketRead( MRef<StreamSocket *> socket );
+		bool doStop;
+		ThreadHandle th;
 };
 
+static void * streamThread( void * arg ){
+	StreamThreadData * data;
+	data = (StreamThreadData *)arg;
+
+		// We want to keep a reference to the object so that it
+		// exist (at least) until we exit this function.
+	MRef<StreamThreadData *> ref=data;
+
+	ref->run();
+	return NULL;
+}
+
 StreamThreadData::StreamThreadData( MRef<SipLayerTransport *> transport){
+	doStop=false;
 	this->transport = transport;
+	cerr << "Creating thread"<<endl;
+	th=Thread::createThread(streamThread, this);
+	cerr << "threadhandle is as long int: "<<th.asLongInt()<<endl;
 }
 
+void StreamThreadData::join(){
+	cerr << "threadhandle is as long int: "<<th.asLongInt()<<endl;
+	Thread::join(th);
+}
 
+
 bool sipdebug_print_packets=false;
 
 void set_debug_print_packets(bool f){
@@ -333,7 +359,8 @@
 	int i;
 
 	for( i=0; i < NB_THREADS ; i++ ){
-            Thread::createThread(streamThread, new StreamThreadData(this));
+		StreamThreadData *worker = new StreamThreadData(this);
+		workers.push_back(worker);
 	}
 }
 
@@ -361,13 +388,36 @@
   
 void SipLayerTransport::stop(){
 	serversLock.lock();
+	list<MRef<StreamThreadData*> >::iterator j;
+
+
+	for( j=workers.begin(); j != workers.end(); j++ ){
+		MRef<StreamThreadData*> w = *j;
+		w->stop();
+	}
+
 	list<MRef<SipSocketServer *> >::iterator i;
-
 	for( i=servers.begin(); i != servers.end(); i++ ){
 		MRef<SipSocketServer *> server = *i;
 
 		server->stop();
+		*i=NULL;
 	}
+
+		//wake up blocking threads
+	int n;
+	for (n=0; n< NB_THREADS; n++){
+		semaphore.inc();
+	}
+
+	for( j=workers.begin(); j != workers.end(); j++ ){
+		MRef<StreamThreadData*> w = *j;
+		w->join();
+		*j=NULL;
+	}
+
+	workers.clear();
+	servers.clear();
 	serversLock.unlock();
 }
 
@@ -1067,25 +1117,38 @@
 		} // if event
 }
 
+void StreamThreadData::stop(){
+	doStop=true;
+	transport=NULL;
+}
+
 void StreamThreadData::run(){
-	while(true){
+	while(!doStop){
 
 		MRef<StreamSocket *> socket;
-                transport->semaphore.dec();
+		
+			//Keep a local reference of transport so that
+			//it is not deleted until we are done with it.
+		MRef<SipLayerTransport*> transp = transport;
+		if (!transp)
+			break;
+                transp->semaphore.dec();
+		if (doStop)
+			break;
                 
 		/* Take the last socket pending to be read */
-		transport->socksPendingLock.lock();
-		socket = transport->socksPending.front();
-		transport->socksPending.pop_front();
-		transport->socksPendingLock.unlock();
+		transp->socksPendingLock.lock();
+		socket = transp->socksPending.front();
+		transp->socksPending.pop_front();
+		transp->socksPendingLock.unlock();
                 
 		/* Read from it until it gets closed */
 		streamSocketRead( socket );
 
 		/* The socket was closed */
-		transport->socksLock.lock();
-		transport->socks.remove( socket );
-		transport->socksLock.unlock();
+		transp->socksLock.lock();
+		transp->socks.remove( socket );
+		transp->socksLock.unlock();
 #ifdef DEBUG_OUTPUT
 		mdbg << "StreamSocket closed" << end;
 #endif
@@ -1104,7 +1167,7 @@
 	int avail;
 	MRef<SipMessage*> pack;
 
-	while( true ){
+	while( !doStop){
 		fd_set set;
 
 		do{
@@ -1203,11 +1266,5 @@
 	}// while true
 }
 
-static void * streamThread( void * arg ){
-	StreamThreadData * data;
-	data = (StreamThreadData *)arg;
 
-	data->run();
-	return NULL;
-}
 

Modified: trunk/libmsip/source/SipSocketServer.cxx
===================================================================
--- trunk/libmsip/source/SipSocketServer.cxx	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/source/SipSocketServer.cxx	2007-01-20 16:41:03 UTC (rev 3132)
@@ -37,6 +37,7 @@
 // SipSocketServer
 // 
 
+
 SipSocketServer::SipSocketServer(MRef<SipLayerTransport*> r, MRef<Socket*> sock): ssock(sock), receiver(r),doStop(false){
 	externalPort = ssock->getPort();
 }

Modified: trunk/libmsip/source/SipStack.cxx
===================================================================
--- trunk/libmsip/source/SipStack.cxx	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/source/SipStack.cxx	2007-01-20 16:41:03 UTC (rev 3132)
@@ -79,6 +79,9 @@
 
 SipStack::~SipStack(){
 	MRef<SipStackInternal*> * mrefPtr = (MRef<SipStackInternal*> *) sipStackInternal;
+	
+	(*mrefPtr)->free();
+
 	delete mrefPtr;
 }
 

Modified: trunk/libmsip/source/SipStackInternal.cxx
===================================================================
--- trunk/libmsip/source/SipStackInternal.cxx	2007-01-19 20:54:43 UTC (rev 3131)
+++ trunk/libmsip/source/SipStackInternal.cxx	2007-01-20 16:41:03 UTC (rev 3132)
@@ -150,6 +150,15 @@
 	return dispatcher;
 }
 
+void SipStackInternal::free(){
+	setCallback(NULL);
+	setConfCallback(NULL);
+	dispatcher->free();
+	dispatcher=NULL;
+	timeoutProvider->stopThread();
+	timeoutProvider=NULL;
+}
+
 MRef<SipStackConfig*> SipStackInternal::getStackConfig(){
 	return config;
 }



More information about the Minisip-devel mailing list