2010-07-14 109 views
4

我有一個服務器端客戶端程序,其中有多個線程在服務器和客戶端。有不同數量的客戶端和服務器(如3臺服務器(副本),10臺客戶端)。我在這個程序中調試源文件。我認爲存在某種類型的死鎖,可能有以下幾種:幫助需要與pthreads調試

互斥鎖已被服務器方法佔用,來自客戶端的請求調用一個想要再次獲取互斥鎖的服務器方法。

該程序由測試腳本啓動,該腳本生成服務器和客戶端,並使客戶端向服務器發送特定請求。我已經使用在代碼的可疑區域下面的代碼,看看是否有一個僵局,但它似乎沒有工作,即代碼既不進入塊:

if (pthread_mutex_lock(&a_mutex) == EDEADLK) { 
    cout<<"couldnt acquire lock."<<endl; 
} 
else cout<<"acquired lock"<<endl; 

我試着調試(通過附加一個運行服務器進程)與gdb。我爲a_mutex添加了「display」和「watch」(在gdb的不同運行中)。我得到以下形式的結果:

1: a_mutex = {__data = {__lock = 2, __count = 0, __owner = 4193, __kind = 0, __nusers = 2, 
{__spins = 0, __list = {__next = 0x0}}}, 
    __size = "\002\000\000\000\000\000\000\000a\020\000\000\000\000\000\000\002\000\000 \000\000\000\000", __align = 2} 

我不知道在上面的輸出中的所有事物的意義,但我可以看到一個線程(4193)持有的互斥。我看到該線程的回溯(剪切):

#0 0xb8082430 in __kernel_vsyscall() 
#1 0xb7e347a6 in nanosleep() from /lib/tls/i686/cmov/libc.so.6 
#2 0xb7e345be in sleep() from /lib/tls/i686/cmov/libc.so.6 
#3 0x0804cb59 in class1::method1 (this=0xbfa9fe6c, clt=1, id= 
    {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb7c9c11c "l/%\b"}}) 
at file1.cc:33 

我不知道如何以及錯誤在哪裏。

我將高度讚賞有以下問題的任何幫助:

  1. 什麼是調試這樣的條件/程序的好方法嗎?
  2. 我該如何檢測死鎖狀態(例如,鎖正在被鎖定而未被釋放)?
  3. 在這樣的多進程程序中,有沒有更好的使用gdb的方法? (即檢查所有進程中的狀態?配置gdb以在進程開始之前監視/顯示變量?)
  4. 因爲當服務器啓動後(通過測試腳本)將gdb與服務器連接在一起時,服務器可能已經超越了我想要檢查的代碼。我試圖在可疑區域之前添加睡眠(20)以幫助我使用gdb,但我認爲這不是一個好方法。我也認爲打開多個終端,手動啓動服務器和客戶端並檢查每個終端的狀態也不是一個好主意(如果我錯了,請糾正我)。

PS:我已經讀過question了。

非常感謝。

+1

我個人使用了英特爾線程檢查器。我發現它非常有用捕獲死鎖 – onof 2010-07-14 11:43:42

+2

我也使用過英特爾線程檢查器。這個hellgrind工具(Valgrind的一部分)也很棒。 – 2010-07-14 13:41:22

+0

這看起來不像死鎖,而只是爭用。你有第二個互斥體在那裏被收購嗎?如果是這樣,請確保它們以相同的順序*被鎖定。 – 2010-07-14 20:11:50

回答

4

使用GDB並將其附加到掛起的程序。然後使用 「線程應用所有bt」(我認爲,但我沒有一個系統方便)。

它會給你一個所有線程的回溯,你應該是 能夠看到哪個線程在做什麼。

如果這個問題很容易重現,那麼你可以使用strace來給你一些鎖定信息的信息。