一:背景
上一篇我们聊到了如何通过 procdump
抓取 cpu爆高
和 内存暴涨
两种情况,这一篇再聊聊如何去抓程序 挂死
和 意外退出
。
二:程序挂死
1. 定义
程序挂死
简单的说就是程序没有响应,既然没响应了,可能 死锁
, 可能 负载过大线程池耗尽
等等情况,万千世界,啥情况都有😄😄😄。
既然是用 procdump
去抓,我得先了解下它对 挂死 (hung on)
的定义?
-h Write dump if process has a hung window (does not respond to window messages for at least 5 seconds).
从上面的定义看,人家貌似是判断窗口是否在指定时间内响应 windows消息
来判别的,我知道你在想什么😄,你寻找的web请求响应时间过长,这种场景通过 -h 是抓不到的,我感觉它特别适合那些带有 GUI 程序的抓取,比如说:(WPF,Winform) 。
2. 案例演示
现在我准备创建一个简单的 winform
程序,在 button 事件中故意让主线程sleep造成程序假死,参考代码如下:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Thread.Sleep(1000 * 10); MessageBox.Show("clicked me!"); } }
接下来启动 cmd 窗口,输入:
C:\Windows\system32>procdump -ma -h -w WindowsFormsApp1.exe E:\net5\hungwindow.dmpProcDump v10.0 - Sysinternals process dump utilityCopyright (C) 2009-2020 Mark Russinovich and Andrew RichardsSysinternals - www.sysinternals.comWaiting for process named WindowsFormsApp1.exe...
启动程序后点击 button 让 winform 假死,可以看到 procdump 在 5s 之后自动输出了dump。
C:\Windows\system32>procdump -ma -h -w WindowsFormsApp1.exe E:\net5\hungwindow.dmpPress Ctrl-C to end monitoring without terminating the process.[14:49:53] Hung Window:[14:49:53] Dump 1 initiated: E:\net5\hungwindow.dmp[14:49:53] Dump 1 writing: Estimated dump file size is 303 MB.[14:49:53] Dump 1 complete: 303 MB written in 0.7 seconds[14:49:54] Dump count reached.
然后用 windbg 看看每一个线程都在做什么?
0:000> ~*e !clrstackOS Thread Id: 0x6698 (0)Child SP IP Call Site00cfeb60 7722327c [HelperMethodFrame: 00cfeb60] System.Threading.Thread.SleepInternal(Int32)00cfebe4 5da9be7b System.Threading.Thread.Sleep(Int32)00cfebec 02d1238d WindowsFormsApp1.Form1.button1_Click(System.Object, System.EventArgs) [E:\net5\ConsoleApp1\WindowsFormsApp1\Form1.cs @ 23]00cfec04 5a3b95bb System.Windows.Forms.Control.OnClick(System.EventArgs)00cfec18 5a3bbe57 System.Windows.Forms.Button.OnClick(System.EventArgs)...
三:意外退出
1. 概念
意外退出
我想很多朋友都遇到过,本来 Console 程序跑的好好地,半夜收到报警短信.... 还有用户反馈,你那终端可行呀,点了几下就挂掉了。。。😂😂😂
有些朋友可能在想,sd,这问题还不简单,加一个全局 未处理异常
不就好啦??? 真搞不懂怎么想的 🐱🐱🐱。
哈哈,总以为 全局异常处理
能够包治百病,还是太年轻了,记得上一家公司用了阿里的sdk,底层用了 C++ 封装,程序莫名退出了,全局异常处理也没任何日志,说到这里我想你也知道了,非托管层抛出的异常,托管层这时候就是弟弟,就这么简单😄😄😄
2. 演示
我准备在程序中抛出一个简单的 DivideByZeroException
,方便让程序退出。
public class Program { public static void Main(string[] args) { var result = CalcDAL(); Console.WriteLine($"result={result}"); Console.ReadLine(); } public static int CalcDAL() { try { var query = "0"; Thread.Sleep(2000); //do sth... return 0 / Convert.ToInt32(query); } catch (Exception ex) { Console.WriteLine(ex.Message); throw; } } }
程序跑起来后,在 procdump 上用 -e
命令抓取。
C:\Windows\system32>procdump -ma -e -w ConsoleApp1.exe E:\net5\test.dmpProcDump v10.0 - Sysinternals process dump utilityCopyright (C) 2009-2020 Mark Russinovich and Andrew RichardsSysinternals - www.sysinternals.comWaiting for process named ConsoleApp1.exe...Press Ctrl-C to end monitoring without terminating the process.[15:29:56] Exception: 04242420[15:29:58] Exception: C0000094.INT_DIVIDE_BY_ZERO[15:29:58] Exception: C0000094.INT_DIVIDE_BY_ZERO[15:29:58] Exception: C0000094.INT_DIVIDE_BY_ZERO[15:29:58] Unhandled: C0000094.INT_DIVIDE_BY_ZERO[15:29:58] Dump 1 initiated: E:\net5\test-2.dmp[15:29:58] Dump 1 writing: Estimated dump file size is 50 MB.[15:29:59] Dump 1 complete: 50 MB written in 0.2 seconds[15:29:59] Dump count reached.
从输出看,万事ok。
3. 拓展
不知道有没有朋友还记得 VS 有一个 异常断点
吗? 表示当某种异常抛出时,程序自动进入断点处调试状态,这是一个帮助找到bug的利器,但还是有一定限制的,毕竟程序都跑在生产上,你也不能把 vs 搬过去,也不可能搞个远程调试啥的,所以当程序抛出了某一种异常后,怎么自动生成一个 dump 呢???
在强大的 procdump 面前这些都是弟弟,🐂👃,主要通过下面两种方式进行异常碰撞检索。
- 通过
异常类型
抓取
何为 异常类型
,比如本节的 DivideByZeroException
异常,通过在 procdump 中设置 -e 1 -f DivideByZeroException
即可。
把 CalcDAL()
方法中的 throw 去掉,保证程序不异常退出。
public static int CalcDAL() { try { var query = "0"; Thread.Sleep(2000); //do sth... return 0 / Convert.ToInt32(query); } catch (Exception ex) { Console.WriteLine(ex.Message); return 0; } }
然后用 proddump
输入如下命令。
C:\Windows\system32>procdump -ma -w -e 1 -f "divide by zero" -w ConsoleApp1.exe E:\net5\test.dmpProcDump v10.0 - Sysinternals process dump utilityCopyright (C) 2009-2020 Mark Russinovich and Andrew RichardsSysinternals - www.sysinternals.comWaiting for process named ConsoleApp1.exe...Press Ctrl-C to end monitoring without terminating the process.CoreCLR Version: v5.0.3[15:44:15] Exception: E0434F4D.System.DivideByZeroException ("Attempted to divide by zero.")[15:44:15] Dump 1 initiated: E:\net5\test-3.dmp[15:44:16] Dump 1 writing: Estimated dump file size is 50 MB.[15:44:16] Dump 1 complete: 50 MB written in 0.2 seconds[15:44:16] Dump count reached.
看到上面的 Exception: E0434F4D.System.DivideByZeroException ("Attempted to divide by zero.")
了嘛? 哈哈,已经成功捕获啦,是不是挺有意思😄。
- 通过
异常信息
抓取
用 异常信息
的话,我觉得更加灵活,比如我搜索一下:divide by zero
关键词就能成功捕获。
C:\Windows\system32>procdump -ma -w -e 1 -f "divide by zero" -w ConsoleApp1.exe E:\net5\test.dmp[15:46:34] Exception: E0434F4D.System.DivideByZeroException ("Attempted to divide by zero.")[15:46:34] Dump 1 initiated: E:\net5\test-4.dmp[15:46:34] Dump 1 writing: Estimated dump file size is 49 MB.[15:46:34] Dump 1 complete: 49 MB written in 0.2 seconds[15:46:35] Dump count reached.
四:总结
混混沌沌写了这么多,上下两篇四种抓取方法我想你都学会了吧,万事开头难,有了dump,接下来就是好好研究咯!
更多高质量干货:参见我的 GitHub: dotnetfly
原文转载:http://www.shaoqun.com/a/702740.html
亚马逊礼品卡:https://www.ikjzd.com/w/1090.html
asiabill:https://www.ikjzd.com/w/1014
一:背景上一篇我们聊到了如何通过procdump抓取cpu爆高和内存暴涨两种情况,这一篇再聊聊如何去抓程序挂死和意外退出。二:程序挂死1.定义程序挂死简单的说就是程序没有响应,既然没响应了,可能死锁,可能负载过大线程池耗尽等等情况,万千世界,啥情况都有😄😄😄。既然是用procdump去抓,我得先了解下它对挂死(hungon)的定义?-h Writedumpifprocesshasahungw
扬帆计划:https://www.ikjzd.com/w/1581
dojo:https://www.ikjzd.com/w/2052
小马哥:https://www.ikjzd.com/w/1655
美国FDA(OTC)注册流程:https://www.ikjzd.com/home/134696
爱情与婚姻:http://lady.shaoqun.com/m/a/268580.html
口述:每个月 我付1500元买爱情:http://www.30bags.com/a/253672.html
没有评论:
发表评论