Boost logo

Boost :

Subject: [boost] [Thread] Assertion on mutex when using multiple threads and mutexes
From: Tim van den Kerkhof (tim.van.den.kerkhof_at_[hidden])
Date: 2011-07-22 10:46:04


Hi all,

As a part of a project I'm writing a logger function. This logger
function sends an e-mail when the program wants to log something. Since
it has happened that the SMTP server was non responsive, I've decided to
do the sending of the mails in a separate thread.
This thread reads messages from an std::deque which is filled by the
logging function.
The thread is setup as follows:

while (!boost::this_thread::interruption_requested())
{
     EmailItem emailItem;
     {
       boost::unique_lock<boost::mutex> lock(mMutex);
       while (mEmailBuffer.empty())
         mCond.wait(lock);

       bufferOverflow = mBufferOverflow;
       mBufferOverflow = false;
       nrOfItems = mEmailBuffer.size();

       if (nrOfItems > 0)
       {
         emailItem = mEmailBuffer.front();
         mEmailBuffer.pop_front();
       }
     }

     if (nrOfItems > 0)
     {
         bool sent = false;
         while(!sent)
         {
             try
             {
                ..... Do something with the message .....
               {
                   boost::this_thread::disable_interruption di;
                   boost::lock_guard<boost::mutex> lock(mLoggerMutex);
                   mLogFile << emailItem.mMessage << std::endl;
               }
               sent = true;
             }
             catch (const std::exception &e)
             {
               // Unable to send mail, an exception occurred. Retry
sending it after some time
               sent = false;
               
boost::this_thread::sleep(boost::posix_time::seconds(LOG_WAITBEFORE_RETRY));
             }
         }
     }
}

The function log() adds a new message to the deque (mEmailBuffer) as
follows:

{
     boost::lock_guard<boost::mutex> lock(mMutex);
     mEmailBuffer.push_back(e);
     mCond.notify_one();
}

When the main program exits, the destructor of the logger object is
called. This is where it goes wrong, the application crashes with an error:

/usr/include/boost/thread/pthread/mutex.hpp:45: boost::mutex::~mutex():
Assertion `!pthread_mutex_destroy(&m)' failed.

The destructor merely calls an interrupt on the thread and then joins it:

mQueueThread.interrupt();
mQueueThread.join();

In the main program, I use multiple different classes which make use of
boost threading and mutex as well, could this cause this behaviour? Not
calling the destructor of the logger object results in no errors, as
does using the logger object and not doing anything else.

My guess is I am doing something very wrong, or there is a bug in the
threading library when using multiple threads divided over several classes.
Does anyone have a idea what the reason for this error might be?

Regards,

Tim van den Kerkhof


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk