记一次 .NET某环境监测系统 崩溃分析

news/2024/11/17 0:54:47/文章来源:https://www.cnblogs.com/huangxincheng/p/18350168

一:背景

1. 讲故事

前些天有位朋友找到我,说他们的程序崩溃了,也自己分析了下初步结果,让我帮忙再确认下,既然让我确认,那就开始dump分析之旅吧。

二:WinDbg 分析

1. 为什么会崩溃

windbg 有一个强大之处就是带有一个自动化的分析命令 !analyze -v 可以帮助我们快速的分析,输出如下:


0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************CONTEXT:  (.ecxr)
rax=00007ff95c5a9877 rbx=00007ff959d6d8e0 rcx=0000000000000000
rdx=0000000000000000 rsi=000000e394b98de0 rdi=000000e394b99530
rip=00007ff959c7b699 rsp=000000e394b99510 rbp=000000e394b99d00r8=0000000000000000  r9=0000000000000007 r10=0000000000000000
r11=0000000000000000 r12=0000022da11451d0 r13=0000000000000000
r14=000000e394b9a9e0 r15=0000000000040ae4
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000200
KERNELBASE!RaiseException+0x69:
00007ff9`59c7b699 0f1f440000      nop     dword ptr [rax+rax]
Resetting default scopeEXCEPTION_RECORD:  (.exr -1)
ExceptionAddress: 00007ff959c7b699 (KERNELBASE!RaiseException+0x0000000000000069)ExceptionCode: c000041dExceptionFlags: 00000001
NumberParameters: 0PROCESS_NAME:  xxx.Desktop.dllERROR_CODE: (NTSTATUS) 0xc000041d - <Unable to get error code text>EXCEPTION_CODE_STR:  c000041d
...

从卦中可以看到当前的崩溃码是 c000041d,即 An unhandled exception was encountered during a user callback,这个异常码是个统称异常,言外之意就是内部还藏有真实的异常码,那真实的异常码是多少呢?

2. 真实的异常码在哪里

要想知道这个答案,可以切到异常上下文找到 RaiseException 的父函数在图观察,输出如下:


0:000> k 5# Child-SP          RetAddr               Call Site
00 000000e3`94b99510 00007ff8`eb52cb19     KERNELBASE!RaiseException+0x69
01 000000e3`94b995f0 00007ff8`eb52cb4b     coreclr!NakedThrowHelper2+0x9
02 000000e3`94b99620 00007ff8`eb52cb55     coreclr!NakedThrowHelper_RspAligned+0x1e
03 000000e3`94b99b48 00007ff8`8da3caa3     coreclr!NakedThrowHelper_FixRsp+0x5
04 000000e3`94b99b50 00007ff8`8d5a5e23     Avalonia_Base!Avalonia.Rendering.Composition.Compositor.RequestCompositionUpdate+0x830:000> ub 00007ff8`eb52cb19
...
00007ff8`eb52cb14 e857910b00      call    coreclr!LinkFrameAndThrow (00007ff8`eb5e5c70)0:000> uf coreclr!LinkFrameAndThrow
Flow analysis was incomplete, some code may be missing
coreclr!LinkFrameAndThrow [D:\a\_work\1\s\src\coreclr\vm\excep.cpp @ 6934]:6934 00007ff8`eb5e5c70 4053            push    rbx6934 00007ff8`eb5e5c72 4883ec20        sub     rsp,20h6937 00007ff8`eb5e5c76 488d05bb771f00  lea     rax,[coreclr!FaultingExceptionFrame::`vftable' (00007ff8`eb7dd438)]...6949 00007ff8`eb5e5cea 448b05c7682800  mov     r8d,dword ptr [coreclr!g_SavedExceptionInfo+0x18 (00007ff8`eb86c5b8)]6949 00007ff8`eb5e5cf1 8b15ad682800    mov     edx,dword ptr [coreclr!g_SavedExceptionInfo+0x4 (00007ff8`eb86c5a4)]6949 00007ff8`eb5e5cf7 8b0da3682800    mov     ecx,dword ptr [coreclr!g_SavedExceptionInfo (00007ff8`eb86c5a0)]6950 00007ff8`eb5e5cfd 4883c420        add     rsp,20h6950 00007ff8`eb5e5d01 5b              pop     rbx6949 00007ff8`eb5e5d02 48ff2537581b00  jmp     qword ptr [coreclr!_imp_RaiseException (00007ff8`eb79b540)]  Branch...

从卦中可以看到 RaiseException 的参数来自于异常信息全局变量 g_SavedExceptionInfo,这个变量中存放着当前崩溃的真实上下文以及寄存器信息,在 CLR 中的数据结构如下:


struct SavedExceptionInfo
{EXCEPTION_RECORD m_ExceptionRecord;CONTEXT m_ExceptionContext;CrstStatic m_Crst;
}

有了这些之后接下来就可以用 dt 来挖了,输出如下:


0:000> dt coreclr!g_SavedExceptionInfo 00007ff8eb86c5a0+0x000 m_ExceptionRecord : _EXCEPTION_RECORD+0x0a0 m_ExceptionContext : _CONTEXT+0x570 m_Crst           : CrstStatic0:000> dx -r1 (*((coreclr!_EXCEPTION_RECORD *)0x7ff8eb86c5a0))
(*((coreclr!_EXCEPTION_RECORD *)0x7ff8eb86c5a0))                 [Type: _EXCEPTION_RECORD][+0x000] ExceptionCode    : 0xc0000005 [Type: unsigned long][+0x004] ExceptionFlags   : 0x0 [Type: unsigned long][+0x008] ExceptionRecord  : 0x0 [Type: _EXCEPTION_RECORD *][+0x010] ExceptionAddress : 0x7ff88da3caa3 [Type: void *][+0x018] NumberParameters : 0x2 [Type: unsigned long][+0x020] ExceptionInformation [Type: unsigned __int64 [15]]

从卦中信息来看当前崩溃的真正原因是 0xc0000005,即 访问违例,同时还记录了崩溃的那个点 RIP=0x7ff88da3caa3

3. 什么逻辑导致的崩溃

这个比较简单,用 !Uuf 都可以试下,输出如下:


0:000> !U 0x7ff88da3caa3
Normal JIT generated code
Avalonia.Rendering.Composition.Compositor.RequestCompositionUpdate(System.Action)
ilAddr is 0000022DC65AE2D4 pImport is 00000238EE6FECA0
Begin 00007FF88DA3CA20, size 96
...
00007ff8`8da3ca9b 488bce          mov     rcx,rsi
00007ff8`8da3ca9e e8cdeaa5fe      call    00007ff8`8c49b570 (Avalonia.Rendering.Composition.Compositor.RequestCompositionBatchCommitAsync(), mdToken: 00000000060009D9)
>>> 00007ff8`8da3caa3 488b4008        mov     rax,qword ptr [rax+8]
00007ff8`8da3caa7 8b4008          mov     eax,dword ptr [rax+8]
...0:000> dt coreclr!g_SavedExceptionInfo 00007ff8eb86c5a0+0x000 m_ExceptionRecord : _EXCEPTION_RECORD+0x0a0 m_ExceptionContext : _CONTEXT+0x570 m_Crst           : CrstStatic0:000> dx -r1 (*((coreclr!_CONTEXT *)0x7ff8eb86c640))
...[+0x078] Rax              : 0x0 [Type: unsigned __int64]
...

从卦中的汇编代码看,崩溃的原因是Avalonia 框架的 RequestCompositionBatchCommitAsync 返回 null 导致的,即 rax=0,这个 Avalonia 不就是那个跨平台的WPF吗,有点意思了,接下来到源码中确认下到底是什么变量。

从代码逻辑上看 _nextCommit 是一个类变量而不是方法局部变量,在并发较高的情况下如果有其他方法将_nextCommit=null的话确实存在这种情况,为了验证想法在类中搜索,真的有方法会设置 null,截图如下:

到这里基本就搞清楚了,这是 Avalonia 的一个bug,最后我们看下 Avalonia 的版本,发现这个版本是非常新的,输出如下:


0:000> lmvm Avalonia_Base...Timestamp:        A0BE2821 (This is a reproducible build file hash, not a timestamp)CheckSum:         001CDA05ImageSize:        001D4000File version:     11.1.0.0Product version:  11.1.0.0File flags:       0 (Mask 3F)File OS:          4 Unknown Win32File type:        2.0 DllFile date:        00000000.00000000Translations:     0000.04b0Information from resource tables:CompanyName:      Avalonia TeamProductName:      AvaloniaInternalName:     Avalonia.Base.dllOriginalFilename: Avalonia.Base.dllProductVersion:   11.1.0+2a8ea17985fd739234fa0d93c3437948535d35c4FileVersion:      11.1.0.0FileDescription:  Avalonia.BaseLegalCopyright:   Copyright 2013-2024 © The AvaloniaUI Project

4. 如何解决呢

知道了这是 Avalonia 的bug,并且 Avalonia 也是非常新的版本,升级这条路就堵死了,只能提交个issue 给官方:https://github.com/AvaloniaUI/Avalonia 来解决吧。

三:总结

这次生产事故挖了点新东西,有点好奇的是现在工控行业也开始用 Avalonia 替代 WPF 了吗? 不过现阶段稳定性和 WPF 是没法比的,期待未来更健壮的版本吧。

图片名称

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/780143.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Avalonia 11.1 获取平台调用的窗口的方法

本文和大家介绍如何在 11.1 版本的 Avalonia 里获取平台调用的窗口的方法,如 Windows 获取窗口句柄,在 Linux 下获取 X11 的 xid 窗口信息在拿到任意的 Avalonia 的 Visual 元素,可通过 TopLevel 的 GetTopLevel 方法获取到其窗口。由于 Avalonia 是一个跨平台的 UI 框架,因…

milvus日常管理

1.创建用户 create user -u hxl -p Milvus 让需要在auut界面赋予账号权限

违法高发提醒

3 违法地点:京藏高速辅路上清桥南(长期高发地) 违法行为:机动车违反禁止标线指示的

保障速度与安全合规的前提下,如何传文件到国外?

伴随着经济全球化,数据跨境活动日益频繁,数据出境场景越来越多,防范数据出境安全风险,保障数据依法有序自由流动成为我国关注的重要方面。涉及数据出海的行业多种多样,像跨国运营、全球研发、金融服务等领域的企业都涉及传文件到国外,将数据资源、业务或技术应用扩展到海…

多线程学习总结

Java 多线程学习总结 本章目标理解线程的基本概念 理解线程与进程的区别 熟悉线程的实现方式 了解线程的管理 熟悉线程的生命周期 掌握线程同步 掌握线程池 了解线程通信 掌握线程定时器什么是进程 进程就是正在运行的程序,它是系统进行资源分配和调度的基本单位,各个进程之间…

AOP -面向切面编程

AOP -面向切面编程 aop是oop(面向对象编程)的补充和完善。oop是一种纵向开发,然而当面对需要一些横向的功能如日志,就会导致大量重复的代码。 aop利用横切把一些重复的非核心的代码插入到核心代码周围,不需要重复写很多遍。 应用场景:日志记录,在方法的执行前后插入日志…

OneKeyAdmin 后台任意文件下载

无它唯手熟尔,还是太菜了侵权声明 本文章中的所有内容(包括但不限于文字、图像和其他媒体)仅供教育和参考目的。如果在本文章中使用了任何受版权保护的材料,我们满怀敬意地承认该内容的版权归原作者所有。 如果您是版权持有人,并且认为您的作品被侵犯,请通过以下方式与我…

适合新手进行接口与自动化测试练习的推荐网站!!!

对于新手来说,接口与自动化测试练习网站是提升技能的重要资源。以下是一些适合新手进行接口与自动化测试练习的推荐网站: 1、httpbin.org httpbin.org是一个在线提供HTTP服务的网站,它提供了丰富的HTTP接口,用于测试HTTP请求和响应的各种信息,如cookie、IP、headers和登录…

《最新出炉》系列小成篇-Python+Playwright自动化测试-67 - 模拟手机浏览器兼容性测试

1.简介 在日常工作中,我们会遇到需要使用不同的硬件设备测试兼容性的问题,尤其是现在手机型号基本上是每个厂家每年发布一款新机型,而且手机的屏幕大小分辨率五花八门的,我们基本不可能全部机型都用真机测试一遍,playwright提供了模仿机型的功能,我们可以使用playwright来…

在IIS上部署ASP.NET Core Web API和Blazor Wasm详细教程

前言 前段时间我们完成了七天.NET 8 操作 SQLite 入门到实战的开发系列教程,有不少同学留言问如何将项目发布部署到IIS上面运行。本篇文章我们就一起来讲讲在IIS上部署ASP.NET Core Web API和Blazor Wasm。 前提条件 安装.NET Core SDKhttps://dotnet.microsoft.com/zh-cn/dow…

Sublime Text 4 如何配置成完美的OI编辑器,优雅的打比赛

Sublime Text 完整配置编译文件点击新建编译系统(Tools -> Build system -> New build system)改为以下代码: Ubuntu : {"encoding": "utf-8","working_dir": "$file_path","shell_cmd": "g++ \"$file_name…