一:背景

1. 讲故事

最近不知道咋了,各种程序有问题都寻上我了,你说 .NET 程序有问题找我能理解,Windows 崩溃找我,我也可以试试看,毕竟对 Windows 内核也知道一丢丢,那 Visual Studio 有问题找我就说不过去了,但又不好拒绝,就让朋友发下卡死的 dump 我看一看。

二:WinDbg 分析

1. 到底是哪里的卡死

因为 VS 是窗体程序,所以在卡死的时候看下主线程便知,使用 ~0s;!clrstack 即可。


0:000> k
# Child-SP RetAddr Call Site
00 0000004b`acaf9b90 000001ed`309f0f28 0x00007ffb`1b77bfe8
01 0000004b`acaf9b98 00007ffb`4a03e397 0x000001ed`309f0f28
02 0000004b`acaf9ba0 00007ffb`4a04c08e PresentationFramework_ni!System.Windows.Controls.ItemContainerGenerator.DoLinearSearch+0x1d7
03 0000004b`acaf9c70 00007ffb`4ab3bd36 PresentationFramework_ni!System.Windows.Controls.ItemContainerGenerator.ContainerFromItem+0x8e
04 0000004b`acaf9ce0 00007ffb`4ab3bd6e PresentationFramework_ni!System.Windows.Automation.Peers.ItemAutomationPeer.GetWrapper+0xc6
05 0000004b`acaf9d20 00007ffb`4ab3c94f PresentationFramework_ni!System.Windows.Automation.Peers.ItemAutomationPeer.GetWrapperPeer+0xe
06 0000004b`acaf9d60 00007ffb`4ba3f72c PresentationFramework_ni!System.Windows.Automation.Peers.ItemAutomationPeer.IsControlElementCore+0xf
07 0000004b`acaf9d90 00007ffb`4ba42026 PresentationCore_ni!System.Windows.Automation.Peers.AutomationPeer.IsControlElement+0x3c
08 0000004b`acaf9de0 00007ffb`4ba41e8b PresentationCore_ni!System.Windows.Automation.Peers.AutomationPeer.IsControlElement+0x36
09 0000004b`acaf9e20 00007ffb`4bcc5632 PresentationCore_ni!System.Windows.Automation.Peers.AutomationPeer.GetPropertyValue+0x7b
0a 0000004b`acaf9e70 00007ffb`4c182cf8 PresentationCore_ni!MS.Internal.Automation.ElementUtil.<>c__DisplayClass11_0.<Invoke>b__0+0x32
0b 0000004b`acaf9eb0 00007ffb`4c182bf6 WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.InternalRealCall+0x68
0c 0000004b`acaf9f20 00007ffb`4c180202 WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.TryCatchWhen+0x36
0d 0000004b`acaf9f70 00007ffb`4bca4423 WindowsBase_ni!System.Windows.Threading.Dispatcher.LegacyInvokeImpl+0x172
0e 0000004b`acafa010 00007ffb`480629e1 PresentationCore_ni!MS.Internal.Automation.ElementUtil.Invoke+0xb3
0f 0000004b`acafa070 00007ffb`7af71059 UIAutomationTypes_ni+0x729e1
10 0000004b`acafa0e0 00007ffb`7ae13eba clr!COMToCLRDispatchHelper+0x39
11 0000004b`acafa110 00007ffb`7af70fb7 clr!COMToCLRWorker+0x1ea
12 0000004b`acafa1b0 00007ffb`625b4cc9 clr!GenericComCallStub+0x57
...

我丢,这线程栈一看有意外发现哈,这 PresentationCore_ni 不是 WPF 的专用库嘛,下面还有 clr ,看样子 VS 的UI是 WPF 写的,顿时有一种亲切感,那既然是 .NET 程序我还是可以分析的。

进一步观察线程栈,可以看到它没有非托管的部分,诸如:user32.dllntdll.dll,也就说明此时的卡死只是托管层面,接下来使用 sos 专有的 !clrstack 观察,删减后如下:


0:000> !clrstack
OS Thread Id: 0x8144 (0)
Child SP IP Call Site
0000004bacafa220 00007ffb1b77bfe8 [ComMethodFrame: 0000004bacafa220]
0000004bacafb0d8 00007ffb1b77bfe8 [InlinedCallFrame: 0000004bacafb0d8] MS.Win32.UnsafeNativeMethods.OleSetClipboard(System.Runtime.InteropServices.ComTypes.IDataObject)
0000004bacafb0d8 00007ffb4c357e22 [InlinedCallFrame: 0000004bacafb0d8] MS.Win32.UnsafeNativeMethods.OleSetClipboard(System.Runtime.InteropServices.ComTypes.IDataObject)
0000004bacafb0a0 00007ffb4c357e22 DomainNeutralILStubClass.IL_STUB_PInvoke(System.Runtime.InteropServices.ComTypes.IDataObject)
0000004bacafb180 00007ffb4ba0f5ed System.Windows.Clipboard.CriticalSetDataObject(System.Object, Boolean)
0000004bacafb1c0 00007ffae3b1bd6a Microsoft.VisualStudio.Text.Utilities.WpfClipboardService.SetData(System.String, System.String, System.String, Boolean, System.String, Boolean, Boolean)
0000004bacafb210 00007ffae3b1bc1c Microsoft.VisualStudio.Text.Operations.Implementation.EditorOperations.CopyToClipboard(System.String, System.String, Boolean, Boolean)
0000004bacafb270 00007ffae3b199a2 Microsoft.VisualStudio.Text.Operations.Implementation.EditorOperations+c__DisplayClass176_0.b__0()
0000004bacafb2a0 00007ffae3b196ca Microsoft.VisualStudio.Text.Operations.Implementation.EditorOperations.CopySelection()
...
0000004bacafcc20 00007ffb2edd765b JetBrains.ReSharper.Feature.Services.Clipboard.CopyPasteAssistManager.DoCopyOrCut(JetBrains.Application.DataContext.IDataContext, JetBrains.Application.UI.Actions.DelegateExecute)
0000004bacafcc70 00007ffb2edd7628 JetBrains.ReSharper.Feature.Services.Clipboard.CopyPasteAssistManager.DoCopyOrCut(JetBrains.Application.DataContext.IDataContext, JetBrains.Application.UI.Actions.DelegateExecute)
0000004bacafcd00 00007ffb2edd5407 JetBrains.ReSharper.InplaceRefactorings.CutCopyPaste.CopyPasteManager.DoCopyOrCut(JetBrains.Application.DataContext.IDataContext, Boolean, JetBrains.Application.UI.Actions.DelegateExecute)
0000004bacafcd70 00007ffb2edd53c4 JetBrains.ReSharper.InplaceRefactorings.CutCopyPaste.CopyPasteManager.DoCopyOrCut(JetBrains.Application.DataContext.IDataContext, Boolean, JetBrains.Application.UI.Actions.DelegateExecute)
0000004bacafce50 00007ffb2edd4d88 JetBrains.ReSharper.Feature.Services.Clipboard.ClipboardActionHandler.Execute(JetBrains.Application.DataContext.IDataContext, JetBrains.Application.UI.Actions.DelegateExecute)
...
0000004bacafdc40 00007ffb2268a2da DomainNeutralILStubClass.IL_STUB_COMtoCLR(IntPtr, Int32, Int32, Int64, Int64)
0000004bacafde00 00007ffb7af71011 [ComMethodFrame: 0000004bacafde00]

从卦中看,是在处理剪贴板OleSetClipboard的逻辑中一直出不来,而且还有一个外来的 JetBrains.ReSharper 插件,看样子朋友的某些操作让 Resharper 介入了。

为了进一步验证是不是 Resharper 导致的,可以根据 ip 找到所属的模块。


0:000> !ip2md 00007ffb2edd5407
MethodDesc: 00007ffb28e984b0
Method Name: JetBrains.ReSharper.InplaceRefactorings.CutCopyPaste.CopyPasteManager.DoCopyOrCut(JetBrains.Application.DataContext.IDataContext, Boolean, JetBrains.Application.UI.Actions.DelegateExecute)
Class: 00007ffb28ea1b40
MethodTable: 00007ffb28e98578
mdToken: 00000000060000aa
Module: 00007ffb201c48b8
IsJitted: yes
CodeAddr: 00007ffb2edd4f60
Transparency: Critical
0:000> !DumpModule /d 00007ffb201c48b8
Name: C:\Users\Administrator\AppData\Local\JetBrains\Installations\ReSharperPlatformVs17_265273ed_001\JetBrains.ReSharper.InplaceRefactorings.dll
Attributes: PEFile SupportsUpdateableMethods
Assembly: 000001edb0cce780
LoaderHeap: 0000000000000000
TypeDefToMethodTableMap: 00007ffb201d0020
TypeRefToMethodTableMap: 00007ffb201d03a8
MethodDefToDescMap: 00007ffb201d10a0
FieldDefToDescMap: 00007ffb201d21c0
MemberRefToDescMap: 0000000000000000
FileReferencesMap: 00007ffb201d2ae0
AssemblyReferencesMap: 00007ffb201d2ae8
MetaData start address: 000001edb6b8a960 (103320 bytes)

从卦中的 Name 来看,再一次确认了 ReSharper 的问题。

2. ReSharper 是阻塞还是死锁

本着 4S 店只换不修的思路,让朋友直接卸载掉VS中的 ReSharper 肯定是没问题的,但为了兴趣继续探究下 Resharper 正在做什么?

从汇编代码看,当前正准备做两个 if 判断,而且都是 true,最后跳转到 IGeneratorHost.View 属性中,不管怎么说,这里还是不断的处理,所以我觉得这里的阻塞要么是 死循环 出不来,要么还需要再等等。

可能有些朋友好奇,Resharper 塞入到剪贴板中到底是什么数据,要想挖这个信息,可以看汇编从线程栈提取,这次就不搞这么复杂了,换个思路吧,先看 CriticalSetDataObject 方法源码,输出如下:


internal static void CriticalSetDataObject(object data, bool copy)
{ IComDataObject dataObject; if (data is DataObject)
{
dataObject = (DataObject)data;
}
else if (data is IComDataObject)
{
SecurityHelper.DemandUnmanagedCode();
dataObject = (IComDataObject)data;
}
else
{
dataObject = new DataObject(data);
}
...
}

接下来用 !dso 看下有没有类似的 DataObjectIComDataObject 对象,输出如下:


0:000> !dso
OS Thread Id: 0x8144 (0)
RSP/REG Object Name
...
0000004BACAFB138 000001ed401e9ec8 System.Windows.DataObject
... 0:000> !mdt 000001ed401e9ec8
000001ed401e9ec8 (System.Windows.DataObject)
_innerData:000001ed401e9ee0 (System.Windows.DataObject+DataStore)
0:000> !mdt 000001ed401e9ee0
000001ed401e9ee0 (System.Windows.DataObject+DataStore)
_data:000001ed401e9ef8 (System.Collections.Hashtable)
0:000> !mdt 000001ed401e9ef8
000001ed401e9ef8 (System.Collections.Hashtable)
buckets:000001ed401e9f48 (System.Collections.Hashtable+bucket[], Elements: 3, ElementMT=00007ffb79123af8)
count:0x2 (System.Int32)
occupancy:0x1 (System.Int32)
loadsize:0x2 (System.Int32)
loadFactor:0.720000 (System.Single)
version:0x2 (System.Int32)
isWriterInProgress:false (System.Boolean)
keys:NULL (System.Collections.ICollection)
values:NULL (System.Collections.ICollection)
_keycomparer:NULL (System.Collections.IEqualityComparer)
_syncRoot:NULL (System.Object)
expand all 2 items
0:000> !mdt 000001ed401e9f48
000001ed401e9f48 (System.Collections.Hashtable+bucket[], Elements: 3, ElementMT=00007ffb79123af8)
expand all 3 items
0:000> !mdt -e:2 000001ed401e9f48
000001ed401e9f48 (System.Collections.Hashtable+bucket[], Elements: 3, ElementMT=00007ffb79123af8)
[0] (System.Collections.Hashtable+bucket) VALTYPE (MT=00007ffb79123af8, ADDR=000001ed401e9f58)
key:000001ed310ea6f0 (System.String) Length=11, String="UnicodeText"
val:000001ed401e9fd0 (System.Windows.DataObject+DataStore+DataStoreEntry[], Elements: 1)
hash_coll:0xf337c502 (System.Int32)
[1] (System.Collections.Hashtable+bucket) VALTYPE (MT=00007ffb79123af8, ADDR=000001ed401e9f70)
key:000001ed310eaa08 (System.String) Length=16, String="Rich Text Format"
val:000001ed401ea018 (System.Windows.DataObject+DataStore+DataStoreEntry[], Elements: 1)
hash_coll:0x30818946 (System.Int32)
[2] (System.Collections.Hashtable+bucket) VALTYPE (MT=00007ffb79123af8, ADDR=000001ed401e9f88)
key:NULL (System.Object)
val:NULL (System.Object)
hash_coll:0x0 (System.Int32)
increase depth
0:000> !mdt 000001ed401ea018
000001ed401ea018 (System.Windows.DataObject+DataStore+DataStoreEntry[], Elements: 1)
expand all 1 items
0:000> !mdt -e:2 000001ed401ea018
000001ed401ea018 (System.Windows.DataObject+DataStore+DataStoreEntry[], Elements: 1)
[0] 000001ed401e9ff0 (System.Windows.DataObject+DataStore+DataStoreEntry)
_data:000001ed401635e8 (System.String) Length=1165, String="{\rtf\ansi{\fonttbl{\f0 NSimSun;}}{\colortbl;\red0\green0\blue255;\red0\green0\blue0;\red0\green128\blue0;}\f0 \fs19 \cf1 \cb0 \highlight0 var\cf2 hostname = System.Net.Dns.GetHostName();\par System.Net.IPAddress[] hostaddrs = System.Net.Dns.GetHostAddresses(hostname);\par \par \cf1 var\cf2 localIPList = \cf1 new\cf2 List<IPAddress>();\par \cf1 for\cf2 (\cf1 int\cf2 i = 0; i < hostaddrs.Length; i++)\par \{\par \cf1 if\cf2 (System.Net.Sockets.AddressFamily.InterNetwork == hostaddrs[i].AddressFamily)\par \{\par \cf1 if\cf2 (hostaddrs[i].ToString().Equals(_localIP))\par \{\par localIPList.Insert(0, hostaddrs[i]);\cf3 //\uc1\u20248?\uc1\u20808?\uc1\u20351?\uc1\u29992?\uc1\u19978?\uc1\u27425?\uc1\u-28706?\uc1\u25509?IP\cf2 \par \}\par \cf1 else\cf2 \par \{\par localIPList.Add(hostaddrs[i]);\par \}\par \}\par \}}"
_autoConvert:true (System.Boolean)
_aspect:0x1 (System.Runtime.InteropServices.ComTypes.DVASPECT)
_index:0x0 (System.Int32)
increase depth

简单整理了下大概是这样的代码。

            var hostname = System.Net.Dns.GetHostName();
System.Net.IPAddress[] hostaddrs = System.Net.Dns.GetHostAddresses(hostname); var localIPList = new List<IPAddress>();
for (int i = 0; i < hostaddrs.Length; i++)
{
if (System.Net.Sockets.AddressFamily.InterNetwork == hostaddrs[i].AddressFamily)
{
if (hostaddrs[i].ToString().Equals(_localIP))
{
localIPList.Insert(0, hostaddrs[i]);//优先使用上次连接IP
}
else
{
localIPList.Add(hostaddrs[i]);
}
}
}

有了这些信息,还是先让朋友把 Reshaper 卸载掉看看,据朋友反馈在 Resharper 官方的 issue 里找到了解决方案,禁用了如下选项,暂时没有出现任何问题,截图如下:

三:总结

综合朋友的反馈,这次VS的卡死就是他按下了 Ctrl+C 复制这段代码的时候,Resharper 插件介入,然后在处理富文本时出问题了,不知道大家可踩过类似的坑,算是给后来人一点定位经验吧。

记一次 Visual Studio 2022 卡死分析的更多相关文章

  1. .NET6系列:Visual Studio 2022 线路图

    系列目录     [已更新最新开发文章,点击查看详细] 在上一篇博客<Visual Studio 2022>中介绍了VS2022的性能改进与重要功能.本文主要介绍在 Visual Stud ...

  2. Visual Studio 2022 git error Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa

    前言 前两天因为升级了Git导致git提交拉取的时候都提示下面这个异常,然后经过一番折腾以后终于把这个问题解决了.但是今天我升级了下Visual Studio 2022将其升级到了17.1.3版本然后 ...

  3. 11个Visual Studio代码性能分析工具

    软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行代码分析和 ...

  4. .NET 11 个 Visual Studio 代码性能分析工具

    原文地址 软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行 ...

  5. [翻译]正式宣布 Visual Studio 2022

    原文: [Visual Studio 2022] 首先,我们要感谢正在阅读这篇文章的你,我们所有的产品开发都始于你也止于你,无论你是在开发者社区上发帖,还是填写了调查问卷,还是向我们发送了反馈意见,或 ...

  6. 它来了!!!有史以来第一个64位Visual Studio(2022)预览版将在今夏发布!

    美国时间2021年4月19日,微软产品研发部一位负责人Amanda Silver在其博客上发布一则<Visual Studio 2022>的消息,表示将在今年(2021年)夏天发布Visu ...

  7. .NET6系列:微软正式宣布Visual Studio 2022

    系列目录     [已更新最新开发文章,点击查看详细] 首先,我们要感谢正在阅读这篇文章的你,我们所有的产品开发都始于你也止于你,无论你是在开发者社区上发帖,还是填写了调查问卷,还是向我们发送了反馈意 ...

  8. 微软发布了Visual Studio 2022 Preview 1 以及.NET 6 Preview 5

    Microsoft 今天宣布了Visual Studio 2022 的第一个预览版,并且同时也发布了.NET 6 Preview 5. https://devblogs.microsoft.com/v ...

  9. Visual Studio 2022 Preview 1 和.NET 6 Preview 5 正式发布

    具有里程碑意义的Visual Studio 2022 Preview 1正式发布,重点是64位,而没有增加新功能,并且同时也发布了.NET 6 Preview 5. https://devblogs. ...

  10. 乘风破浪,遇见Visual Studio 2022预览版(Preview),宇宙最强开发者工具首次迎来64位版本

    简介 众所周知,我们从官方新闻来看,对Visual Studio 2022最大的期待莫过于:其是首个64位的Visual Studio,这个宇宙最强开发者工具一脚迈入了新的阶段. https://vi ...

随机推荐

  1. maven 多模块项目的测试覆盖率分析 - jacoco 聚合分析

    前言 对于大多数 maven 多模块化工程,可以使用 Jacoco 这款工具,关于 Jacoco 这款工具,ChatGPT 对它的描述是这样的: JaCoCo(Java Code Coverage)是 ...

  2. echart 解决setOption线残留

    前言: Antd + echarts 我想要实现的是点击表的某一行自动生成对应的折线图,我在点击第一行生成5条线,我在点击第二行的时候,本该生成2条线,结果还是5条线: 最开始我以为设置的 serie ...

  3. Android--观察APP运行日志以及APP的工程目录结构解释

    运行日志 Log:d--便于跟踪调试 APP开发基础 APP的运行环境 第一种情况,就是在Android studio软件客户端上面使用模拟器运行APP 第二种情况,就是使用真实的手机运行APP程序 ...

  4. 对Javaweb的相关练习之利用.jsp文件和.java文件将输入的数据存储到指定的数据库中

    练习分析 import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.* ...

  5. 一文带你吃透Redis

    目录 1. 基本数据结构 2. 数据持久化 3. 高可用 4. 缓存 文章字数大约1.9万字,阅读大概需要66分钟,建议收藏后慢慢阅读!!! 1. 基本数据结构 什么是Redis Redis是一个数据 ...

  6. 单元测试Mockito框架

    单元测试Mockito框架 Mock 测试就是在测试过程中,对于某些 不容易构造(如 HttpServletRequest 必须在 Servlet 容器中才能构造出来)或者不容易获取 比较复杂 的对象 ...

  7. FreeSWITCH的originate命令解析及示例

    FreeSWITCH版本:1.10.9 操作系统:CentOS 7.6.1810 originate经常用于发起呼叫,在实际工作过程中用到的也比较多,今天总结下基本用法,也方便我以后查阅. 一.wik ...

  8. 鼎捷ERP二次开发教程 Tiptop GP开发资料大全 Tipto开发实战经验 鼎捷开发实战例子 Tiptop GP二次开发项目例子 4GL开发Demo 鼎捷二次开发完整例子 鼎捷ERP二次开发入门

    本人在ERP实施公司做顾问四五年,参与企业实施ERP十多个项目,非常熟悉企业ERP流程,在实施过程遇到众多问题,提出了不少根据企业具体情况的解决方案. 曾经参与鼎捷Tiptop GP实施十多个项目,具 ...

  9. 电商平台趋势妙手采集类API接口

    电商平台趋势,平台化.大家可以看到大的电商都开始有自己的平台,其实这个道理很清楚,就是因为这是充分利用自己的流量.自己的商品和服务大效益化的一个过程,因为有平台,可以利用全社会的资源弥补自己商品的丰富 ...

  10. k8s集群进行删除并添加node节点

    在已建立好的k8s集群中删除节点后,进行添加新的节点,可参考用于添加全新node节点,若新的node需要安装docker和k8s基础组件. 建立集群可以参考曾经的文章:CentOS8 搭建Kubern ...