上一篇咱們聊到了如何經過 procdump
抓取 cpu爆高
和 內存暴漲
兩種狀況,這一篇再聊聊如何去抓程序 掛死
和 意外退出
。web
程序掛死
簡單的說就是程序沒有響應,既然沒響應了,可能 死鎖
, 可能 負載過大線程池耗盡
等等狀況,萬千世界,啥狀況都有😄😄😄。windows
既然是用 procdump
去抓,我得先了解下它對 掛死 (hung on)
的定義?ide
-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) 。spa
如今我準備建立一個簡單的 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.dmp ProcDump v10.0 - Sysinternals process dump utility Copyright (C) 2009-2020 Mark Russinovich and Andrew Richards Sysinternals - www.sysinternals.com Waiting for process named WindowsFormsApp1.exe...
啓動程序後點擊 button 讓 winform 假死,能夠看到 procdump 在 5s 以後自動輸出了dump。日誌
C:\Windows\system32>procdump -ma -h -w WindowsFormsApp1.exe E:\net5\hungwindow.dmp Press 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 看看每個線程都在作什麼?code
0:000> ~*e !clrstack OS Thread Id: 0x6698 (0) Child SP IP Call Site 00cfeb60 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) ...
意外退出
我想不少朋友都遇到過,原本 Console 程序跑的好好地,半夜收到報警短信.... 還有用戶反饋,你那終端可行呀,點了幾下就掛掉了。。。😂😂😂orm
有些朋友可能在想,sd,這問題還不簡單,加一個全局 未處理異常
不就好啦??? 真搞不懂怎麼想的 🐱🐱🐱。事件
哈哈,總覺得 全局異常處理
可以包治百病,仍是太年輕了,記得上一家公司用了阿里的sdk,底層用了 C++ 封裝,程序莫名退出了,全局異常處理也沒任何日誌,說到這裏我想你也知道了,非託管層拋出的異常,託管層這時候就是弟弟,就這麼簡單😄😄😄
我準備在程序中拋出一個簡單的 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.dmp ProcDump v10.0 - Sysinternals process dump utility Copyright (C) 2009-2020 Mark Russinovich and Andrew Richards Sysinternals - www.sysinternals.com Waiting 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。
不知道有沒有朋友還記得 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.dmp ProcDump v10.0 - Sysinternals process dump utility Copyright (C) 2009-2020 Mark Russinovich and Andrew Richards Sysinternals - www.sysinternals.com Waiting 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,接下來就是好好研究咯!