又一起.NET程序挂死, 用 Windbg 抽丝剥茧式的真实案例分析
2024-09-03 16:53:38
一:背景
1. 讲故事
前天有位粉丝朋友在后台留言让我帮忙看看他的 Winform程序 UI无响应
+ 410线程
到底是啥情况,如下图:
说实话,能看到这些真实案例我是特别喜欢的 ,就像医生看病,光停留在理论和那些 demo 上,那是没有前途的,如果有朋友在这块搞不定的话,我可以免费帮你解读 dump,再附送一篇博客详述。
好了,言归正传,既然粉丝朋友已经提到了高达 410
线程,我本能反应就是要么高负载,要么野线程,后者大多是无数新出现的线程卡在某个锁上。
WinForm 出现高负载的情况,我至今还是没遇到,如果说卡在某个锁上,基本都属于这类,有了这个先入为主的思路,接下来就可以祭出 windbg 一探究竟了。
二: windbg 分析
1. 查找 CLR 同步块表
十个人用锁,八个人会用 lock, 所以先用 !syncblk
看看程序的锁情况。
0:000> !syncblk
Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
76 070e5fa4 67 1 17367570 15e8 218 03e6dd68 System.IO.Ports.SerialStream
-----------------------------
Total 789
CCW 39
RCW 2
ComClassFactory 1
Free 535
我去,从卦象上来看情况很不好,我来简单分析下。
- MonitorHeld = 67
这个 67 表示当前有 1 个线程持有锁,有 33 个线程在等待锁,肯定有朋友想问怎么算的?很简单:当一个线程持有了锁的时候 MonitorHeld+1
,当一个线程在等待锁的时候 MonitorHeld+2
,所以表达式就是: 67= [1 + 66=(33*2)]
。
- Owning Thread Info = 17367570 15e8 218
上面三个信息都表示当前持有线程,可以看最后的 218,它是 windbg 映射出来的线程ID,如果不信的话,可以用 !t 来一探究竟。
0:000> !t
ThreadCount: 315
UnstartedThread: 0
BackgroundThread: 302
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 c64 00cc3de0 24220 Preemptive 042E1884:00000000 00cbc0a0 0 STA
214 240 1398 16702b90 1029220 Preemptive 00000000:00000000 00cbc0a0 0 MTA (Threadpool Worker)
215 323 b5c 12ab7260 1029220 Preemptive 00000000:00000000 00cbc0a0 0 MTA (Threadpool Worker)
216 290 1858 16c21c98 1029220 Preemptive 00000000:00000000 00cbc0a0 0 MTA (Threadpool Worker)
218 117 15e8 17367570 1029220 Preemptive 00000000:00000000 00cbc0a0 1 MTA (Threadpool Worker)
...
对,就是 218 这个罪魁祸首在持有了锁,导致 33 个线程在无辜的等待它。。。
- SyncBlock Owner = System.IO.Ports.SerialStream
也许你会好奇,到底 lock 持有的是哪一个对象呢?从 SyncBlock Owner
上看就是 SerialStream
,
最新文章
- jq.validate 自定义验证两个日期
- C++ 虚函数表解析
- jquery实现简单瀑布流布局
- 8-06循环结构WHILE
- javascript版快速排序和冒泡排序
- display:inline-block 和float:left 的区别
- jQuery 的属性
- Windows Azure Cloud Service (42) 使用Azure In-Role Cache缓存(1)Co-located Role
- Arrya数组添加过滤条件
- .NET微信通过授权获取用户的基本信息
- Java开发中的23种设计模式(转)
- MetadataType的使用,MVC的Model层数据验证
- 【转】使用XCODE 的SOURCE CONTROL 做版本控制 (1)
- Codevs 1081 线段树练习 2
- Unity 改变类模板-为你的类添加一个命名空间
- Log4j2 简明教程
- 在ExpressJS中设置二级域名跨域共享Cookie
- Chapter 5 Blood Type——8
- SQL SERVER启动步骤
- vue中嵌套页面(iframe)