Утверждение о мьютексе при использовании нескольких потоков и мьютексов

В рамках проекта я пишу функцию регистратора. Эта функция регистратора отправляет электронное письмо, когда программа хочет что-то зарегистрировать. Поскольку случилось так, что SMTP-сервер не отвечал, я решил отправить почту в отдельном потоке. Этот поток читает сообщения из std :: deque, который заполняется функцией регистрации. Поток настраивается следующим образом:

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));
          }
      }
  }
}

Функция log () добавляет новое сообщение в двухстороннюю очередь (mEmailBuffer) следующим образом:

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

Когда основная программа завершается, вызывается деструктор объекта регистратора. Здесь происходит сбой, приложение вылетает с ошибкой:

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

Деструктор просто вызывает прерывание в потоке, а затем присоединяется к нему:

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

В основной программе я использую несколько разных классов, которые используют ускорение потоковой передачи а также мьютекс, могло ли это вызвать такое поведение? Отсутствие вызова деструктора объекта логгера не приводит к ошибкам, как и использование объекта логгера и бездействие чего-либо.

Я предполагаю, что я делаю что-то очень неправильно, или есть ошибка в библиотеке потоков при использовании нескольких потоки разделены на несколько классов. Кто-нибудь знает, в чем может быть причина этой ошибки?

РЕДАКТИРОВАТЬ: Я сделал, как предлагал @Andy T, и максимально удалил код. Я удалил почти все в функции, которая выполняется в другом потоке. Теперь цепочка выглядит так:

void Vi::Logger::ThreadedQueue()
{
  bool bufferOverflow = false;
  time_t last_overflow = 0;
  unsigned int nrOfItems = 0;

  while (!boost::this_thread::interruption_requested())
  {
    EmailItem emailItem;
    // Check for new log entries
    {
      boost::unique_lock<boost::mutex> lock(mMutex);
      while (mEmailBuffer.empty())
        mCond.wait(lock);
    }
  }
}

Проблема все еще сохраняется. Однако поиск проблемы показал мне нечто отличное от исходного кода:

#0  0x00007ffff53e9ba5 in raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x00007ffff53ed6b0 in abort () at abort.c:92
#2  0x00007ffff53e2a71 in __assert_fail (assertion=0x7ffff7bb6407 "!pthread_mutex_lock(&m)", file=<value optimized out>, line=50, function=0x7ffff7bb7130 "void boost::mutex::lock()") at assert.c:81
#3  0x00007ffff7b930f3 in boost::mutex::lock (this=0x7fffe2c1b0b8) at /usr/include/boost/thread/pthread/mutex.hpp:50
#4  0x00007ffff7b9596c in boost::unique_lock<boost::mutex>::lock (this=0x7fffe48b3b40) at /usr/include/boost/thread/locks.hpp:349
#5  0x00007ffff7b958db in boost::unique_lock<boost::mutex>::unique_lock (this=0x7fffe48b3b40, m_=...) at /usr/include/boost/thread/locks.hpp:227
#6  0x00007ffff6ac2bb7 in Vi::Logger::ThreadedQueue (this=0x7fffe2c1ade0) at /data/repos_ViNotion/stdcomp/Logging/trunk/src/Logger.cpp:198
#7  0x00007ffff6acf2b2 in boost::_mfi::mf0<void, Vi::Logger>::operator() (this=0x7fffe2c1d890, p=0x7fffe2c1ade0) at /usr/include/boost/bind/mem_fn_template.hpp:49
#8  0x00007ffff6acf222 in boost::_bi::list1<boost::_bi::value<Vi::Logger*> >::operator()<boost::_mfi::mf0<void, Vi::Logger>, boost::_bi::list0> (this=0x7fffe2c1d8a0, f=..., a=...) at /usr/include/boost/bind/bind.hpp:253
#9  0x00007ffff6acf1bd in boost::_bi::bind_t<void, boost::_mfi::mf0<void, Vi::Logger>, boost::_bi::list1<boost::_bi::value<Vi::Logger*> > >::operator() (this=0x7fffe2c1d890) at /usr/include/boost/bind/bind_template.hpp:20
#10 0x00007ffff6aceff2 in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, Vi::Logger>, boost::_bi::list1<boost::_bi::value<Vi::Logger*> > > >::run (this=0x7fffe2c1d760)
    at /usr/include/boost/thread/detail/thread.hpp:56
#11 0x00007ffff2cc5230 in thread_proxy () from /usr/lib/libboost_thread.so.1.42.0
#12 0x00007ffff4d87971 in start_thread (arg=<value optimized out>) at pthread_create.c:304
#13 0x00007ffff549c92d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#14 0x0000000000000000 in ?? ()

Возможно ли, что mMutex не разблокируется в сочетании с использованием unique_lock () и последующим прерыванием потока?

7
задан Tim 29 July 2011 в 08:13
поделиться