2014-10-08 71 views
2

我在一個linux應用程序中使用Boost 1.41,它在一個線程上接收數據並將其保存在一個隊列中,另一個線程將其從隊列中彈出並處理它。爲了使線程安全,我使用了作用域鎖。Boost範圍鎖定斷言失敗

我的問題是極少的鎖定功能與信息讀取功能失敗:「!pthread_mutext_lock(&米)」

無效的boost ::互斥鎖::()斷言失敗

這是非常罕見的,在最後一次運行中,在發生故障之前花了36小時(約425萬筆交易)。讀取和寫入功能如下表所示,它總是在斷言出現讀取功能

寫入隊列從隊列中讀取

void PacketForwarder::Enqueue(const byte_string& newPacket, long sequenceId) 
{ 
    try 
    { 
     boost::mutex::scoped_lock theScopedLock(pktQueueLock); 
     queueItem itm(newPacket,sequenceId); 
     packetQueue.push(itm); 

     if (IsConnecting() && packetQueue.size() > MaximumQueueSize) 
     { 
      // Reached maximum queue size while client unavailable; popping. 
      packetQueue.pop(); 
     } 
    } 
    catch(...) 
    { 
     std::cout << name << " Exception was caught:" << std::endl; 
    } 
} 

while (shouldRun) 
{ 
    try 
    { 
     if (clientSetsHaveChanged) 
     { 
      tryConnect(); 
     } 

     size_t size = packetQueue.size(); 
     if (size > 0) 
     { 
      byte_string packet; 
      boost::mutex::scoped_lock theQLock(pktQueueLock); 
      queueItem itm = packetQueue.front(); 
      packet = itm.data; 
      packetQueue.pop(); 

      BytesSent += packet.size(); 

      trySend(packet); 
     } 
     else 
     { 
      boost::this_thread::sleep(boost::posix_time::milliseconds(50)); 
     } 
    } 
    catch (...) 
    { 
     cout << name << " Other exception in send packet" << endl; 
    } 

我已經在銷燬scoped_locks時發現了一些問題,但沒有發現無法獲得鎖定。我還通過增強版發佈筆記和Trac日誌進行了搜索,以查看這是否被其他人識別爲問題。我認爲我的代碼非常簡單,但顯然有些事情已經到來。有什麼想法嗎? TIA 保羅

+1

有兩件事:1)boost 1.41已經很老了,你可能想看看更新是否能解決問題; 2)你可以修改具有assert的區域,以便記錄從'pthread_mutex_lock()'返回的值,這可能會給出問題的線索。 – 2014-10-08 17:08:27

+0

是否只有一個全局'pktQueueLock'?另外,在不保存'pktQueueLock'的情況下調用'packetQueue.size()'是否安全? – dohashi 2014-10-08 17:10:24

+0

可能與你的問題無關,你的代碼似乎也對不需要鎖的操作持有鎖,例如writer中的queueItem itm(newPacket,sequenceId)和讀者中的trySend(packet);' (除非有多個閱讀器線程並且發送需要按順序進行)。 – 2014-10-08 17:14:33

回答

0

。在你的節目中的一個線程安全的問題,在這一段代碼:

size_t size = packetQueue.size(); 
    if (size > 0) 
    { 
     byte_string packet; 
     boost::mutex::scoped_lock theQLock(pktQueueLock); 
     queueItem itm = packetQueue.front(); 
     packet = itm.data; 
     packetQueue.pop(); 
     // ... 
    } 

這裏的問題是,時間之間你檢查隊列的大小和你有時間鎖定其他讀者線程可能會將最後一個項目排除隊列,這將導致front()pop()失敗。除非您只有一個閱讀器線程,否則還需要檢查大小。

我不知道這是否是斷言失敗的原因。斷言意味着對pthread_mutex_lock的調用返回一個非零值,表示出現錯誤。不幸的是,Boost並未顯示possible pthread_mutex_lock errors發生了什麼。

+1

另外,因爲'packetQueue'大小在編寫器線程中發生了變化。除非'size()'函數在內部處理併發性問題,否則讀取大小而不保持互斥體可能是數據競爭(並因此未定義行爲)。 – 2014-10-08 18:03:36

+0

我最初對此感到懷疑,但在檢查時只有1位作者和1位讀者,所以我不認爲這是問題所在。 – roccap 2014-10-09 07:55:40