原调试debugwindbg死锁deadlock

前言

这是几年前在项目中遇到的一个死锁问题,在博客园发布过。我对之前的笔记进行了整理重新发布于此。

本文假设小伙伴们知道一些基本概念,比如什么是.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的线程看看, 可以使用~~[0x000001ac]s来根据线程id切换线程。输入~~[0x000001ac]s;kv



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

小结

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

提示

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

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

后记

windbg可谓是windows下分析各种疑难杂症的神兵利器,熟练掌握windbg是每一个优秀的windows开发人员必备的技能!而掌握windbg中的各种命令是掌握windbg的基础。

参考资料

  • 《格蠹汇编》
  • windbg帮助文件

[原]调试实战——使用windbg调试excel启动时死锁的更多相关文章

  1. [原]调试实战——使用windbg调试TerminateThread导致的死锁

    原调试debugwindbg死锁deadlock 前言 项目里的一个升级程序偶尔会死锁,查看dump后发现是死在了ShellExecuteExW里.经验少,不知道为什么,于是在高端调试论坛里发帖求助, ...

  2. [原]调试实战——使用windbg调试DLL卸载时的死锁

    原调试debugwindbg死锁deadlock 前言 最近我们的程序在退出时会卡住,调查发现是在卸载dll时死锁了.大概流程是这样的:我们的dll在加载的时候会创建一个工作线程,在卸载的时候,会设置 ...

  3. [原]调试实战——使用windbg调试崩溃在ole32!CStdMarshal::DisconnectSrvIPIDs

    原调试debugwindbg崩溃crash 前言 最近程序会不定期崩溃,很是头疼!今晚终于忍无可忍,下决心要干掉它!从之前的几个相关的dump可以猜到是有接口未释放导致的问题,但没有确认到底是哪个接口 ...

  4. [原]调试实战——使用windbg调试崩溃在ComFriendlyWaitMtaThreadProc

    原调试debugwindbgcrash崩溃COM 前言 这是几年前在项目中遇到的一个崩溃问题,崩溃在了ComFriendlyWaitMtaThreadProc()里,没有源码.耗费了我很大精力,最终通 ...

  5. [原]excel启动时死锁

    项目中遇到的一个死锁问题!   代码大概如下: 调用SetWinEventHook安装了进程内钩子,dll注入到excel进程后,专门开启一个线程来分发监听到的事件信息,并在该线程内会获取IAcces ...

  6. .NET高级调试系列-Windbg调试入门篇

    Windbg是.NET高级调试领域中不可或缺的一个工具和利器,也是日常我们分析解决问题的必备.准备近期写2篇精华文章,集中给大家分享一下如果通过Windbg进行.NET高级调试. 今天我们来一篇入门的 ...

  7. 【转】WinDbg调试器:启动程序时自动连接调试器方法

    当我们调试服务进程或子进程时,无法直接用调试加载进程的方式启动,此时需要在启动程序时自动连接调试器方法: 第一步:注册表展开到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft ...

  8. Windbg调试命令详解

    作者:张佩][原文:http://www.yiiyee.cn/Blog] 1. 概述 用户成功安装微软Windows调试工具集后,能够在安装目录下发现四个调试器程序,分别是:cdb.exe.ntsd. ...

  9. Windbg调试命令详解(1)

    转载注明>> [作者:张佩][镜像:http://www.yiiyee.cn/Blog] 1. 概述 用户成功安装微软Windows调试工具集后,能够在安装目录下发现四个调试器程序,分别是 ...

随机推荐

  1. 【数据库】SQL 关系代数

    环境:MySQL ID:MySQL WorkBench 6.3 CE 实现以下有点难度的关系除法. 先给定义: 除运算是同时从关系的水平方向和垂直方向进行运算.给定关系R(X,Y)和S(Y,Z),X. ...

  2. C语言之结构体概述

    C语言之结构体概述1.结构体类型是一种自定义类型(1)C语言中有2种类型:原生类型和自定义类型.2.结构体使用时先定义结构体类型再用类型定义变量(1)结构体定义时需要先定义结构体类型,再用类型来定义变 ...

  3. JZOJ-2019-11-5 A组

    T1 给定由 n 个点 m 条边组成的无向连通图,保证没有重边和自环. 你需要找出所有边,满足这些边恰好存在于一个简单环中.一个环被称为简单环,当且仅当它包含的所有点都只在这个环中被经过了一次.(即求 ...

  4. SpringCloud学习之Stream消息驱动【自定义通道】(十一)

    如果不清楚本篇内容的,请务必先去看完上一篇再看本篇,否则阅读起来可能会有部分障碍和困难: 上一篇文章<SpringCloud学习之Stream消息驱动[默认通道](十)>我们简单用自定义通 ...

  5. OpenCV2基础操作----直线、矩形、圆、椭圆函数的使用

    opencv2几个画图函数的调用 要用到几个随机变量: int fr = rand()%frame.rows; int fc = rand()%frame.cols; int b = rand()%2 ...

  6. JVM探秘:jstat查看JVM统计信息

    本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. jstat命令用来查看JVM统计信息,可以查看类加载信息.垃圾收集的信息.JIT编译信 ...

  7. nodejs(7)练习 http 和 express 创建简单的服务器

    http const http = require('http') // 创建服务器 const server = http.createServer() // 绑定事件,监听客户端的请求 serve ...

  8. UVA 11468 AC 自动机

    首先我们应该是枚举 L个位置上的每个字符来得到最终概率 然后AC自动机的作用就是为了判断你枚举的地方是否对应了单词节点,如果对应了,就肯定要不得 #include <iostream> # ...

  9. UVA 10891 SUM游戏 DP

    刚看到这个题目不知道怎么个DP法,有点难想到 解法如下 设置dp[i][j]代表i到j这段子序列能获得的最大值,这样,枚举m=min(m,dp[i+1到j][j],dp[i][i到j-1]),m就代表 ...

  10. dockerfile---apt-get install vim 时 Unable to locate package vim

    在学习 dockerfile 的时候,发现编写的 Dockerfile 中的 apt-get install 命令无法找到要安装的包,所以记录一下这次发生的错误. 环境:宿主机:windows 10 ...