死锁问题调试-思路分析

今儿晚上碰到一死锁问题,之前定位没定位出来,讨论问题时被人指出来了,感觉很羞愧。

记录下,下次碰到类似死锁要有思路。

咱们死锁一般有两种情况,

1.线程A和线程B相互死锁。这种情况下,通过堆栈查找两个等待锁之间的依赖关系,还是比较好确定的。

2.线程A自死锁,造成这种死锁的情况是自己加了锁之后,还没来得及释放,下次又继续等锁,而这种锁刚好又不是递归锁,就会出现自死锁的情况。

针对于情况一:

一般思路,还是用gdb观察当前线程快照,如果现在功能卡住,而且gdb几次快照都在某个预期很快获取到锁的地方等锁,那么基本能确定是死锁。 那么,第二步就应该是获取该锁的ownerID,看这把锁到底是被哪个线程持有。ok,问题来了,如果这个时候gdb看不到ownerID,原因有很多(比如给你的就只有一个gdb快照,但是已经被定位为死锁,现场已经被破坏了,而且很难复现)怎么办?那么只好根据堆栈来查代码了,看上一层堆栈进入时,有进入什么锁。。。一层一层查,看能否能查到和另外那个互死锁的锁进锁的地方。好吧,我承认这个方法很low。

针对情况二:

猜想的原因有两种,一种是自己这段代码中在加锁后真的就没有完成锁释放,而且下次还能继续执行到加锁进入的代码入口。第二种,是锁的加锁和释放锁确实成对了,但是在加锁后,有可能被中断,而中断执行的中断函数(或者信号函数)也有这边锁的进入,就会造成自死锁。

很不幸,我今儿碰到的是第二种。而且只看到了堆栈,没法用gdb查看堆栈内变量的值,现场也已经被破坏掉了。从堆栈上和代码相结合我们看到了线程确实死锁了,因为锁不应该在这个地方长时间等待。

两个线程在等同一把锁,但是奇怪的是从代码上直接看,是看不到有其他线程能够持有这把锁的。所以一直被他们说持有这把锁的线程消失了。由于没有能复现,也没法查看占用锁的线程,所以当时就放过了这个问题。今儿开会过问题,被翻出来看了,结果被其他同事指出来了。

最关键的地方是:先看下死锁线程的更底层堆栈,看这些堆栈有进什么锁,或者什么操作会影响到锁。

这个问题的是,

frame 0:在信号处理函数中等待这把锁mutexM

frame1:进入这个信号处理函数B

gdb中提示<signal handler called>

frame2:write

frame3:函数A

按照刚才的思路,我们查看frame2,发现write接口之前即在函数A中是有进这把锁mutexM的,只是在宏里面被隐藏了。然后调用了write,在write时,信号中断了,调用了信号处理函数,这个函数中又要求进mutexM,然而此时函数A还未执行到mutexM的leave操作,因此出现了死锁。

另一个线程又刚好也在等这把锁,因此从堆栈上直接看上去,有两个线程都在等这把锁,但是没看到占有锁的线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值