Commit 8d9d8fa1 authored by Axel Auweter's avatar Axel Auweter
Browse files

After fixing a problem where mutexes were held when destructing

them, Boost 1.54.0 is no longer a problem.
parent 31ccfc4b
...@@ -10,12 +10,12 @@ ...@@ -10,12 +10,12 @@
using namespace std; using namespace std;
using namespace boost::system; using namespace boost::system;
static boost::mutex threadMtx;
#ifdef SimpleMQTTVerbose #ifdef SimpleMQTTVerbose
static boost::mutex coutMtx; static boost::mutex coutMtx;
#endif #endif
static boost::mutex launchMtx;
SimpleMQTTServerThread::SimpleMQTTServerThread() SimpleMQTTServerThread::SimpleMQTTServerThread()
{ {
/* /*
...@@ -25,11 +25,21 @@ SimpleMQTTServerThread::SimpleMQTTServerThread() ...@@ -25,11 +25,21 @@ SimpleMQTTServerThread::SimpleMQTTServerThread()
* *
* Special care must be taken not to call the run function * Special care must be taken not to call the run function
* before the child has gone through its constructor. Thus, * before the child has gone through its constructor. Thus,
* we lock a mutex that will cause the 'launch' function to * we lock a mutex (launchMtx) that will cause the 'launch'
* wait until the mutex is released by the child's * function to wait until the mutex is released by the
* constructor. * child's constructor.
*
* A second mutex (cleanupMtx) is held to allow others to
* wait for a thread to return from its child-specific
* 'run' function. This is necessary for cases where the
* child class has local objects that can only be destroyed
* after the 'run' function has finished (to avoid access
* to these objects in the 'run'function after destroying
* them). In such cases, the child class destructor can try
* to obtain the mutex in the destructor.
*/ */
threadMtx.lock(); launchMtx.lock();
cleanupMtx.lock();
terminate = false; terminate = false;
if (pthread_create(&t, NULL, launch, this) != 0) { if (pthread_create(&t, NULL, launch, this) != 0) {
...@@ -76,14 +86,19 @@ void* SimpleMQTTServerThread::launch(void *selfPtr) ...@@ -76,14 +86,19 @@ void* SimpleMQTTServerThread::launch(void *selfPtr)
* before the constructor of the child class has finished. * before the constructor of the child class has finished.
* The lock is released at the end of the child's constructor. * The lock is released at the end of the child's constructor.
*/ */
threadMtx.lock(); launchMtx.lock();
threadMtx.unlock(); launchMtx.unlock();
/* /*
* Call the child's run function... * Call the child's run function...
*/ */
((SimpleMQTTServerThread*)selfPtr)->run(); ((SimpleMQTTServerThread*)selfPtr)->run();
/*
* The thread will terminate. Unlock the cleanupMtx...
*/
((SimpleMQTTServerThread*)selfPtr)->cleanupMtx.unlock();
return NULL; return NULL;
} }
...@@ -210,7 +225,7 @@ SimpleMQTTServerAcceptThread::SimpleMQTTServerAcceptThread(int listenSock, Simpl ...@@ -210,7 +225,7 @@ SimpleMQTTServerAcceptThread::SimpleMQTTServerAcceptThread(int listenSock, Simpl
* Release the lock to indicate that the constructor has * Release the lock to indicate that the constructor has
* finished. This causes the launcher to call the run function. * finished. This causes the launcher to call the run function.
*/ */
threadMtx.unlock(); launchMtx.unlock();
} }
SimpleMQTTServerAcceptThread::~SimpleMQTTServerAcceptThread() SimpleMQTTServerAcceptThread::~SimpleMQTTServerAcceptThread()
...@@ -423,10 +438,21 @@ SimpleMQTTServerMessageThread::SimpleMQTTServerMessageThread(SimpleMQTTMessageCa ...@@ -423,10 +438,21 @@ SimpleMQTTServerMessageThread::SimpleMQTTServerMessageThread(SimpleMQTTMessageCa
* Release the lock to indicate that the constructor has * Release the lock to indicate that the constructor has
* finished. This causes the launcher to call the run function. * finished. This causes the launcher to call the run function.
*/ */
threadMtx.unlock(); launchMtx.unlock();
} }
SimpleMQTTServerMessageThread::~SimpleMQTTServerMessageThread() SimpleMQTTServerMessageThread::~SimpleMQTTServerMessageThread()
{ {
/*
* When this destructor is called externally, we are likely
* holding the fdsMtx mutex and waiting in poll().
* Terminate the thread from here and acquire cleanupMtx to
* ensure that the thread's 'run' function has terminated in
* order to avoid fdsMtx to be accessed after destruction.
*/
terminate = true;
cleanupMtx.lock();
cleanupMtx.unlock();
} }
...@@ -14,6 +14,8 @@ protected: ...@@ -14,6 +14,8 @@ protected:
pthread_t t; pthread_t t;
bool terminate; bool terminate;
boost::mutex cleanupMtx;
static void* launch(void* thisPtr); static void* launch(void* thisPtr);
static void yield(); static void yield();
virtual void run() = 0; virtual void run() = 0;
......
...@@ -5,7 +5,7 @@ DISTFILES = thrift-0.9.0.tar.gz;https://dist.apache.org/repos/dist/release/thrif ...@@ -5,7 +5,7 @@ DISTFILES = thrift-0.9.0.tar.gz;https://dist.apache.org/repos/dist/release/thrif
apache-cassandra-1.2.6.tar.gz;http://mirror.netcologne.de/apache.org/cassandra/1.2.6/apache-cassandra-1.2.6-bin.tar.gz \ apache-cassandra-1.2.6.tar.gz;http://mirror.netcologne.de/apache.org/cassandra/1.2.6/apache-cassandra-1.2.6-bin.tar.gz \
mosquitto-1.1.3.tar.gz;http://mosquitto.org/files/source/mosquitto-1.1.3.tar.gz \ mosquitto-1.1.3.tar.gz;http://mosquitto.org/files/source/mosquitto-1.1.3.tar.gz \
rudeconfig-5.0.5.tar.gz;http://rudeserver.com/config/download/rudeconfig-5.0.5.tar.gz \ rudeconfig-5.0.5.tar.gz;http://rudeserver.com/config/download/rudeconfig-5.0.5.tar.gz \
boost_1_53_0.tar.gz;http://netcologne.dl.sourceforge.net/project/boost/boost/1.53.0/boost_1_53_0.tar.gz boost_1_54_0.tar.gz;http://netcologne.dl.sourceforge.net/project/boost/boost/1.54.0/boost_1_54_0.tar.gz
FETCH = wget -c --no-check-certificate -O - FETCH = wget -c --no-check-certificate -O -
MAKETHREADS ?= 4 MAKETHREADS ?= 4
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment