C/C++进程卡死
定位思路
C/C++进程未按预期执行,进程仍在后台运行,这种情况称为进程卡死,它往往是由于死锁或者进程进入死循环导致的。定位思路如C/C++进程卡死所示。
图1 C/C++进程卡死问题定位思路


- 使用top命令查看相关进程仍在运行,确认是进程卡死。
- 重新编译可调试版本,运行新版本,复现问题,GDB调试新版本。
- 分析堆栈信息及业务逻辑,找出卡死原因。
- 修改代码,重新编译进行验证。
- 若问题解决,则确认修改,合入原代码。
- 若问题未解决,增加定位信息,重新编译运行。
案例
问题现象:
某软件在服务器上运行出现卡死问题。
定位过程:
- 使用top命令查看进程仍存在,确认是卡死问题。
- 重新编译该程序为可调试版本,重新运行,复现问题,查询该进程PID号。
- 进入到程序的调测模式。
gdb attach 2573
2573为该程序PID号。
- 开启日志,将堆栈信息导出到文件。
1 2 3
set logging file core_info.log set logging on thread apply all bt
- 查看线程状态。
1
info threads
绝大部分线程都处在等待状态__lll_lock_wait。其中,等待的锁变量主要有两个,resource1和resource2。
- 通过print命令查看,两个锁变量的信息。其中__owner表示当前该锁的持有者线程ID。
可见,resource1由线程3889持有未释放,resource2由线程3892持有未释放。
- 从上述收集的日志文件中找到ID为3889和3892的线程日志。
从这两个线程的状态信息可以看出,3889号线程持有了锁resource1,但是本身在请求resource2;而3892号线程持有了锁resource2,但是本身在请求resource1。这两个线程的锁调用关系构成了死锁条件导致无法退出,同时,其他所有依赖这两个锁的线程都陷入了等待状态。
- 根据上述堆栈信息,是threadOne和threadTwo直接相互调用导致死锁,查看业务代码逻辑,修改代码,重新编译,运行,问题未复现,确认修改代码合入,验证问题解决。
父主题: 疑难问题