如何通过GDB识别持有std::recursive_mutex或std::shared_mutex的线程?
方法1:用libstdc++的GDB调试脚本
GDB自带针对libstdc++的调试辅助脚本,多数情况下会自动加载。如果没加载,手动执行:
source /usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30-gdb.py
(路径根据你的libstdc++实际版本调整,比如把6.0.30换成你系统里的版本号)
加载后直接打印互斥锁实例:
- 对
std::recursive_mutex,执行p mutex,输出里的__owner字段就是持有锁的线程ID - 对
std::shared_mutex:- 独占模式下,
__exclusive_owner字段对应持有锁的线程ID - 共享模式下,
__shared_count会显示当前持有共享锁的线程数,结合线程栈能进一步定位具体线程
- 独占模式下,
方法2:手动解析底层POSIX结构
如果调试脚本用不了,直接看C++标准库封装的底层POSIX锁结构:
std::recursive_mutex本质是pthread_mutex_t,执行p *(pthread_mutex_t*)&mutex,查看__data.__owner字段(部分glibc版本里是__owner,直接看输出里的线程ID字段即可)std::shared_mutex底层是pthread_rwlock_t,执行p *(pthread_rwlock_t*)&mutex:__data.__writer是独占锁的持有线程ID__data.__nr_readers显示共享锁的持有数量,再配合每个线程的栈帧,找调用lock_shared()未返回的线程
方法3:遍历线程栈排查
如果前两种方法都不生效,直接查所有线程的调用栈:
- 执行
info threads列出所有线程ID - 用
thread <线程ID>切换到目标线程,再执行bt打印栈帧 - 找那些调用了
std::recursive_mutex::lock()、std::shared_mutex::lock()(独占)或std::shared_mutex::lock_shared()(共享)但还没返回的线程,这些就是持有锁的线程
内容的提问来源于stack exchange,提问作者calvin
相关产品推荐
相关产品推荐

