我们用来分析CPU过高、死锁问题的常见方案是使用Windbg分析dump文件。
但是这种方式存在一些缺点,比如dump文件过大难以下载,windbg使用过于复杂难以掌握等。
这里介绍一个小工具dotnet-stack,帮助我们检查托管代码调用堆栈,快速定位到当前执行的代码,找到问题原因。
准备代码
新建ConsoleApp1,编写如下代码:
static void Main(string[] args)
{new Program().TestLock();Console.Read();
}void TestLock()
{lock (this){var task = Task.Factory.StartNew(() =>{Console.WriteLine("-------开始-------");Deadlock();Console.WriteLine("---------完成--------");});task.Wait();}
}void Deadlock()
{lock (this){Console.WriteLine("公众号“My IO”");}
}
示例代码通过抢占lock模拟死锁现象,运行代码后,可以发现命令行停在"-------开始-------"就没有继续输出了。
分析问题
首先,运行下面的命令安装dotnet-stack:
dotnet tool install --global dotnet-stack
然后,我们需要找到死锁程序对应的进程id。虽然可以用任务管理器或者ps
去查看,但是这里可以直接用命令获取:
dotnet-stack ps
拿到ConsoleApp1的进程id6004
,运行下列命令:
dotnet-stack report --process-id 6004
该命令可从进程中收集跟踪的所有堆栈。格式如下:
注释前缀为#
每个线程都有一个包含本机线程ID的头:
Thread (<thread-id>):
托管代码:
模块!方法
非托管代码:
[Native Frames]
从图中可以看到,最后执行到的代码是ConsoleApp1!Program.Deadlock()
,对照代码,就可以轻松找到死锁原因了。
结论
dotnet-stack
麻雀虽小,但是功能不错,用于解决死锁问题还是不错的。
如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!