windbg .net 程序的死锁检测 常用方法(个人备份笔记)

//死锁检测

.load sosex.dll

0:004> !dlk

0:000> !mk -a

The mk command displays a call stack of the currently selected thread (including both managed and unmanaged frames).
The command has now been extended to support the -a switch which outputs both the local variables as well as parameters
(combination of -l and -p switches):

0:003> !finq

  

The finq command (finalization queue) lists all the objects that are on the finalization queue. An example is shown below:

0:003> !frq -stat

  

The frq command (f-reachable queue) on the other hand, lists all objects that are on the f-reachable queue as shown below:

// 200b220 代表线程等待,可能是锁,或者 Sleep(), 这个要进一步检查。

0:046> !threads
ThreadCount:      54
UnstartedThread:  0
BackgroundThread: 22
PendingThread:    0
DeadThread:       9
Hosted Runtime:   no
                                           PreEmptive                                                   Lock
       ID  OSID        ThreadOBJ     State GC       GC Alloc Context                  Domain           Count APT Exception
   9    1  1644 0000000001412de0      8220 Enabled  0000000000000000:0000000000000000 0000000000311a20     0 Ukn
  17    2   528 000000000141f5d0      b220 Enabled  0000000000000000:0000000000000000 0000000000311a20     0 MTA (Finalizer)
  19    4  181c 00000000039853e0   100a220 Enabled  0000000000000000:0000000000000000 0000000000311a20     0 MTA (Threadpool Worker)
  20    5  221c 0000000003998d00      1220 Enabled  0000000000000000:0000000000000000 0000000000311a20     0 Ukn
  21    6  16d8 00000000044484c0   200b220 Enabled  0000000000000000:0000000000000000 00000000039980a0     0 MTA
  22    7  1e54 0000000004460680   200b220 Enabled  0000000000000000:0000000000000000 00000000039980a0     0 MTA
  23    8  1308 000000000445fd20   200b220 Enabled  0000000000000000:0000000000000000 00000000039980a0     0 MTA
XXXX    9       00000000044b0510   1019820 Enabled  0000000000000000:0000000000000000 0000000000311a20     0 MTA (Threadpool Worker)
  25    a  1e50 00000000044e0e80   200b020 Enabled  0000000000000000:0000000000000000 00000000039980a0     0 MTA
  26    b  204c 000000000450b110   200b220 Enabled  0000000000000000:0000000000000000 00000000039980a0     0 MTA

  

0:000> !ThreadState 3009220
    Legal to Join
    Background
    CLR Owns
    In Multi Threaded Apartment
    Thread Pool Worker Thread
    Interruptible
0:000> !ThreadState 200b220
    Legal to Join
    Background
    CLR Owns
    CoInitialized
    In Multi Threaded Apartment
    Interruptible
0:000> !ThreadState 8009220
    Legal to Join
    Background
    CLR Owns
    In Multi Threaded Apartment
    Completion Port Thread

  

// threadstate详细: http://www.parallelfun.com/2012_11_01_archive.html

 0:050> !syncblk
Index         SyncBlock 		MonitorHeld Recursion 	Owning Thread Info          	SyncBlock Owner
   57 		000000000456f9e8            1         1 	0000000004567c30 1c98  46   	00000001800b6e90 System.Object
		Waiting threads:
  141 		00000000045702a8            1         1 	0000000004567c30 1c98  46   	00000001800b6f70 ProtoBufV2.Meta.BasicList
		Waiting threads:
-----------------------------
Total           152
CCW             3
RCW             2
ComClassFactory 0
Free            64

  

// 46号托管线程拥有一个Monitor, MonitorHeld 的计算方法:(MonitorHeld-1)/2 个线程等待 46号线程。
// 例如: 线程91 的 MonitorHeld 是39,则:(39-1)/2=19 表示有19个线程等待线程91
// 这里的MonitorHeld按msdn的解释,拿锁的线程为1,等锁的线程为2; Monitorheld的值是偶数,也说明已经没有线程拿住锁了。

/*
Sync Block 的信息:
通过!syncblk 索引值 可以显示Sync Block的信息,主要有如下信息
Index: Sync Block Table中的Index值
Sync Block: Sync Block的地址
MonitorHeld: numbers of monitor held
Recursion: 该线程获取该sync block的次数
Owning thread info : 总共有三个值,第一个值是线程的数据结构地址,第二个是线程的系统线程ID,第三个值为线程的托管线程ID
SyncBlock Owner:指向拥有该SyncBlock的对象的内存地址,也就是Object的地址
如果有第二个值指这个synblock第二个Held的类型
统计信息:
Total    152   (sync block table的总的sync Lock数量)
CCW    3     (CCW(COM Callable Wrappers)对象拥有的sync block 数量)
RCW    2       (RCW(Runtime Callable Wrappers )对象拥有的sync block 数量)
ComClassFactory 0
Free 64 Sync block table 剩余的空索引的数量

*/

/*

http://blogs.msdn.com/b/oldnewthing/archive/2006/12/12/1266392.aspx

!syncblock 详细解释和 !critsec 使用
http://blogs.msdn.com/b/tess/archive/2006/01/09/a-hang-scenario-locks-and-critical-sections.aspx
*/

0:044> !syncblk
Index         SyncBlock MonitorHeld Recursion Owning Thread Info          SyncBlock Owner
 2193 000000000598fe18            5         1 000000000a4650e0 3038 110   00000001bff69770 System.Object
		Waiting threads: 90 121
 2616 000000000577db08          133         0 0000000000000000     none    000000011fc6aa30 System.RuntimeType+RuntimeTypeCache+MemberInfoCache`1[[System.Reflection.RuntimeMethodInfo, mscorlib]]
		Waiting threads: 39 40 42 48 49 52 53 58 60 63 65 67 69 73 75 76 77 79 81 82 83 85 86 87 88 93 94 95 97 99 100 104 105 107 108 109 110 111 112 114 115 117 120 122 123 124 128 129 132 133 134 135 136
 2910 000000000577bae8            3         1 000000000a5821b0 134bc  78   000000019fc88170 System.Object
		Waiting threads: 64
-----------------------------
Total           3256
CCW             3
RCW             2
ComClassFactory 1
Free            2992

  

//如果知道临界区的地址,可以用一下命令,如果不知道地址,可以用!locks

0:044> !critsec 000000011fc6aa30

DebugInfo for CritSec at 000000011fc6aa30 does not point back to the critical section
NOT an initialized critical section.

CritSec +1fc6aa30 at 000000011fc6aa30
WaiterWoken        Yes
LockCount          -1
RecursionCount     0
OwningThread       0
EntryCount         fef56b35
ContentionCount    2000007
*** Locked

  

// !locks 的输出
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff541979(v=vs.85).aspx

0:105> !locks

CritSec +1192340 at 0000000001192340
WaiterWoken        No
LockCount          0
RecursionCount     1
OwningThread       bad0
EntryCount         0
ContentionCount    46a
*** Locked

  

//直接切换到进程上去:

0:014> ~~[bad0]s

  

//或者用 ~ 列出所有线程,然后切过去
//参考:http://blogs.msdn.com/b/tess/archive/2006/01/09/a-hang-scenario-locks-and-critical-sections.aspx

0:105> ~
#  0  Id: d9e0.a700 Suspend: 0 Teb: 000007ff`fffde000 Unfrozen
   1  Id: d9e0.18bac Suspend: 0 Teb: 000007ff`fffdc000 Unfrozen
   2  Id: d9e0.bfa0 Suspend: 0 Teb: 000007ff`fffd7000 Unfrozen
   3  Id: d9e0.bad0 Suspend: 0 Teb: 000007ff`fffd3000 Unfrozen
   4  Id: d9e0.16364 Suspend: 0 Teb: 000007ff`fff9e000 Unfrozen
0:014> ~3s

  

//

 0:046> .shell -i - -ci "~*e !clrstack" FIND  /i "Monitor.Enter"
0000000002f7d428 0000000076f6171a [HelperMethodFrame: 0000000002f7d428] System.Threading.Monitor.Enter(System.Object)
00000000049ad3e8 0000000076f6171a [HelperMethodFrame: 00000000049ad3e8] System.Threading.Monitor.Enter(System.Object)
0000000016a6d898 000007fef76500b9 [HelperMethodFrame: 0000000016a6d898] System.Threading.Monitor.Enter(System.Object)
0000000016b6e8b8 000007fef76500b7 [HelperMethodFrame: 0000000016b6e8b8] System.Threading.Monitor.Enter(System.Object)
.shell: Process exited
0:046> .shell -i - -ci "~*e !clrstack" FIND  /i "Monitor.TryEnter"
.shell: Process exited
0:046> .shell -i - -ci "~*e !clrstack" FIND  /i "Monitor"
000000000433eae8 0000000076f6186a [HelperMethodFrame_1OBJ: 000000000433eae8] System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object)
000000000504e3b8 0000000076f6186a [HelperMethodFrame_1OBJ: 000000000504e3b8] System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object)
000000000504e4e0 000007fef663d2ae System.Threading.Monitor.Wait(System.Object)
0000000002f7d428 0000000076f6171a [HelperMethodFrame: 0000000002f7d428] System.Threading.Monitor.Enter(System.Object)
00000000049ad3e8 0000000076f6171a [HelperMethodFrame: 00000000049ad3e8] System.Threading.Monitor.Enter(System.Object)
0000000016a6d898 000007fef76500b9 [HelperMethodFrame: 0000000016a6d898] System.Threading.Monitor.Enter(System.Object)
0000000016b6e8b8 000007fef76500b7 [HelperMethodFrame: 0000000016b6e8b8] System.Threading.Monitor.Enter(System.Object)
.shell: Process exited

  

// 有时候会发现无锁定同步快或死锁,还可以用!mlocks 看看

0:164> !dlk
Examining SyncBlocks...
Scanning for ReaderWriterLock instances...
Scanning for holders of ReaderWriterLock locks...
Scanning for ReaderWriterLockSlim instances...
Scanning for holders of ReaderWriterLockSlim locks...
Examining CriticalSections...
Scanning for threads waiting on SyncBlocks...
Scanning for threads waiting on ReaderWriterLock locks...
Scanning for threads waiting on ReaderWriterLocksSlim locks...
Scanning for threads waiting on CriticalSections...
No deadlocks detected.
0:164> !mlocks
Examining SyncBlocks...
Scanning for ReaderWriterLock instances...
Scanning for holders of ReaderWriterLock locks...
Scanning for ReaderWriterLockSlim instances...
Scanning for holders of ReaderWriterLockSlim locks...
Examining CriticalSections...

ClrThread  DbgThread  OsThread    LockType    Lock              LockLevel
------------------------------------------------------------------------------
0x67       116        0x1e8       thinlock    000000014036a2b0  (recursion:0)
0xab       182        0x268       thinlock    00000001c0724188  (recursion:0)
0xa4       177        0x14cc      RWLockSlim  000000013ff0a358  Writer          

0:164> !rwlock 000000013ff0a358
WriteLockOwnerThread:             0xa4
UpgradableReadLockOwnerThread:    None
ReaderCount:                      0
ReaderThreadIds:                  None
WaitingReaderCount:               204
WaitingReaderThreadIds:           0x9,0xa,0x11,0x12,0x13,0x14,0x15,0x16,0x17
WaitingWriterCount:               204
WaitingWriterThreadIds:           0x8,0xf,0x1d,0x21,0x24,0x2b,0x2f,0x30,
WaitingUpgradableReaderCount:     0
WaitingUpgradableReaderThreadIds: None
WaitingWriterUpgradeCount:        0
WaitingWriterUpgradeThreadIds:    None  

ClrThread  DbgThread  OsThread    LockType    Lock              LockLevel
------------------------------------------------------------------------------
0x15       19         0x15e8      thinlock    00000000010b6130  (recursion:0)
0x16c      226        0x1a1c      SyncBlock   0000000000c735a8

  

// shell 命令:

.shell -ci "!mlocks -d" find "Writer"

  

参考:
http://weblogs.thinktecture.com/ingo/2006/08/who-is-blocking-that-mutex---fun-with-windbg-cdb-and-kd.html

http://blogs.msdn.com/b/tess/archive/2006/01/09/a-hang-scenario-locks-and-critical-sections.aspx

http://hi.baidu.com/ju_feng/item/e22f06974dafe530326eeb64

http://stackoverflow.com/questions/22037581/determining-which-method-is-holding-a-readerwriterlockslim-writelock

时间: 2025-01-14 02:04:41

windbg .net 程序的死锁检测 常用方法(个人备份笔记)的相关文章

SQL SERVER性能分析--死锁检测数据库阻塞语句

工作中数据库经常出现内存,找了篇文章 参照CSDN,中国风(Roy)一篇死锁文章 阻塞:其中一个事务阻塞,其它事务等待对方释放它们的锁,同时会导致死锁问题. 整理人:中国风(Roy) 参照Roy_88的博客 http://blog.csdn.net/roy_88/archive/2008/07/21/2682044.aspx 日期:2008.07.20 ************************************************************************

linux死锁检测的一种思路【转】

转自:http://blog.csdn.net/zdy0_2004/article/details/44652323 linux死锁检测的一种思路 http://www.cnblogs.com/mumuxinfei/p/4365697.html 前言: 上一篇博文讲述了pstack的使用和原理. 和jstack一样, pstack能获取进程的线程堆栈快照, 方便检验和性能评估. 但jstack功能更加的强大, 它能对潜在的死锁予以提示, 而pstack只提供了线索, 需要gdb进一步的确定. 那

为什么MySQL死锁检测会严重降低TPS

在大量的客户端,更新数据表的同一行时,会造成数据库的吞吐量大幅降低. 很多数据库的前辈和同行分别通过实验和源码的方法,定位到了罪魁祸首----MySQL死锁检测 实验方式:http://blog.csdn.net/zhaiwx1987/article/details/6952285 源码方式:http://www.gpfeng.com/?p=426 请大家尤其注意这段代码 ##### lock_mutex_enter(); ut_ad(lock_table_has(thr_get_trx(thr

Unity3D C#打开外部应用程序,并检测应用程序是否关闭退出

欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,我们致力于打造业内unity3d培训.学习第一品牌. Unity3D C#打开外部应用程序,并检测应用程序是否关闭退出实现代码. using UnityEngine; using System.Collections; using System.Diagnostics; using System; public class StartOtherAp

Unix下C程序内存泄漏检测工具Valgrind安装与使用

Unix下C程序内存泄漏检测工具Valgrind安装与使用 Valgrind是一款用于内存调试.内存泄漏检测以及性能分析的软件开发工具. Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届Google-O'Reilly开源代码奖. Valgrind遵守GNU通用公共许可证条款,是一款自由软件. 官网 http://www.valgrind.org 下载与安装 #wget http://www.valgrind.org/downlo

谈谈MySQL死锁之二 死锁检测和处理源码分析

这一篇主要是通过一个实验来进行描述,过程是比较枯燥的. 实验准备 create table test_lock(id int auto_increment primary key ,stock int) engine=innodb; insert into test_lock(id,stock) value(1,50); 这里我把堆栈信息尽可能的简化,25个主要函数的名称和入参 后面为了突出主题,我对事务相关的函数加上这个开头死锁检测函数列表,一共10个函数   死锁检测函数列表A row_se

Linux下c++程序内存泄漏检测代码范例

Linux下对于程序内存泄漏检测的方法很多,最常用的的莫过于使用valgrind工具.但是valgrind相当于让程序在虚拟机中运行,会带来较大的系统资源开销,还会对程序的运行效率产生较大影响,对于那种资源占用大的程序,如果需要长时间运行才能暴露的泄漏问题,它就显得不太好用. linux下的c++程序中自己实现一个轻量级的泄漏检测代码其实是比较方便的,下面我就给出一个简单的范例,并作简单的说明.当然,我们还是应该提倡使用共享指针,用共享指针自动管理内存可以避免内存泄漏这样的不必要的麻烦. 基本原

Windows 64位程序编译及检测

Windows 64位程序编译及检测 1.64位程序编译 采用vs2010可以比较方便的编译出64位的程序. 调整编译配置为x64即可. 配置完成,编译出来的程序即为64位. 2.64位程序检测 检测一个程序是否为64位,可以采用dumpbin工具,这是vs自带的小工具. 步骤如下. 对应命令依次是: 进入vc目录:cd D:\Program Files\Microsoft Visual Studio 10.0\VC 配置vc命令环境:vcvarsall.bat 检测exe是否为64位:dump

MySQL死锁检测和回滚

最近碰到“TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH, WE WILL ROLL BACK FOLLOWING TRANSACTION”. 重新温习下受益良多,其中死锁的判定规则,其实我们早在5年前解决秒杀场景的第一个版本就已经涉及,并且思路很相似,如果有时间的话,我会补充上一批文章说下如果关闭死锁检测对单行更新能提升多少性能. 下面这一段代码展示的是: “ If the LATEST DETECTED DEADLOCK s