[原]调试excel启动时死锁

这是继前两篇死锁文章之后的第三篇文章,依然是使用windbg进行调试。欢迎各位阅读,希望对你有所帮助。我列出了前两篇文章的链接,方便各位查看。

[原]调试DLL卸载时的死锁

[原]调试TerminateThread导致的死锁


前言

这是几年前在项目中遇到的一个死锁问题。本文假设小伙伴们知道一些基本概念。比如,什么是.dump文件(转储文件,进程在某一时刻的快照),什么是windbgwindows下的调试利器),windbg的基本命令,调用栈,调用约定,等等。

背景介绍

我们的程序会把dll注入到其它进程,然后后调用SetWinEventHook安装进程内钩子。然后专门开启一个线程来分发监听到的事件信息,并在该线程内会获取IAccessible接口并使用该接口获取感兴趣的属性(e.g. 按钮的标题,按钮的位置等等)。运行我们的程序后,再启动excel,有时候会导致excel卡死,本文分析的.dump文件就是其中一次卡死时抓取的。背景介绍完毕,下面开始分析.dump

问题分析

首先,我们用windbg打开.dump文件,因为当时没截图,这里就不放图了。

因为是UI线程卡死,而且一般情况下,第一个线程就是UI线程,所以我们使用~0s命令来切换到UI线程。

然后用kv命令列出调用栈,因为比较长,这里只用了kv10,列出前16个栈帧(windbg默认是16进制)。

我们发现0号线程进入关键段时卡住了,在等待值为0x544的句柄,猜测应该是关键段内部的LockSemaphore(类型为的event,可以通过!handle 0x544来验证,之前忘记截图了,这里就不放图了),我们可以用命令!cs 76b18770来观察关键段76b18770的内容。

通过OwningThread字段我们可以知道关键段76b18770被线程0x000001ac占用着,而0号线程的线程id0x00000de4

我们可以通过? $tid来观察当前线程的id(因为我们之前用~0s切换到0号线程了,所以观察到的是0号线程对应的id

我们切换到线程id0x000001ac的线程看看, 可以使用~~[native_thread_id]s来根据线程id切换线程。输入~~[0x000001ac]s;kv

从上图可知,线程0x000001ac正是我们新建的线程。从调用栈可知,本线程正在取name属性。但是因为某些原因触发了异常!frame 2表示正在调用SuspendThread挂起句柄为fffffffe的线程!也就是当前线程!!!我们可以反汇编KERNELBASE!GetCurrentThread来验证。输入uf KERNELBASE!GetCurrentThread

小结

0号线程尝试进入关键段76b18770,而关键段76b18770正在被线程id0x000001ac的线程占用着,该线程又由于某些异常将自己挂起了!于是????死锁了!!!

提示

windbg有一个很有用的命令可以帮助我们快速找到死锁的关键段!

输入!cs -l

我们也可以从上图中看到线程0x000001ac拥有着关键段76b18770

后记

windbg可谓是windows下调试的神兵利器。熟练掌握windbg是每一个优秀的windows开发人员必备的技能!而掌握windbg中的各种命令是掌握windbg的基础。今天的命令你掌握了吗?

参考资料

  • 《格蠹汇编》

  • windbg 帮助文件

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值