DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

背景

在开发项目的一个feature时,发现有一个线程hang住,一直无法向元数据管理模块发送心跳,导致线程所在的机器被drop掉,组里的一个同学使用gdb找到了hang住的原因,于是自己也决定学一下这种方法。

测试程序

启动两个线程,竞争互斥锁,其中一个线程拿到锁之后不释放,两个线程因为死锁必然会卡住,利用gdb找到每个线程hang住的位置。 image.png

步骤

  1. 为了生成调试信息,编译的时候加上-g选项。 image.png

  2. 后台启动main程序,查看main进程的进程id,779131。 image.png

  3. 查看进程内的所有线程。779131是main线程id(也是进程id),779132和779133是main线程启动的两个线程id,就是代码中的thread1和thread2。 image.png

  4. 用gdb attach main调试main进程。main线程启动的两个新线程id,如下图所示。 image.png

  5. 用info threads命令查看所有线程。最前面的*号表示当前线程。 image.png

  6. 用thread n命令切换线程,用bt命令检查每个线程的栈信息。可以看到线程一直阻塞在main.cpp的第10行,而第10行正是mu.lock()加锁的行,同样的方法可以找到另一个线程阻塞的位置。 image.png

总结

  • pstree -p ${pid}可以查看进程的所有线程关系。
  • gdb attach ${pid}可以调试已经启动的进程。
  • gdb中执行info threads可以查看所有的线程信息
  • gdb中执行thread n可以切换当前线程,通过bt命令查看当前线程的栈信息。

下一步

特意阅读了下《Debugging with GDB》,书中有关多线程调试的章节还是挺多的,但是都没有结合例子说明,阅读的难度对我来说还是挺大的,只能自己google+尝试实践。

posted on 2023-03-14 20:04  DoubleLi  阅读(472)  评论(0编辑  收藏  举报