是否可以确定持有互斥锁的线程?


70

首先,我使用pthread库编写多线程C程序。线程总是被等待的互斥锁挂起。当我使用strace实用程序查找线程处于FUTEX_WAIT状态时,我想知道当时哪个线程持有该互斥量。但是我不知道该怎么做。有没有公​​用事业可以做到这一点?

有人告诉我Java虚拟机支持此功能,因此我想知道Linux是否支持此功能。

Answers:


119

您可以使用互斥量内部知识来执行此操作。通常,这不是一个好主意,但是对于调试来说很好。

在具有NPTL实现的pthreads Linux(任何现代glibc)下,您可以检查结构的__data.__owner成员pthread_mutex_t以找出当前已将其锁定的线程。这是通过以下方法将其附加到流程之后的方法gdb

(我切换到挂起的线程;进行回溯以查找被pthread_mutex_lock()卡住的线程;更改堆栈框架以查找其试图锁定的互斥体的名称;然后打印该互斥体的所有者)。这告诉我,具有LWP ID 22025的线程是罪魁祸首。

然后,您可以使用thread find 22025查找该gdb线程的线程号并切换到该线程号。


1
有没有一种方法可以将数据.__ owner__与pthread线程ID相关联?在玩这个游戏时,我只对日志<<互斥锁.__ data __。owner << endl进行了编码,看来工作正常。但是data.owner是一个值,例如9841,而tid是一个值,例如140505876686608。这两个值之间的关系是什么?
鸭子2010年

5
@Duck:中的值为.__data.__ownerTID。当每个线程启动时,您可以让他们记录其TID(使用tid = syscall(SYS_gettid);)以及其TID pthread_t(来自pthread_self())。
caf 2010年

1
您还可以在中的stat文件中检查线程的堆栈指针proc,它的值非常接近(几kb之内)pthread_t。:-)
R .. GitHub停止帮助ICE,

2
顺便说一句:可以info threads用来将TID(.__data.__owner)映射到pthread ID(一个在gdb中进行操作的ID)。
亚当·罗曼尼克

8
@caf,您可以添加到您的答案中,即现在在gdb中有thread find命令。因此,在找到的mutex.__data.__owner是22025之后,您可以运行:thread find 22025并获取gdb中的线程号:(例如:)Thread 29 has target id 'Thread 0x7fffdf5fe700 (LWP 22025)' 。因此,您接下来可以使用以下命令切换到持有锁的线程:thread 29t 29

5

我不知道有任何这样的功能,因此我认为您不会轻易摆脱这种情况-而且它可能不会像您认为的那样有助于调试程序。尽管技术水平很低,但日志记录是调试这些事情的朋友。开始收集您自己的小日志功能。他们不必花哨,而只需要在调试时完成工作即可。

对不起,C ++但类似:

日志记录不是一个完美的解决方案,但没有。它通常会为您提供所需的知识。


日志记录确实是用于调试的非常有用的工具。感谢您的建议。
特里

1
+1谁不喜欢伐木?使用LD_PRELOAD无需更改任何代码即可完成操作(并且要有耐心)。pthread_mutex_*用记录了函数调用,互斥体的地址和线程标识符的东西包装函数(pthread_t在Linux上碰巧是不可或缺的类型,不是可移植的假设,而是很方便的)。
pilcrow,2010年

7
日志记录可能存在的问题是,它可能会破坏时间安排并使其消失。
Spudd86

同样,您不能总是/可预测地插入库函数。这不是保证。
马特·乔纳

日志记录非常有用。但是,在某些地方记录不安全。具体来说,malloc在某些地方不安全-例如,在信号处理程序,atfork处理程序中,多线程程序中的fork和exec之间,等等。请参见async-signal-safety和其他手册页。
mgarey

2

通常,libc / platforms调用由OS抽象层抽象。可以使用所有者变量和pthread_mutex_timedlock跟踪互斥锁死锁。每当线程锁定时,都应使用自己的tid(gettid()更新该变量,也可以为pthread id存储使用另一个变量)。因此,当其他线程阻塞并在pthread_mutex_timedlock上超时时,它可以显示所有者tid和pthread_id的值。这样,您可以轻松地找到所有者线程。请在下面找到代码段,请注意,并未处理所有错误情况

还有其他方法可以找出死锁,也许此链接可能对http://yusufonlinux.blogspot.in/2010/11/debugging-core-using-gdb.html有所帮助。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.