Windbg找出死锁
前言
本文介绍本人的一次使用Windbg分析dump文件找出死锁的过程,并重点介绍如何确定线程所等待的锁及判断是否出现了死锁。
对于如何安装及设置Windbg请参考:《使用Windbg和SoS扩展调试分析.NET程序》http://www.cnblogs.com/shanyou/archive/2006/12/23/601004.html
起因
今天,部署到生产环境中的软件再次发生了不响应请求的问题,看了系统日志与软件本身的log都没发现异常,而在任务管理器中软件占用了1G多的内存,有点偏高(正常是300M左右)。由于本人不在现场,只能通过远程的方式查看,同时故障出现间隔比较长(将近一周),在生产环境中也就无法使用VS进行调试。
无意中在资源监视器的CPU页看到软件的线程数是1.7万个,内存页的提交内存使用也将近18G,同时线程数与提交内存也在缓慢增加。当时就想是不是由于某种原因导致线程无法退出从而在线程数太多的时候致使软件不响应请求(后来的调试也证实是死锁导致的)。
由于故障难以重现(只在生产环境中长时间运行才会出现,在测试环境无法出现),只能对正在运行的软件进行分析。
这时候就请出了大名鼎鼎的Windbg,下面是详细的过程。
过程
一、抓取dump文件
抓取dump的方法,可以参考《抓取user mode dump文件的几重境界》http://www.cnblogs.com/pugang/archive/2013/02/18/2916211.html
我选择的是使用图形化操作的方式,在任务管理器的进程页中,右键需要抓取的程序,选择“创建转储文件”
运行完成后将会弹出成功对话框并提示dump文件的所在
二、在Windbg中加载dump文件与SOS.dll
运行Windbg,在File菜单下选择Open Crash Dump,选择上面抓取的dump文件
在Windbg下侧的命令输入框中输入“.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos”并回车加载SOS.dll。由于我是调试net4.0 64位的软件,所以使用了Framework64\v4.0.30319下的sos,其它版本请选择对应位置的sos进行加载
三、使用Windbg查找死锁
使用“!threads”命令列出所有的线程,发现一共存在17306个线程
使用“~17306s”命令切换到最后一个线程,并使用“!clrstack”命令输出当前线程的调用堆栈,发现存在“System.Threading.Monitor.Enter(System.Object)”,表明线程正在请求一个锁。由于得不到锁,因此线程卡死
切换到其它线程查看调用堆栈,都是因为同样的原因导致线程卡死,这时候可以初步判断这些线程是因为死锁导致执行不下去
使用“!syncblk”命令列出所有正在使用的锁,其中MonitorHeld与Recursion列表示了请求锁的线程数量情况,Info列表示哪个线程拥有了锁,SyncBlock列表示锁对象的地址。如MonitorHeld与Recursion的值为3775与1那行表示第40个线程拥有了这个锁,其它(3775-1)/2=1887个线程在等待锁,锁对象地址为0000000003c812f0。看到如此多的线程在请求同一个锁,就知道情况不正常,看来离死锁的真相又近了一步
接下来的过程就是:找到某个线程(如线程A)请求的锁(如锁J),查看哪个线程(如线程B)拥有这个锁(锁J)及这个线程请求的锁(锁K),接着查看哪个线程(如线程C)拥有这个锁(锁K)及这个线程请求的锁(锁L),重复查看的过程,看最终是否有一个线程(如线程D)请求前面出现的任意一个锁(如线程B拥有的锁J),形成环状,这时即可判断其为死锁
这里从线程17306开始分析,使用“!clrstack -l”命令列出当前线程的调用堆栈及其使用的局部变量
在调用“System.Threading.Monitor.Enter(System.Object)”之前的一个方法内,应该存在作为局部变量的线程请求的锁对象
这里猜测下面的0000000003c812f0就是这个锁对象,通过查找上面的锁列表,确定了这个猜测,同时知道线程40拥有这个锁
使用“~40s”命令切换到线程40,并使用“!clrstack -l”命令列出当前线程的调用堆栈及其使用的局部变量,通过查找锁列表确定000000000317ac10为当前线程请求的锁对象,同时知道线程26拥有这个锁
同样使用“~26s”与“!clrstack -l”命令找到线程26请求的锁对象00000000044a81a8,这个锁对象被线程43拥有
接着使用“~43s”与“!clrstack -l”命令找到线程43请求的锁对象000000000317ac10,这个锁对象被线程26拥有
此时可以发现线程26与线程43之间形成了死锁
结果
终于真相大白了,上面的过程成功找到了死锁
也由此推断由于死锁的存在,导致后面新建的线程由于得不到请求的锁,一直不能执行下去,更不可能释放所占用的内存,从而使得线程数与内存占用在一直升高,直到软件无法响应请求为止
接下来的工作就是查看死锁线程的调用堆栈,结合软件源代码分析死锁形成时软件的运行情况,并更改处理逻辑以避免死锁的产生
Windbg找出死锁的更多相关文章
- 使用Windbg找出死锁,解决生产环境中运行的软件不响应请求的问题
前言 本文介绍本人的一次使用Windbg分析dump文件找出死锁的过程,并重点介绍如何确定线程所等待的锁及判断是否出现了死锁. 对于如何安装及设置Windbg请参考:<使用Windbg和SoS扩 ...
- Windbg找出memory leak的一种笨办法
以下内容是转自 http://www.cnblogs.com/fbird/p/5889596.html 以前做项目碰到过一个问题,在客户的站点上面发现有严重的内存泄漏.幸运的是我们找到了重现的步骤,一 ...
- 利用WinDbg找出程序崩溃的代码行号
之前碰到论坛里有几个好友,说程序不时的崩溃,什么xxoo不能read的! 如果光要是这个内存地址,估计你会疯掉~~ 所以分享一下基本的调试技巧,需要准备的工具有WinDbg + VC6.0, 下面是自 ...
- 用windbg+sos找出程序中谁占用内存过高,谁占用CPU过高(转载)
原文地址: http://www.cnblogs.com/Lawson/archive/2011/01/23/1942692.html 很早看到windbg+sos方面的知识,一直没仔细学习,也许因为 ...
- SQL Server如何找出一个表包含的页信息(Page)
在SQL Server中,如何找到一张表或某个索引拥有那些页面(page)呢? 有时候,我们在分析和研究(例如,死锁分析)的时候还真有这样的需求,那么如何做呢? SQL Server 2012提供了一 ...
- Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化
9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...
- 使用T-SQL找出执行时间过长的作业
有些时候,有些作业遇到问题执行时间过长,因此我写了一个脚本可以根据历史记录,找出执行时间过长的作业,在监控中就可以及时发现这些作业并尽早解决,代码如下: SELECT sj.name , ...
- [LeetCode] Find All Numbers Disappeared in an Array 找出数组中所有消失的数字
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...
- [LeetCode] Find All Duplicates in an Array 找出数组中所有重复项
Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others ...
随机推荐
- find your present (2) 2095
Problem Description In the new year party, everybody will get a "special present".Now it's ...
- 两个div横向排列,顶端对齐的方式。
1.左右两个div都设置为float:left,如果右边div没有设置宽度,右边div的宽度会根据div里的内容自动调整. <!DOCTYPE html PUBLIC "-//W3C/ ...
- 【淡墨Unity3D Shader计划】四 热带雨林的文章: 排除、深度测试、Alpha测试和基本雾编译
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://hpw123.net/a/C__/kongzhitaichengxu/2014/1222/163.html 作者:毛星云 ...
- HDU 4107 线段树
给出N个节点,M次操作,和p 每次操作 对l-r区间的每一个节点+c,若节点值>=p,则加2*c: 结点存当前区间伤害最小值,最大值,以及lazy操作.更新到假设最小值大于等于P,或者最大值小于 ...
- 用css2属性clip实现网页进度条
前言 看了网上一些关于网页进度条样式的资料,有很多方式实现,针对其展现形式,有用图片的,有用css2属性clip,有用flash的,本人就学会了一种,下面就简单来介绍一下. css2的属性clip 如 ...
- 再谈IE的浏览器模式和文档模式
原文:再谈IE的浏览器模式和文档模式 以前在 “IE8兼容视图(IE7 mode)与独立IE7的区别”一文中曾经涉及过浏览器模式和文档模式,但二者的区别却不甚了了,现在有了新的认识,再补充一下. 1. ...
- [转载]C#播放流媒体的几种方法
做视频开发要学的东西真多,不知道如何入门,乱打乱撞,慢慢摸索吧! 首先搭建Windows Meida Server ,方法很简单,试试就会.在这里需要声明的是,这几种方法 都可以播放 本地视频.并且基 ...
- gtest框架
解析gtest框架运行机制 1.前言 Google test是一款开源的白盒单元测试框架,据说目前在Google内部已在几千个项目中应用了基于该框架的白盒测试. 最近的工作是在搞一个基于gtest ...
- 运维自动化之SALTSTACK简单入门
运维自动化之SaltStack简单入门 饱食终日而无所事事,是颓也,废也.但看昨日,费九牛二虎之力除一BUG便流连于新番之中,不知东方之既黑,实乃颓颓然而荒废矣.故今日来缀一文以忏昨日之悔. Salt ...
- Asterisk 未来之路3.0_0006
原文:Asterisk 未来之路3.0_0006 Modules Asterisk 是基于模块构建的.一个模块提供某个特定的功能,它是动态的被装载.比如:信道驱动(chan_sip.so),或可以连接 ...