操作系统 | 核心数 |
---|---|
centos 3.10.0 | 32位单核 |
gbd调试方法-以线程运行时调试为例
- 线程死锁状态时查看栈
- 升级gbd
- 通过gdb在程序运行时进行调试
线程死锁状态时查看栈
在线程-线程安全之互斥中,我们自己写了一个模拟实现的线程死锁情况
我们用gbd调试查看了当前线程的调用,仅仅能知道当前线程处于lock_wait请求锁阻塞状态,
我们不知道当前线程持有哪把锁,被阻塞的锁是什么,那么首先需要将gbd调试工具升级一下了
升级gbd
升级gbd调试工具(升级后可以看到当前线程加的是哪把锁)
1.先修改"/etc/yum.repos.d/CentOS-Debuginfo.repo"文件的 enable=1;有时候该文件不存在,则需要手工创建此文件并加入以下内容:
[debug]
name=CentOS-7 - Debuginfo
baseurl=http://debuginfo.centos.org/7/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Debug-7
enabled=1
2.执行sudo yum install -y glibc
3.执行sudo debuginfo-install glibc
升级完成后,再次调用pstack [pid]
就能看到当前的线程加的是哪把锁了。
我们现在可以知道当前线程要加哪把锁了,但是不知道当前线程已经加了哪把锁
通过gdb在程序运行时进行调试
首先在makefile文件中需要加入两个命令行参数:-lpthread -g
分别表示需要链接线程库和需要进行gbd调试。
运行起来之后,
-
gdb attach[pid]
-
thread apply all bt
(展示所有线程的调用堆栈)
-
t 3
(展示线程3的当前堆栈)
-
bt
(展示当前线程的调用堆栈)
-
由于线程A拿不到B锁,所以查看当前线程A的调用堆栈
f 3
-
查看锁B,以此来看为什么线程A拿不到锁B
p lock_B
通过查看锁B,发现锁B的owner是线程号为30072的线程持有,回看线程ID,发现30072是线程B。意味着当前的B锁是被线程B持有的。而线程A在请求由线程B持有的锁,故线程A一直在等待。
至此,终于知道了为何当前程序运行起来后就卡死了,由于当前线程中AB线程分别拿着自己的AB锁,又在同时请求对方的BA锁,这时造成了死锁。