杀鸡焉用牛刀!放下Windbg,让dotnet-stack来快速定位死锁原因

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了杀鸡焉用牛刀!放下Windbg,让dotnet-stack来快速定位死锁原因相关的知识,希望对你有一定的参考价值。

我们用来分析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“,记住我!

以上是关于杀鸡焉用牛刀!放下Windbg,让dotnet-stack来快速定位死锁原因的主要内容,如果未能解决你的问题,请参考以下文章

《Spring 手撸专栏》第 2 章:小试牛刀(让新手能懂),实现一个简单的Bean容器

《Spring 手撸专栏》第 2 章:小试牛刀(让新手能懂),实现一个简单的Bean容器

产品经理如何让程序员放下手中的刀?

windbg的初始化脚本

无法在 WinDbg 中加载 SOS

《Spring 手撸专栏》第 2 章:小试牛刀(让新手能懂),实现一个简单的Bean容器