QNX pthread_mutex_lock, вызывающий ошибку взаимоблокировки (45 = EDEADLK) - PullRequest
0 голосов
/ 02 января 2019

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

void CTraceFileWriterThread::run() 
{
    bool fShoudIRun = shouldThreadsRun();  //  Some global function which decided if operations need to stop. Not really relevant here. Assume "true" value.

    while(fShoudIRun)
    {
      std::string nextMessage = fetchNext();
      if( !nextMessage.empty() )
      {
          process(nextMessage);
      }
      else
      {
          fShoudIRun = shouldThreadsRun();
          condVarTraceWriter.wait();
      }
    }
 }

//This is the consumer. This is in my thread with lower priority
std::string CTraceFileWriterThread::fetchNext() 
{
    // When there are a lot of logs, I mean A LOT, I believe the 
    // control stays in this function for a long time and an other 
    // thread calling the "add" function is not able to acquire the lock
    // since its held here.

    std::string message;

    if( !writeQueue.empty() )
    {
      writeQueueMutex.lock();        // Obj of our wrapper around pthread_mutex_lock 
      message = writeQueue.front();  
      writeQueue.pop();              // std::queue
      writeQueueMutex.unLock() ;
    }
    return message;
}




//  This is the producer and is called from multiple threads.
void CTraceFileWriterThread::add( std::string outputString ) {

if ( !outputString.empty() )
{
    // crashes here while trying to acquire the lock when there are lots of
    // logs in prod systems.

    writeQueueMutex.lock();
    const size_t writeQueueSize = writeQueue.size();

    if ( writeQueueSize == maximumWriteQueueCapacity )
    {
        outputString.append ("\n queue full, discarding traces, traces are incomplete" );
    }

    if ( writeQueueSize <= maximumWriteQueueCapacity )
    {
        bool wasEmpty = writeQueue.empty();
        writeQueue.push(outputString);



        condVarTraceWriter.post(); // will be waiting in a function which calls "fetchNext"

    }
    writeQueueMutex.unLock();

}


int wrapperMutex::lock() {
//#[ operation lock()

 int iRetval;
 int iRetry = 10;

 do
 {
    //
    iRetry--;
    tRfcErrno = pthread_mutex_lock (&tMutex);
    if ( (tRfcErrno == EINTR) || (tRfcErrno == EAGAIN) )
    {
        iRetval = RFC_ERROR;    
        (void)sched_yield();
    }
    else if (tRfcErrno != EOK)
    {
        iRetval = RFC_ERROR;    
        iRetry = 0;
    }
    else
    {
        iRetval = RFC_OK;    
        iRetry = 0;
    }
 } while (iRetry > 0);

 return iRetval;


//#]

}

Я сгенерировал дамп ядра и проанализировал его с помощью GDB, и вот некоторые выводы

  1. Программа завершена с сигналом 11, ошибка сегментации.

  2. "Errno = 45" в функции добавления, где я пытаюсь получить блокировку. Оболочка, которую мы имеем вокруг pthread_mutex_lock, пытается получить блокировку примерно 10 раз, прежде чем она сдастся.

Код работает нормально, когда журналов меньше. Кроме того, у нас нет C ++ 11 или более поздней версии, и поэтому мы ограничены мьютексом QNX. Любая помощь приветствуется, поскольку я смотрю на этот вопрос более месяца с небольшим прогрессом. Пожалуйста, спросите, требуется ли дополнительная информация.

...