开发者
资源
使用GDB调试C/C++程序进程卡死
使用GDB调试C/C++程序进程卡死
发表于2023/10/24
2.6k11

定位思路

image.png

1、使用top命令查看相关进程仍在运行,确认是进程卡死。

2、重新编译可调试版本,运行新版本,复现问题,GDB调试新版本。

3、分析堆栈信息及业务逻辑,找出卡死原因。

4、修改代码,重新编译进行验证。

      1)若问题解决,则确认修改,合入原代码。

      2)若问题未解决,增加定位信息,重新编译运行。

案例

问题现象:

某软件在服务器上运行出现卡死问题。

定位过程:

1、使用top命令查看进程仍存在,确认是卡死问题。

2、重新编译该程序为可调试版本,重新运行,复现问题,查询该进程PID号。

3、进入到程序的调测模式。

gdb attach 2573

说明:2573为该程序PID号。

image.png

4、开启日志,将堆栈信息导出到文件。

set logging file core_info.log
set logging on
thread apply all bt

5、查看线程状态。

info threads

image.png

绝大部分线程都处在等待状态__lll_lock_wait。其中,等待的锁变量主要有两个,resource1和resource2。

6、通过print命令查看,两个锁变量的信息。其中__owner表示当前该锁的持有者线程ID。

image.png

可见,resource1由线程3889持有未释放,resource2由线程3892持有未释放。

7、从上述收集的日志文件中找到ID为3889和3892的线程日志。

image.png

从这两个线程的状态信息可以看出,3889号线程持有了锁resource1,但是本身在请求resource2;而3892号线程持有了锁resource2,但是本身在请求resource1。这两个线程的锁调用关系构成了死锁条件导致无法退出,同时,其他所有依赖这两个锁的线程都陷入了等待状态。

8、根据上述堆栈信息,是threadOne和threadTwo直接相互调用导致死锁,查看业务代码逻辑,修改代码,重新编译,运行,问题未复现,确认修改代码合入,验证问题解决。

收藏举报
Level 1
0
帖子
0
粉丝
0
获赞