用gdb调试pthreads

用gdb调试pthreads,gdb,pthreads,mutex,conditional-breakpoint,Gdb,Pthreads,Mutex,Conditional Breakpoint,我试图调试一个非常罕见的死锁,并将其缩小为pthread_互斥锁的问题,它属于类型1(递归)。我想跟踪这个互斥体的来源,因为我们所有的代码都使用普通互斥体,所以我认为检测互斥体类型==recursive的时间来跟踪它是有意义的 我曾尝试在pthread_mutex_lock中设置一个手动断点,通过堆栈指针等解除对pthread_mutex_t的引用,以检查其类型,但这被调用了数百万次,并且要捕获mutex type==recursive的情况将需要很长时间 我还尝试插入一个库并替换pthread

我试图调试一个非常罕见的死锁,并将其缩小为pthread_互斥锁的问题,它属于类型1(递归)。我想跟踪这个互斥体的来源,因为我们所有的代码都使用普通互斥体,所以我认为检测互斥体类型==recursive的时间来跟踪它是有意义的

我曾尝试在pthread_mutex_lock中设置一个手动断点,通过堆栈指针等解除对pthread_mutex_t的引用,以检查其类型,但这被调用了数百万次,并且要捕获mutex type==recursive的情况将需要很长时间

我还尝试插入一个库并替换pthread_mutex_lock,以使在互斥类型上设置断点成为可能,但这没有得到任何结果(我不相信这是在捕获对pthread_mutex_lock的所有调用)

我觉得在gdb中一定有一种方法可以设置一个观察点/条件断点,以便在调用pthread_mutex_lock时使用递归类型的互斥锁


如能在上述方面提供任何帮助,将不胜感激。提前感谢。

您可以使用观察点,而不是
gdb
断点。您可以尝试:

(gdb) conditional yourbreakpointid mutex.__m_kind==PTHREAD_MUTEX_RECURSIVE
其中,
mutex
是作用域中的互斥体的名称,
yourbreakpointid
是您在函数中放置的断点的id

__m_类可能会根据实现的不同而更改名称,如果这个名称不起作用,请搜索您的分发标题(pthread.h)

我已经把它缩小到pthread_互斥体的问题,它是类型1(递归)
我想追踪这个互斥体的来源,因为我们所有的代码都使用普通互斥体

大概您已经确定您的线程在试图锁定递归互斥锁的
pthread\u mutex\u lock
中被阻塞,您不知道谁持有这个互斥锁,以及为什么

导致
pthread\u mutex\u lock
的堆栈跟踪应该准确地告诉您哪个代码正在尝试锁定该互斥锁,这是理解问题所需要知道的全部

我不明白为什么要在锁定该互斥锁的过程中“捕获”pthread_mutex_锁,因为在检测到死锁后,通过查看堆栈,这可能不会为您提供更多的信息


一般来说,试图用GDB调试互斥锁问题是徒劳的——设置断点(甚至只是附加GDB)的行为改变了操作的时间,以至于在GDB下运行时绝大多数问题都不会出现。

谢谢-我已经尝试过了,但出于某种原因,GDB无法解析互斥锁参数(我记不起确切的错误消息,直到星期二我才可以访问我的机器)。不过我会再试一次,听起来应该可以。我无法让gdb解释传递给pthread_mutex_lock的mutex参数。问题是传递的参数是“mutex”但当我在pthread_lock_mutex中执行ptype mutex时,它返回std::mutex,因此我得到“尝试将类型名称用作表达式”当我尝试使用它做任何事情时。我最初认为这可能是一个gdb错误,但我现在运行的是最新的,仍然没有乐趣。我还尝试静态链接pthreads,但没有用!非常感谢任何帮助:)@user1621986您是否尝试使用
::mutex
,告诉gdb这不是您所指的
std::mutex
,而是全局命名空间中的变量?谢谢您的建议-仍然没有乐趣。奇怪的是,在gdb中,如果我执行ptype pthread_mutex_lock,它将返回int(void)-我不知道为什么会出现这种情况(在redhat 5.6上),我希望在那里看到pthread_mutex_t参数。我可以试试别的机器,看看能得到什么。谢谢。是的,监视点可以工作,但我不确定的是如何计算出要监视的内存地址,以便监视所有对pthread_mutex_lock的调用(类型为recursive)。我同意你的观点,但不幸的是,对于死锁点的线程,堆栈跟踪似乎不完整/损坏(很多??),因此,我看不到足够多的帧来确定每个线程所遵循的代码路径(我可能需要了解有关手动跟踪堆栈指针的更多信息)。我同意死锁不太可能在gdb下出现,但是,我认为跟踪递归互斥的起源(在正常操作期间)可以更好地了解线程3获取锁的位置(取决于使用递归互斥的代码路径的数量:)。