关于.net:如何在-NET-程序万种死法中有效的生成-Dump-下

7次阅读

共计 4659 个字符,预计需要花费 12 分钟才能阅读完成。

一:背景

上一篇咱们聊到了如何通过 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.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 看看每一个线程都在做什么?


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)
...

三:意外退出

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.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。

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.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,接下来就是好好钻研咯!

正文完
 0