[原]调试实战——使用windbg调试excel启动时死锁
前言
这是几年前在项目中遇到的一个死锁问题,在博客园发布过。我对之前的笔记进行了整理重新发布于此。
本文假设小伙伴们知道一些基本概念,比如什么是.dump
文件(转储文件,进程在某一时刻的快照),什么是windbg
(windows
下的调试利器),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
号线程的线程id
是0x00000de4
。
我们可以通过? $tid
来观察当前线程的id
(因为我们之前用~0s
切换到0
号线程了,所以观察到的是0
号线程对应的id
)
我们切换到线程id
为0x000001ac
的线程看看, 可以使用~~[0x000001ac]s
来根据线程id
切换线程。输入~~[0x000001ac]s;kv
从上图可知,线程0x000001ac
正是我们新建的线程。从调用栈可知,本线程正在取name
属性。但是因为某些原因触发了异常!frame 2
表示正在调用SuspendThread
挂起句柄为fffffffe
的线程!也就是当前线程!!!我们可以反汇编KERNELBASE!GetCurrentThread
来验证。输入uf KERNELBASE!GetCurrentThread
小结
0
号线程尝试进入关键段76b18770
,而关键段76b18770
正在被线程id
为0x000001ac
的线程占用着,该线程又由于某些异常将自己挂起了!于是:bomb:!死锁了!!!
提示
windbg中有一个很有用的命令可以帮助我们快速找到死锁的关键段!输入!cs -l
我们也可以从上图中看到线程0x000001ac
拥有着关键段76b18770
。
后记
windbg可谓是windows
下分析各种疑难杂症的神兵利器,熟练掌握windbg是每一个优秀的windows
开发人员必备的技能!而掌握windbg中的各种命令是掌握windbg的基础。
参考资料
- 《格蠹汇编》
- windbg帮助文件
[原]调试实战——使用windbg调试excel启动时死锁的更多相关文章
- [原]调试实战——使用windbg调试TerminateThread导致的死锁
原调试debugwindbg死锁deadlock 前言 项目里的一个升级程序偶尔会死锁,查看dump后发现是死在了ShellExecuteExW里.经验少,不知道为什么,于是在高端调试论坛里发帖求助, ...
- [原]调试实战——使用windbg调试DLL卸载时的死锁
原调试debugwindbg死锁deadlock 前言 最近我们的程序在退出时会卡住,调查发现是在卸载dll时死锁了.大概流程是这样的:我们的dll在加载的时候会创建一个工作线程,在卸载的时候,会设置 ...
- [原]调试实战——使用windbg调试崩溃在ole32!CStdMarshal::DisconnectSrvIPIDs
原调试debugwindbg崩溃crash 前言 最近程序会不定期崩溃,很是头疼!今晚终于忍无可忍,下决心要干掉它!从之前的几个相关的dump可以猜到是有接口未释放导致的问题,但没有确认到底是哪个接口 ...
- [原]调试实战——使用windbg调试崩溃在ComFriendlyWaitMtaThreadProc
原调试debugwindbgcrash崩溃COM 前言 这是几年前在项目中遇到的一个崩溃问题,崩溃在了ComFriendlyWaitMtaThreadProc()里,没有源码.耗费了我很大精力,最终通 ...
- [原]excel启动时死锁
项目中遇到的一个死锁问题! 代码大概如下: 调用SetWinEventHook安装了进程内钩子,dll注入到excel进程后,专门开启一个线程来分发监听到的事件信息,并在该线程内会获取IAcces ...
- .NET高级调试系列-Windbg调试入门篇
Windbg是.NET高级调试领域中不可或缺的一个工具和利器,也是日常我们分析解决问题的必备.准备近期写2篇精华文章,集中给大家分享一下如果通过Windbg进行.NET高级调试. 今天我们来一篇入门的 ...
- 【转】WinDbg调试器:启动程序时自动连接调试器方法
当我们调试服务进程或子进程时,无法直接用调试加载进程的方式启动,此时需要在启动程序时自动连接调试器方法: 第一步:注册表展开到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft ...
- Windbg调试命令详解
作者:张佩][原文:http://www.yiiyee.cn/Blog] 1. 概述 用户成功安装微软Windows调试工具集后,能够在安装目录下发现四个调试器程序,分别是:cdb.exe.ntsd. ...
- Windbg调试命令详解(1)
转载注明>> [作者:张佩][镜像:http://www.yiiyee.cn/Blog] 1. 概述 用户成功安装微软Windows调试工具集后,能够在安装目录下发现四个调试器程序,分别是 ...
随机推荐
- NRF24L01中断双向传输数据
NRF24L01是一款比较常见的无线通讯芯片,不过有个缺点就是只能半双工通讯,当涉及到双向通讯时就比较麻烦一些·,特别是想要做无线IAP数据需要一直来回发送,这点无疑然人恶心到想吐,不过还好有数据中断 ...
- SQL基础教程(第2版)第7章 集合运算:7-1 表的加减法
第7章 集合运算:7-1 表的加减法 ● 集合运算就是对满足同一规则的记录进行的加减等四则运算.● 使用UNION(并集). INTERSECT(交集). EXCEPT(差集)等集合运算符来进行集合运 ...
- Thread--线程间通信--管道
在Java语言中提供了各种各样的输入/输出流Stream,使我们能够方便的对数据进行操作,其中管道流是一种特殊的流,用于在不同线程间直接传送数据.一个线程发送数据到输出管道,另一个线程从输入管道中读数 ...
- 关于scala工程结构(使用sbt)
scala_project:常用目录结构: |lib:手动添加依赖包 |project | |build.properties:build的版本号,可以不写,会自动下载 | |plugins.sbt: ...
- 自动生成返回Json数据的toString()方法
平时书写实体类方法的时候,想要获取的值直接返回Json字符串,以便使用,可以直接在Eclipse里面生成. 实现步骤: 1.快捷键Alt+S 2.选择Edit 3.添加字段,名称随意(我的为JsonS ...
- sudo: /etc/sudoers is mode 0777, should be 0440 单用户 sudo不用输入密码的方法
sudo权限问题考察一题 su - sudo su - sudo su - test [root@localhost ~]# su - zzx #root用户进行切换不需要输入密码 [ ...
- Linux下常用的3种软件安装方式—rpm、yum、tar
一:Linux源码安装 1.解压源码包文件 源码包通常会使用tar工具归档然后使用gunzip或bzip2进行压缩,后缀格式会分别为.tar.gz与.tar.bz2,分别的解压方式: ...
- Java static的用法以及原理(06)
静态:static 用法:是一个修饰符,用于修饰成员(成员变量,成员函数), 当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调:类名.静态成员 类名.静态成员 存在:方 ...
- Git&GitHub 基本使用
如果是Windows用户需要自行去Git的官网下载Git工具 相信以您的聪明才知不需要一会就可以安装好Git工具了 博主这里是MacOS系统,本省就自带Git工具就不演示安装了 在完成一个简单的Git ...
- ImageTag,图片左上侧有一个小标签
这实现思路其实很简单 需求:1. 图片比原来的<div>大,需要切割图片.2. 图片左上角显示标签 解决思路: 1. 把照片设置成div的backgroundImage,然后用CSS3切割 ...