.NET新能源汽车锂电池检测程序UI挂死问题分析
1. 讲故事
这世间事说来也奇怪,近两个月有三位朋友找到我,让我帮忙分析下他的程序hangon现象,这三个dump分别涉及: 医疗,新能源,POS系统。截图如下:
那这篇为什么要拿其中的 新能源
说事呢? 因为这位朋友解决的最顺利,在提供的一些线索后比较顺利的找出了问题代码。
说点题外话,我本人对 winform 是不熟的,又奈何它三番五次的出现在我的视野里,所以我决定写一篇文章好好的总结下,介于没有太多的参考资料,能力有限,只能自己试着解读。
二: Windbg 分析
1. 程序现象
开始之前先吐槽一下,这几位大佬抓的dump文件都是 wow64
,也就是用64bit任务管理器抓了32bit的程序,见如下输出:
1 2 |
|
所以就不好用 windbg preview
来分析了,首先要用 !wow64exts.sw
将 64bit 转为 32bit ,本篇用的是 windbg10,好了,既然是UI卡死,首当其冲就是要看一下UI线程到底被什么东西卡住了,可以用命令 !clrstack
看一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
从调用栈上看,代码是由于 Microsoft.Win32.SystemEvents.OnUserPreferenceChanged
被触发,然后在 System.Windows.Forms.Control.WaitForWaitHandle
处被卡死,从前者的名字上就能看到,OnUserPreferenceChanged(用户首选项)
是一个系统级别的 Microsoft.Win32.SystemEvents
事件,那到底是什么导致了这个系统事件被触发,为此我查了下资料,大概是说:如果应用程序的 Control 注册了这些系统级事件,那么当windows发出 WM_SYSCOLORCHANGE, WM_DISPLAYCHANGED, WM_THEMECHANGED
(主题,首选项,界面显示) 消息时,这些注册了系统级事件的 Control 的handle将会被执行,比如刷新自身。
觉得文字比较拗口的话,我试着画一张图来阐明一下。
从本质上来说,它就是一个观察者模式,但这和UI卡死没有半点关系,充其量就是解决问题前需要了解的背景知识,还有一个重要概念没有说,那就是: WindowsFormsSynchronizationContext
。
2. 理解 WindowsFormsSynchronizationContext
为什么一定要了解 WindowsFormsSynchronizationContext 呢?理解了它,你就搞明白了为什么会卡死,我们知道 winform 的UI线程是一个 STA 模型,它的一个特点就是单线程,其他线程想要更新Control,都需要调度到UI线程的Queue队列中,不存在也不允许并发更新Control的情况,参考如下:
1 2 3 4 5 6 7 8 9 10 11 |
|
Winform 还有一个特点:它会给那些创建 Control 的线程配一个 WindowsFormsSynchronizationContext 同步上下文,也就是说如果其他线程想要更新那个 Control,那就必须将更新的值通过 WindowsFormsSynchronizationContext 调度到那个创建它的线程上,这里的线程不仅仅是 UI 线程哦,有了这些基础知识后,再来分析下为什么会被卡死。
3. 卡死的真正原因
再重新看下主线程的调用栈,它的走势是这样的: OnUserPreferenceChanged -> WindowsFormsSynchronizationContext.Send -> Control.MarshaledInvoke -> WaitHandle.WaitOneNative
,哈哈,有看出什么问题吗???
眼尖的朋友会发现,为什么主线程会调用 WindowsFormsSynchronizationContext.Send
方法呢? 难道那个注册 handler的 Control 不是由主线程创建的吗?要想回答这个问题,需要看一下 WindowsFormsSynchronizationContext 类的 destinationThreadRef 字段值,源码如下:
1 2 3 4 5 |
|
可以用 !dso
命令把线程栈上的 WindowsFormsSynchronizationContext 给找出来,简化输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
果然不出所料, 从卦象上看 Thread=7
线程上有 Control 注册了系统事件,那 Thread=7 到底是什么线程呢? 可以通过 !t
查看。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
从卦象上看: ID=7 是一个线程池线程,而且是 MTA 模式,按理说它应该将创建控件的逻辑调度给UI线程,而不是自己创建,所以UI线程一直在 WaitOneNative 处等待 7号线程消息泵响应,所以导致了无限期等待。
4. 7号线程到底创建了什么控件
这又是一个考验底层知识的问题,也困扰着我至今,太难了,我曾今尝试着把 UserPreferenceChangedEventHandler
事件上的所有 handles 捞出来,写了一个脚本大概如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
输出结果:
||2:2:438> !wow64exts.sw
Switched to Guest (WoW) mode
Thread=7,systemEventInvokeInfo=1107487c
从输出中找到了 7号线程
对应的处理事件 systemEventInvokeInfo ,然后对其追查如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
从输出中可以看到,最后的控件是 DevExpress.LookAndFeel.Design.UserLookAndFeelDefault
,我以为找到了答案,拿着这个结果去 google,结果 devExpress 踢皮球,截图如下:
咳,到这里貌似就查不下去了,有其他资料上说 Control 在跨线程注册 handler 时会经过 MarshalingControl
,所以在这个控件设置bp断点是能够抓到的,参考命令如下:
1 |
|
这里我就没法验证了。
三:总结
虽然知道这三起事故都是由于非UI线程创建Control所致,但很遗憾的是我尽了最大的知识边界还没有找到最重要的罪魁祸首,不过值得开心的是基于现有线索有一位朋友终于找到了问题代码,真替他开心
.NET新能源汽车锂电池检测程序UI挂死问题分析相关推荐
- 记一次 .NET 某新能源汽车锂电池检测程序 UI挂死分析
一:背景 1. 讲故事 这世间事说来也奇怪,近两个月有三位朋友找到我,让我帮忙分析下他的程序hangon现象,这三个dump分别涉及:医疗,新能源,POS系统.截图如下: 那这篇为什么要拿其中的 新能 ...
- 记一次 .NET 某上市工业智造 CPU+内存+挂死 三高分析
一:背景 1. 讲故事 上个月有位朋友加wx告知他的程序有挂死现象,询问如何进一步分析,截图如下: 看这位朋友还是有一定的分析基础,可能玩的少,缺乏一定的分析经验,当我简单分析之后,我发现这个dump ...
- 探秘新能源汽车锂电池正极材料龙头“高镍三元”
摘要:随着人们生活水平的提高,城镇化趋势越来越明显,人们对出行工具的要求也越来越高,近些年环保型新能源汽车已经成为人们出行首选,还可以保护环境节约资源.电池作为汽车的核心部件,成为广大学者研究关注的焦 ...
- 总线控制内部eep_CAN总线在新能源汽车中的通信网络设计及应用分析
从事汽车相关行业的小伙伴们,都知道CAN总线,它是当今汽车各电控单元之间通信的总线标准,现在几乎所有的汽车厂家都选择使用CAN总线通信.CAN总线起初便是基于BOSCH公司为了解决汽车的电子控制单元增 ...
- 2021年中国机动车、汽车和新能源汽车保有量及驾驶人和驾驶证业务办理情况分析「图」
一.机动车和汽车 1.机动车新注册登记数量及保有量 根据公安部数据显示,我国新注册登记机动车数量整体表现为波动上涨趋势,2021年为3674万辆,比2020年增加346万辆,增长10.38%.就机动车 ...
- VxWorks任务挂死实战分析
目录 背景描述 根本原因 分析过程 背景描述 操作系统:VxWorks 5.5 CPU:MIPS32 74Kc内核CPU 现象描述:联调代码时发现应用层代码调用以下接口函数必现任务挂死,检查代码发现入 ...
- I2C 挂死原因分析及解决方案
I2C几乎是嵌入系统中最为通用串行总线,MCU周边的各种器件只要对速度要求不高都可以使用.优点是兼容性好(几乎所有MCU都有I2C主机控制器,没有也可以用IO模拟),管脚占用少,芯片实现简单.I2C协 ...
- Linux服务器挂死案例分析
问题现象: 在linux服务器上运行一个指定的脚本时,就会出现无数个相同进程的,而且不停的产生,杀也杀不掉,最后系统就陷入死循环,无法登陆,只能人工去按机器的电源键才可以.这够崩溃的吧? 问题分析过程 ...
- 【新能源】这家新能源汽车动力电池工厂车间视频,最近刷爆了朋友圈!!
很多人都知道,前段时间,欧洲一些国家,相继发布了禁售燃油车的时间和计划,全世界似乎都要跨入新能源汽车的时代,发动机是燃油车的心脏,而新能源汽车的心脏,则是动力电池:新能源汽车的发展正在将中国汽车产业带 ...
最新文章
- 后氧传感器正常数据_氧传感器正常数据流
- I - Watering Flowers CodeForces - 617C
- The application does not contain a valid bundle identifier.解决方法
- 微信开发系列之九 - 在微信里直接创建SAP C4C的社交媒体消息
- 守护线程 java 1615478655
- 关于Windowsn 7因验证未通过被视为“非正版”出现“黑屏”的应急处理预案
- 数据结构 Tricks(一)—— 父节点和左右孩子索引号之间的关系
- ubuntu 安装 mujoco-py
- 用js实现贪吃蛇网页游戏
- 快乐大本营html5小游戏,快乐大本营小游戏规则-新年小游戏.doc
- 感悟篇:我在B端做数据分析(一)
- 004---css样式表(内部样式表、行内样式表、外部样式表)
- TCP三次握手中SYN,ACK,seq ack的含义
- 实战经验:大数据分析为什么大多数会失败?
- 华中科技大学计算机组成,华中科技大学计算机组成原理.pptx
- JAVA网络爬爬学习之HttpClient+Jsoup
- lintcode落单的数
- Unix系统下修改密码
- window10专业版下:docker中k8s安装
- linux下用shell脚本删除mysql记录数量比较多的表。