目标进程正阻塞在用户态锁上,如 pthread_mutex 或 std::mutex,内核通过 futex_wait 挂起线程等待唤醒;需结合 gdb 查栈和锁地址确认持有者及锁状态。
strace -p 卡在 futex_wait 是什么信号
这说明目标进程正阻塞在用户态锁(如 pthread_mutex、std::mutex)上,内核通过 futex_wait 系统调用挂起线程等待唤醒。它不是死锁的充分证据,但确实是锁竞争或持有者不释放的典型表征。
关键要区分两种情况:短暂等待(比如临界区短、锁很快释放)和持续挂起(几秒以上不动)。后者才值得深入。
-
futex_wait后面通常跟着一个地址(如0x7f...
),这是锁变量在内存中的地址,可用于后续比对 - 如果
strace -p本身也卡住不动,说明 tracee 正在不可中断睡眠(
D状态),此时strace无法注入 syscall,需换方式 - 注意:glibc 的
pthread_mutex_lock在争用时可能先自旋再 fallback 到futex_wait,所以看到futex_wait前没其他锁操作日志,不代表没尝试加锁
怎么确认是哪个锁、被谁持有
仅靠 strace 输出无法定位锁归属,必须结合进程栈和内存状态。优先使用 gdb attach 获取线程上下文:
- 运行
gdb -p,然后thread apply all bt查所有线程栈,重点找持有锁的线程——它通常停在pthread_mutex_lock返回后、或pthread_mutex_unlock之前 - 若栈中出现
__lll_lock_wait或__pthread_mutex_lock,说明该线程正在等锁;若停在__pthread_mutex_unlock或刚返回,可能是它持有了但没及时释放 - 用
info registers和x/gx $rdi(x86_64 下$rdi通常是 mutex 地址)查看锁结构体内容,检查__data.__owner字段是否非零(即有持有者线程 ID) - 若程序带调试符号,可直接
p *$rdi打印整个pthread_mutex_t结构,观察__owner、__nusers、__kind(判断是否递归锁)
为什么 pstack / cat /proc/pid/stack 不够用
pstack 和 /proc//stack 只显示内核态调用栈(scheduler、futex、sys_futex 等),看不到用户态函数名和锁变量地址,对定位锁竞争帮助有限。