背景
在开发项目的一个feature时,发现有一个线程hang住,一直无法向元数据管理模块发送心跳,导致线程所在的机器被drop掉,组里的一个同学使用gdb找到了hang住的原因,于是自己也决定学一下这种方法。
测试程序
启动两个线程,竞争互斥锁,其中一个线程拿到锁之后不释放,两个线程因为死锁必然会卡住,利用gdb找到每个线程hang住的位置。
步骤
-
为了生成调试信息,编译的时候加上-g选项。
-
后台启动main程序,查看main进程的进程id,779131。
-
查看进程内的所有线程。779131是main线程id(也是进程id),779132和779133是main线程启动的两个线程id,就是代码中的thread1和thread2。
-
用gdb attach main调试main进程。main线程启动的两个新线程id,如下图所示。
-
用info threads命令查看所有线程。最前面的*号表示当前线程。
-
用thread n命令切换线程,用bt命令检查每个线程的栈信息。可以看到线程一直阻塞在main.cpp的第10行,而第10行正是mu.lock()加锁的行,同样的方法可以找到另一个线程阻塞的位置。
总结
- pstree -p ${pid}可以查看进程的所有线程关系。
- gdb attach ${pid}可以调试已经启动的进程。
- gdb中执行info threads可以查看所有的线程信息
- gdb中执行thread n可以切换当前线程,通过bt命令查看当前线程的栈信息。
下一步
特意阅读了下《Debugging with GDB》,书中有关多线程调试的章节还是挺多的,但是都没有结合例子说明,阅读的难度对我来说还是挺大的,只能自己google+尝试实践。