最近跟踪了一个程序的界面卡死问题,该卡死偶尔出现,在抓到一次dump后用windbg载入分析,打印出函数调用堆栈后,一眼可以看出是临界区死锁了。

代码:
0:000:x86> kb
ChildEBP RetAddr  Args to Child              
0032dd0c 779ed993 00000710 00000000 00000000 ntdll_779b0000!NtWaitForSingleObject+0x15
0032dd70 779ed877 00000000 00000000 024023f0 ntdll_779b0000!RtlpWaitOnCriticalSection+0x13e
0032dd98 58a2fac3 02404c50 856fd57e 024023f0 ntdll_779b0000!RtlEnterCriticalSection+0x150
0032dffc 58a0d4d7 856fea8a 00000000 001c41a0 SogouSoftware_589d0000!CDownloadListUI::UpdateDownloadListUI+0x43

输出该临界区的信息:

代码:
0:000:x86> !cs 02404c50
-----------------------------------------
Critical section   = 0x0000000002404c50 (+0x2404C50)
DebugInfo          = 0x0000000000611e08
LOCKED
LockCount          = 0xFFFFFFFF
WaiterWoken        = Yes
OwningThread       = 0x0000000000000710
RecursionCount     = 0x1A38
LockSemaphore      = 0x2433B08
SpinCount          = 0x0000000000000000

Windbg指示是0x710号线程占有该临界区在,于是看看0x710号线程是那一个,结果发现报错,一般这种情况是线程已经退出或者被终止掉了。

代码:
0:000:x86> ~~[710]
                 ^ Illegal thread error in '~~[710]'

该临界区死锁的位置部分代码如下:

代码:
void CDownloadListUI::UpdateDownloadListUI()
{
  m_vctLock.Lock();
  vector<int> vecDeleteItems(GetCount());  // record index to be delete
  std::iota(vecDeleteItems.begin(), vecDeleteItems.end(), 0);
  ......
  m_vctLock.UnLock();
}

m_vctLock是ATL一个对临界区简单封装的类,让同事仔细对m_vctLock所有加锁的位置进行检查,发现除了主线程外只有另外一个工作线程会使用,用windbg查了下改工作线程并未退出,线程ID也不为 0x710,难道又被Windbg给忽悠了?打印下该临界区的数据结构看看:

代码:
0:000:x86> dt _RTL_CRITICAL_SECTION 02404c50
DuiLib!_RTL_CRITICAL_SECTION
   +0x000 DebugInfo        : 0x00611e08 _RTL_CRITICAL_SECTION_DEBUG
   +0x004 LockCount        : 0n-6
   +0x008 RecursionCount   : 0n1
   +0x00c OwningThread     : 0x00001a38 Void
   +0x010 LockSemaphore    : 0x00000710 Void
   +0x014 SpinCount        : 0

发现这里显示的拥有者线程号和上面不一致,试试看是那个线程:

代码:
0:000:x86> ~~[1a38]
   6  Id: 2058.1a38 Suspend: 0 Teb: 7ef94000 Unfrozen
      Start: SogouSoftware_589d0000!_threadstartex (58a5192d) 
      Priority: 0  Priority class: 32  Affinity: f
0:000:x86> ~6s
ntdll_779b0000!ZwWaitForMultipleObjects+0x15:
779d019d 83c404          add     esp,4
0:006:x86> kb
ChildEBP RetAddr  Args to Child              
0370fa5c 768615f7 00000002 0370faac 00000001 ntdll_779b0000!ZwWaitForMultipleObjects+0x15
0370faf8 773519f8 0370faac 0370fb20 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x100
0370fb40 773541d8 00000002 7efde000 00000000 kernel32!WaitForMultipleObjectsExImplementation+0xe0
0370fb5c 589f6ba0 00000002 0370fb84 00000000 kernel32!WaitForMultipleObjects+0x18
0370fbd4 58a51907 58aab894 862df68e 00000000 SogouSoftware_589d0000!CThreadQueue<TagDownloadTask>::ThreadProc+0x100 
0370fc0c 58a51991 00000000 0370fc24 7735336a SogouSoftware_589d0000!_callthreadstartex+0x1b [f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c @ 314]
0370fc18 7735336a 023f5170 0370fc64 779e9882 SogouSoftware_589d0000!_threadstartex+0x64 [f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c @ 292]
0370fc24 779e9882 023f5170 771cc6bb 00000000 kernel32!BaseThreadInitThunk+0xe
0370fc64 779e9855 58a5192d 023f5170 00000000 ntdll_779b0000!__RtlUserThreadStart+0x70
0370fc7c 00000000 58a5192d 023f5170 00000000 ntdll_779b0000!_RtlUserThreadStart+0x1b

6号线程正处于等待任务中,对照代码,6号线程有一个观察者的回调函数会调用到CDownloadListUI类中的m_vctLock锁,但是该回调函数已经执行完毕了。那么只有一种可能,就是锁泄露了,即Lock后没有解锁。再去看该回调函数,果然发现有一个很少出现的分支下没有调用Unlock释放临界区而直接返回了,这就造成了经典的锁泄露而引起死锁的bug。
  但 !cs 命令在此种情况下却给出了错误的信息,很容易造成误导而怀疑是一个拥有该锁的线程退出了而引起的。这应该算是Windbg的一个bug吧。
  进一步测试该情况,发现是当64位系统下的32位进程产生的dump会有此问题,32位系统下产生的dump使用 !cs 命令执行正常。

Windbg跟踪临界区的BUG的更多相关文章

  1. 缺陷跟踪系统Mantis Bug Tracker

    缺陷管理平台Mantis,也做MantisBT,全称Mantis Bug Tracker. 项目在github的地址:https://github.com/mantisbt/mantisbt Mant ...

  2. Windows系统上release版本程序bug跟踪解决方案-.dmp文件。

    使用场景: Win32程序在release模式下编译完成,发送给最终用户使用时,我们的程序有时候也会出现崩溃的情况,这个时候如果能快速定位崩溃原因或提供一些程序崩溃时的状态信息,对我们解决问题将会带来 ...

  3. 一个bug在redmine中的诞生到终结

    1.測试员測试出bug,跟踪状态为支持,状态为新建,指派给产品经理. 2.产品经理鉴定确觉得bug.改动跟踪状态为bug.指派给技术经理: 3.技术经理收到bug,指派给开发者: 4.开发者收到bug ...

  4. Android_通过Bugtags平台,方便測试人员提交bug及整个bug系统的管理

    Bugtags 是什么? Bugtags 是一款缺陷发现及管理工具. 当您的 App 集成了 Bugtags SDK 后,測试人员就可直接在 App 里所见即所得的提交 Bug. SDK 会自己主动截 ...

  5. 【测试基础第六篇】bug定义及生命周期

    bug定义 狭义:软件程序的漏洞或缺陷 广义:测试工程师或用户所发现和提出的软件可改进的细节(增强型.建议性)或需求文档存在差异的功能实现 职责:发现bug,提给开发,让其修改 bug类型--了解 代 ...

  6. Linux和Windows设备驱动架构比较

    毕业后一直在学操作系统, 有时候觉得什么都懂了,有时候又觉得好像什么都不懂,但总体来说自认为对操作系统实现机制的了解比周围的人还是要多一些.去年曾花了几个星期的晚上时间断断续续翻译了这篇对Linux和 ...

  7. .NET对象与Windows句柄(三):句柄泄露实例分析

    在上篇文章.NET对象与Windows句柄(二):句柄分类和.NET句柄泄露的例子中,我们有一个句柄泄露的例子.例子中多次创建和Dispose了DataReceiver和DataAnalyzer对象, ...

  8. NetHogs下载和监控

    转自:http://blog.csdn.net/testcs_dn/article/details/40506225 CentOS6.5下使用NetHogs监控进程网络使用情况 分类: CentOS2 ...

  9. Bugtags,产品经理的瑞士军刀

    做为设计移动应用的产品经理,每天的主要工作就是在手机上不停的体验自己的产品,发现问题.优化体验.你是否经常工作在这样的尴尬场景: 发现界面问题,将问题界面截屏传到电脑,用图片标记工具将问题标记出来,然 ...

随机推荐

  1. jQuery弹出深色系层菜单

    低调奢华jQuery弹出层菜单,使用新版的jQuery库,兼容多种浏览器.Demo展示: http://hovertree.com/texiao/layer/3/ 本特效可以作为网站的引导页,使用jQ ...

  2. python读取文件的方法

    一. 通过readline 逐行读取: #--encoding:utf-8 with open("ha.conf","r",encoding='utf-8') ...

  3. linux系统下make & make install

    make,make install都是典型的使用GNU的AUTOCONF和AUTOMAKE产生的程序的安装步骤. make是用来编译的,在命令行输入make命令之后,系统会在当前目录下搜索Makefi ...

  4. Oracle内置函数:时间函数,转换函数,字符串函数,数值函数,替换函数

    dual单行单列的隐藏表,看不见 但是可以用,经常用来调内置函数.不用新建表 时间函数 sysdate 系统当前时间 add_months 作用:对日期的月份进行加减 写法:add_months(日期 ...

  5. 流的文件操作(File)

    一.流的分类: 1.流按照方向分类:分为输入流和输出流,流的操作是相对于内存而言. 输入流的定义:当我们从数据源中将数据读取到内存中就称为输入流,也叫读取流. 输出流的定义:当我们将内存中处理好的数据 ...

  6. 【Java学习系列】第1课--Java环境搭建和demo运行

    本文地址 分享提纲: 1. java环境的搭建 2. java demo代码运行 3.参考文档 本人是PHP开发者,一直感觉Java才是程序的王道(应用广,科班出身),所以终于下决心跟一跟. 主要是给 ...

  7. 用好spring mvc validator可以简化代码

    表单的数据检验对一个程序来讲非常重要,因为对于客户端的数据不能完全信任,常规的检验类型有: 参数为空,根据不同的业务规定要求表单项是必填项 参数值的有效性,比如产品的价格,一定不能是负数 多个表单项组 ...

  8. 取消IE默认下载工具为迅雷

    需求:企业访问内部WEB系统下载文件时,IE默认下载工具设置为迅雷,则弹出迅雷下载框.现需要直接弹出IE下载保存框. 方案:打开迅雷,进行撤销默认下载工具. 1.迅雷5: 1.1. 打开迅雷下载工具 ...

  9. 【单页应用】理解MVC

    前言 之前我们为view引入了wrapperSet的概念,想以此解决view局部刷新问题,后来发现这个方案不太合理 view里面插入了业务相关的代码,事实上这个是应该剥离出去,业务的需求千奇百怪,我们 ...

  10. 友盟(Swift)-集成、统计用户数量、具体页面访问数量、具体按钮点击数量

    什么是友盟.有什么用? 这些傻瓜问题这里就不解释了,可以自己百度去. 友盟提供的文档和demo都是oc的,这里用swift写了一个小demo,在此分享一下. 步骤1:友盟后台注册应用(iOS),拿到a ...