2010-07-14 77 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来给你一些锁定信息的信息。