2011-08-23 85 views
1

我們在靜態類中有幾個鎖(boost :: mutex),但是當程序退出時,pthread_mutex_destroy在互斥體的析構函數中失敗(有一個斷言在boost中檢查它)。boost :: mutex,pthread_mutex_destroy失敗 - 調試建議?

據我所知,pthread_mutex_destroy只會在兩種情況下失敗。

[EBUSY] The implementation has detected an attempt to destroy the object referenced by mutex while it is locked or referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread. 
[EINVAL] The value specified by mutex is invalid. 

當我在GDB中運行並打印鎖時,我發現它已解鎖。 不幸的是我無法在GDB中打印errno。

#3 0x000000000044a2c6 in ~mutex (this=0x847840, __in_chrg=<value optimized out>) at /usr/include/boost/thread/pthread/mutex.hpp:47 
47    BOOST_VERIFY(!pthread_mutex_destroy(&m)); 
(gdb) p m 
$1 = {__data = {__lock = 0, __count = 0, __owner = 0, __nusers = 4294967294, __kind = 0, __spins = 0, __list = {__prev = 0x0, 
     __next = 0x0}}, __size = '\000' <repeats 12 times>"\376, \377\377\377", '\000' <repeats 23 times>, __align = 0} 

現在我寫這篇文章__nusers和__size的值看起來很奇怪。這可能暗示該鎖無效,但我知道該鎖在某個時刻是有效的(我將boost :: mutex包裝在一個Lock類中,在該類中我在構造函數,析構函數和鎖中打印了此值(0x847840) /解鎖功能

任何幫助就如何調試這將不勝感激

編輯 鎖類自boost ::互斥繼承,並導出一個scopedlock(從內存中):

lock_type::scoped_lock getScopedLock() { 
    return lock_type::scoped_lock(*this); 
} 

我也嘗試添加鎖作爲成員,而不是繼承從中,沒有任何行爲改變。 我不認爲getScopedLock函數可能會引入任何問題(範圍鎖定返回y值,但因RVO而不能創建副本),但認爲它可能值得一提。 它的用法如下(我們使用的C++ 0x):

auto lock = lock_.getScopedLock(); 

完整stracktrace:

(gdb) where 
#0 0x00007ffff559da75 in *__GI_raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 
#1 0x00007ffff55a15c0 in *__GI_abort() at abort.c:92 
#2 0x00007ffff5596941 in *__GI___assert_fail (assertion=0x55851c "!pthread_mutex_destroy(&m)", file=<value optimized out>, line=47, 
    function=0x5595a0 "boost::mutex::~mutex()") at assert.c:81 
#3 0x000000000044a2c6 in ~mutex (this=0x847840, __in_chrg=<value optimized out>) at /usr/include/boost/thread/pthread/mutex.hpp:47 
#4 0x000000000044d923 in ~Lock (this=0x847840, __in_chrg=<value optimized out>) at include/Locks.h:43 
#5 0x00007ffff55a3262 in __run_exit_handlers (status=0) at exit.c:78 
#6 *__GI_exit (status=0) at exit.c:100 
#7 0x00000000004ea9a6 in start() at src/main.cc:191 
#8 0x00000000004de5aa in main (argc=1, argv=0x7fffffffe7b8) at src/main.cc:90 
+0

如果你顯示代碼會有幫助(例如'Locks.h'中發生了什麼) – Tom

+1

發佈的代碼很少,這是我發佈此帖的原因之一,因爲我不知道在成千上萬行代碼中尋找問題。所以很不幸,我也無法制作一個小型測試用例。我甚至不知道哪幾個鎖正在破壞(我可以通過打印所有鎖的地址來初始化它們).Locks類所做的所有工作都是從boost :: mutex atm繼承的,它的確如此別的。 – thelamb

+0

@thelamb如果您不能發佈複製器,請在valgrind下運行您的代碼。 –

回答

3

你通常得到這個錯誤,當您unlock你不互斥鎖首先它。

boost::mutex m; 
    m.unlock(); 

我的猜測是某處你正在使用lockunlock成員,而不是RAII, 和你已經失去了lock通話。

請注意,大多數情況下,您不應該致電lockunlock成員。使用爲您調用功能的scoped_lock

struct s 
{ 
    void foo() 
    { 
    boost::mutex::scoped_lock l(m_mutex); 
    //do something 
    } 
    private: 
    boost::mutex m_mutex; 
}; 

此外,你提到你是從boost::mutex繼承。這可能會導致問題,因爲boost::mutex沒有虛擬析構函數,所以最好不要這樣做。

+0

謝謝您的回覆,我會檢查我們對鎖和解鎖的使用情況。在大多數情況下,我們已經使用了scoped_lock。你對繼承是不安全的權利,但我已經檢查過,如果我修改Lock來保持互斥鎖作爲成員並導出鎖定/解鎖功能,問題仍然存在。我將再次執行此操作並保留一個變量,以檢查是否首先調用解鎖並且狀態仍處於解鎖狀態。我忘了提及Lock的一件事,請參閱我的編輯帖子 – thelamb

+0

以瞭解您對getScopedLock的關注:我應該提及我們使用的是C++ 0x。 Scoped鎖是可移動的。但由於這裏不涉及移動或複製,所以不應該有任何問題(我並不過分擔心它不適用於其他編譯器)。 – thelamb

3

好的結果有兩個問題。 有一個鎖,從來沒有被使用過,但當停止時,我確實打電話解鎖。 很明顯,我沒有正確地閱讀文檔,因爲解鎖前的前提條件是當前線程必須擁有鎖定。 謝謝湯姆讓我看到這一點。

的第二個問題是,什麼地方我有一個範圍的鎖,我想解開它,它超出範圍之前:

auto lock = lock_.getScopedLock(); 
if(something) 
    lock.unlock(); 

原來,這個閱讀lock_.unlock();,所以我解鎖互斥,不通過範圍鎖定。

@湯姆,我不喜歡寫作boost::mutex::scoped_lock l(lock_)的原因是,如果你寫boost::mutex::scoped_lock l()不會有任何錯誤。 現在,我看到的唯一危險是有人在沒有將其存儲在變量中的情況下編寫lock_.getScopedLock(),我想當其他人開始觸摸代碼時,我們只需定義一個宏來獲取作用域鎖定(是的,我們可以做同樣的事情對於沒有getScopedLock;)的變體)。 無論如何,我不是從boost::mutex繼承,而是保持它作爲一個成員。你是對的,我們不應該冒險繼承它。

@Daniel, 與-lpthread沒有幫助編譯,我沒有時間去看看那個特定問題的時刻,因爲我並不需要它,但感謝你的建議呢。

@Sam, 我的確在valgrind中運行過,但是它並沒有顯示鎖定問題的有趣輸出。