国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

記一次 .NET 某醫(yī)院門診軟件 卡死分析

開(kāi)發(fā) 前端
去掉了意外的 speech.SpeakAsyncCancelAll();? 語(yǔ)句就搞定了,內(nèi)部深層邏輯也沒(méi)有再探究了,大概率就是意外的 _queueIn 為 0,讓 waveOutReset? 和 waveOutClose 方法沒(méi)有匹配出現(xiàn),造成了卡死現(xiàn)象。

一:背景

1. 講故事

前幾天有位朋友找到我,說(shuō)他們的軟件在客戶那邊卡死了,讓我?guī)兔聪率窃趺椿厥拢课揖妥屌笥言诔绦蚩ㄋ赖臅r(shí)候通過(guò) 任務(wù)管理器 抓一個(gè) dump 下來(lái),雖然默認(rèn)抓的是 wow64 ,不過(guò)用 soswow64.dll 轉(zhuǎn)還是可以的,參考命令如下:

.load C:\soft\soswow64\soswow64.dll
    !wow64exts.sw

接下來(lái)就可以分析了哈。

二:WinDbg 分析

1. 為什么會(huì)卡死

首先用 !t 簡(jiǎn)單看一下主線程的 COM Apartment 模式,如果是 STA 那就是窗體程序,比如 WPF,WinForm 之類的,輸出如下:

0:000:x86> !t
ThreadCount:      39
UnstartedThread:  0
BackgroundThread: 12
PendingThread:    0
DeadThread:       26
Hosted Runtime:   no
                                                                         Lock  
       ID OSID ThreadOBJ    State GC Mode     GC Alloc Context  Domain   Count Apt Exception
   0    1 1928 01aee0b0   2026020 Preemptive  041D496C:00000000 01ae88a8 2     STA 
   ...

既然是窗體程序那就看主線程吧,使用 ~0s;!clrstack 命令。

0:000:x86> !clrstack
OS Thread Id: 0x1928 (0)
Child SP       IP Call Site
0177dff8 0167e1f8 [HelperMethodFrame_1OBJ: 0177dff8] System.Threading.SynchronizationContext.WaitHelper(IntPtr[], Boolean, Int32)
0177e29c 6a6fc693 System.Windows.Threading.DispatcherSynchronizationContext.Wait(IntPtr[], Boolean, Int32)
0177e2b0 71e36d54 System.Threading.SynchronizationContext.InvokeWaitMethodHelper(System.Threading.SynchronizationContext, IntPtr[], Boolean, Int32) [f:\dd\ndp\clr\src\BCL\system\threading\synchronizationcontext.cs @ 349]
0177e4d8 73220076 [GCFrame: 0177e4d8] 
0177e5f8 73220076 [GCFrame: 0177e5f8] 
0177e6d8 73220076 [GCFrame: 0177e6d8] 
0177e6f4 73220076 [HelperMethodFrame_1OBJ: 0177e6f4] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
0177e770 18078b93 System.Speech.Internal.Synthesis.AudioDeviceOut.Abort()
0177e79c 17270698 System.Speech.Internal.Synthesis.VoiceSynthesis.Abort()
0177e7e8 065ec76b System.Speech.Synthesis.SpeechSynthesizer.SpeakAsyncCancelAll()
0177e7f0 065ec728 xxx.xxx.Speek(System.String)
...

從卦中看是一個(gè) 語(yǔ)音模塊,還有 Speek 功能,挺有意思。。。還 Speek 啥呢?可以用 !mdso 看一下。

0:000:x86> !mdso
Thread 0:
Location          Object            Type
------------------------------------------------------------
0177e060  04176eb8  System.IntPtr[]
...
0177e7f8  03be9504  System.String  "請(qǐng)先登錄驗(yàn)證身份"

哈哈,上面只是花絮,繼續(xù)看線程棧會(huì)發(fā)現(xiàn)代碼卡在 Monitor.ReliableEnter 上,也就是等待 lock 鎖,接下來(lái)用 kb 把 鎖對(duì)象提取出來(lái),即 clr!JITutil_MonReliableEnter 方法的第一個(gè)參數(shù) 03be11b4,輸出如下:

0:000:x86> kb
...
17 0177e768 18078b93     03be11b4 00000000 00000000 clr!JITutil_MonReliableEnter+0xb5
18 0177e794 17270698     0177e7bc 73252799 00000000 0x18078b93
19 0177e7e0 065ec76b     0177e808 065ec728 00000000 0x17270698
1a 0177e7e8 065ec728     00000000 03a0b318 03be9504 0x65ec76b
1b 0177e808 1727e09f     00000000 03be0920 04158b98 0x65ec728
1c 0177e824 69181324     04175c04 041199c0 00000001 0x1727e09f
...

0:000:x86> !do 03be11b4
Name:        System.Object
MethodTable: 71f200f4
EEClass:     71a715b0
Size:        12(0xc) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Object
Fields:
None

有了這個(gè)對(duì)象就可以用 !syncblk 命令觀察同步塊表,到底是哪個(gè)線程在持有不釋放?

0:000:x86> !syncblk
Index         SyncBlock MonitorHeld Recursion Owning Thread Info          SyncBlock Owner
   96 11ac3ee0            3         1 11af0f28 35d4  13   03be11b4 System.Object
-----------------------------
Total           931
CCW             39
RCW             19
ComClassFactory 2
Free            802

0:000:x86> ~13s;!clrstack
ntdll_76fc0000!NtWaitForSingleObject+0xc:
7703159c c20c00          ret     0Ch
OS Thread Id: 0x35d4 (13)
Child SP       IP Call Site
17f8f23c 0000002b [InlinedCallFrame: 17f8f23c] 
17f8f238 1adf3269 DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr)
17f8f23c 1adf2e82 [InlinedCallFrame: 17f8f23c] System.Speech.Internal.Synthesis.SafeNativeMethods.waveOutClose(IntPtr)
17f8f26c 1adf2e82 System.Speech.Internal.Synthesis.AudioDeviceOut.End()
17f8f298 187a5cd6 System.Speech.Internal.Synthesis.VoiceSynthesis.SpeakText(System.Speech.Internal.Synthesis.SpeakInfo, System.Speech.Synthesis.Prompt, System.Collections.Generic.List`1<System.Speech.Internal.Synthesis.LexiconEntry>)
17f8f304 17271669 System.Speech.Internal.Synthesis.VoiceSynthesis.ThreadProc()
17f8f3b8 71e3710d System.Threading.ThreadHelper.ThreadStart_Context(System.Object) [f:\dd\ndp\clr\src\BCL\system\threading\thread.cs @ 74]
17f8f3c4 71e640c5 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 954]
17f8f430 71e63fd6 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 902]
17f8f444 71e63f91 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 891]
17f8f45c 71e37068 System.Threading.ThreadHelper.ThreadStart() [f:\dd\ndp\clr\src\BCL\system\threading\thread.cs @ 111]
17f8f5a0 73220076 [GCFrame: 17f8f5a0] 
17f8f784 73220076 [DebuggerU2MCatchHandlerFrame: 17f8f784] 


0:013:x86> !t
  ...
  13   14 35d4 11af0f28     2b220 Preemptive  00000000:00000000 01ae88a8 2     MTA 
  ...

從卦中信息看:13號(hào)線程持有了 lock 鎖,并且它非線程池線程,而是通過(guò) new Thread 出來(lái)的,從線程棧看都是sdk函數(shù),綜合這些信息,應(yīng)該是 VoiceSynthesis 創(chuàng)建出來(lái)的后臺(tái)線程,下面的圖也可以佐證。

圖片

接下來(lái)繼續(xù)看,從線程棧頂上可以觀察到最后卡在了 System.Speech.Internal.Synthesis.SafeNativeMethods.waveOutClose 方法處,逆向之后的代碼如下:

// System.Speech.Internal.Synthesis.AudioDeviceOut
    internal override void End()
    {
        if (!_deviceOpen)
        {
            throw new InvalidOperationException();
        }
        lock (_noWriteOutLock)
        {
            _deviceOpen = false;
            CheckForAbort();
            if (_queueIn.Count != 0)
            {
                SafeNativeMethods.waveOutReset(_hwo);
            }
            MMSYSERR mMSYSERR = SafeNativeMethods.waveOutClose(_hwo);
        }
    }

由于這是 Windows 的 VoiceSynthesis 模塊封裝底層函數(shù),經(jīng)過(guò)千錘百煉,理論上出問(wèn)題的概率會(huì)非常小,除非上層有不合理的調(diào)用,這種概率會(huì)大一些。

2. 是上層不合理的調(diào)用嗎

這一塊我也沒(méi)玩過(guò),網(wǎng)上搜一下 waveOutReset , waveOutClose ,看下有沒(méi)有同病相憐的人,結(jié)果網(wǎng)上一搜一堆,比如下面這樣:

圖片

圖片

不管怎么說(shuō),這一塊如果處理不好容易出現(xiàn)死鎖和卡死的情況,那是不是正如圖中所說(shuō) waveOutReset 和 waveOutClose 沒(méi)有匹配造成的呢?

這就取決于代碼中的 _queueIn 集合,可以觀察這兩個(gè)函數(shù)的匯編代碼提取出這個(gè)變量。

0:013:x86> !U /d 1adf2e82
Normal JIT generated code
System.Speech.Internal.Synthesis.AudioDeviceOut.End()
...
1adf2e30 8bf1            mov     esi,ecx
...
1adf2e69 8b4608          mov     eax,dword ptr [esi+8]
1adf2e6c 83780c00        cmp     dword ptr [eax+0Ch],0
1adf2e70 7408            je      1adf2e7a
...

0:013:x86> !U /d 187a5cd6
Normal JIT generated code
System.Speech.Internal.Synthesis.VoiceSynthesis.SpeakText(System.Speech.Internal.Synthesis.SpeakInfo, System.Speech.Synthesis.Prompt, System.Collections.Generic.List`1<System.Speech.Internal.Synthesis.LexiconEntry>)
...
187a5cc8 8b45d0          mov     eax,dword ptr [ebp-30h]
187a5ccb 8b486c          mov     ecx,dword ptr [eax+6Ch]
187a5cd3 ff5014          call    dword ptr [eax+14h]
>>> 187a5cd6 58              pop     eax
...


0:013:x86> kb 10
 # ChildEBP RetAddr      Args to Child              
...
08 17f8f264 1adf2e82     03be11b4 00000001 00000000 0x1adf3269
09 17f8f290 187a5cd6     187a5e16 03be0d24 043f3520 0x1adf2e82
0a 17f8f2f4 17271669     040efa14 040ef9a4 732515d8 0x187a5cd6
0b 17f8f3b0 71e3710d     03ff3e98 17f8f420 71e640c5 0x17271669
...

仔細(xì)觀察上面的匯編代碼:eax 來(lái)自于 esi,esi 來(lái)自于 ecx,ecx 最終來(lái)自于父函數(shù)中的 ebp-30h 的位置,串聯(lián)起來(lái)的命令就是 !do poi(poi(poi(17f8f2f4-30)+6c)+0x8) ,接下來(lái)我們 do 一下。

0:000:x86> !do poi(poi(poi(17f8f2f4-30)+6c)+0x8)
Name:        System.Collections.Generic.List`1[[System.Speech.Internal.Synthesis.AudioDeviceOut+InItem, System.Speech]]
MethodTable: 16cf20ec
EEClass:     71af6f8c
Size:        24(0x18) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
71f2f320  4001891        4     System.__Canon[]  0 instance 03c74538 _items
71f21bb4  4001892        c         System.Int32  1 instance        0 _size
71f21bb4  4001893       10         System.Int32  1 instance     1900 _version
71f200f4  4001894        8        System.Object  0 instance 00000000 _syncRoot
71f2f320  4001895        4     System.__Canon[]  0   static  <no information>

可以看到此時(shí)的 _size=0 ,有可能就是因?yàn)樯蠈硬缓侠碚{(diào)用導(dǎo)致這里的 _queueIn 意外為 0 ,最終引發(fā)的卡死現(xiàn)象。

3. 真相大白

一時(shí)之間也找不到上層哪里有不合理的調(diào)用,接下來(lái)的思路還是自己研讀主線程和13號(hào)線程的調(diào)用棧,最后發(fā)現(xiàn)一個(gè)可疑的現(xiàn)象,截圖如下:

圖片

通過(guò)仔細(xì)研讀底層代碼,Speek 會(huì)將消息丟到底層的queue隊(duì)列中,后臺(tái)線程會(huì)提取處理,這里的 SpeakAsyncCancelAll 是完全沒(méi)必要的。

有了這個(gè)消息,就讓朋友把這個(gè)函數(shù)去掉觀察下試試,據(jù)朋友反饋說(shuō)沒(méi)有問(wèn)題了。

圖片

三:總結(jié)

這個(gè)案例中去掉了意外的 speech.SpeakAsyncCancelAll(); 語(yǔ)句就搞定了,內(nèi)部深層邏輯也沒(méi)有再探究了,大概率就是意外的 _queueIn 為 0,讓 waveOutReset 和 waveOutClose 方法沒(méi)有匹配出現(xiàn),造成了卡死現(xiàn)象。

責(zé)任編輯:武曉燕 來(lái)源: 一線碼農(nóng)聊技術(shù)
相關(guān)推薦

2023-09-27 07:23:10

.NET監(jiān)控軟件

2025-09-02 01:35:00

.NET光學(xué)定位軟件

2024-05-20 09:39:02

.NETurl線程池

2022-10-13 18:40:05

.NETOA后端

2024-07-01 13:00:24

.NET網(wǎng)絡(luò)邊緣計(jì)算

2024-11-29 10:06:59

2022-01-17 21:28:36

管理系統(tǒng).NET

2024-09-14 10:28:56

.NET卡死程序

2023-07-06 10:11:38

.NET模式dump

2024-12-27 13:31:18

.NETdump調(diào)試

2024-06-06 10:51:15

自動(dòng)化系統(tǒng)推測(cè)

2024-05-28 10:18:30

WPF程序數(shù)據(jù)

2023-10-07 13:28:53

.NET軟件賬本

2024-05-31 12:56:06

.NET代碼方法

2022-10-09 10:47:37

NET視覺(jué)軟件

2023-06-26 00:12:46

2024-03-28 12:56:36

2023-04-06 10:52:18

2023-03-26 20:24:50

ERP網(wǎng)站系統(tǒng)

2024-07-12 11:20:34

.NET崩潰視覺(jué)程序
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

97av在线影院| 久久人91精品久久久久久不卡| 欧美极品少妇无套实战| 亚洲精品白浆高清| 欧美精品一区二区久久婷婷 | 亚洲国产高清在线观看视频| 精品欧美一区二区久久久伦| 久久99国产精品视频| 最近2019中文字幕mv免费看 | 日韩午夜中文字幕| 天海翼一区二区三区四区在线观看| 久久精品久久综合| 国产精品果冻传媒潘| 亚洲精品亚洲人成在线观看| 亚洲午夜未删减在线观看| 欧美性天天影视| 精品成人在线视频| 免费观看一二区视频网站| 久久久国产综合精品女国产盗摄| 中国黄色录像片| 老司机亚洲精品| 激情久久av| 91精品国产乱码久久久久久久 | 国偷自产视频一区二区久| 亚洲网站在线播放| free性欧美| 精品国产一区二区亚洲人成毛片 | 永久免费精品影视网站| 91在线中文| 欧美日韩精品欧美日韩精品一| а√最新版地址在线天堂| 中文字幕欧美国产| 北条麻妃69av| 26uuu国产在线精品一区二区| 中文字幕无码精品亚洲资源网久久| 国产综合久久久久影院| 日韩和欧美的一区二区| 丝袜美腿一区二区三区| 久久婷婷人人澡人人喊人人爽| 亚洲字幕久久| 高清国语自产拍免费一区二区三区| 91麻豆精品国产91久久久平台| 国产精品成人观看视频国产奇米| 国产aⅴ精品一区二区三区久久| 国产91精品青草社区| 亚洲69av| 国产日韩欧美影视| 欧美日本一区二区视频在线观看 | 日韩一区二区三区视频| 免费在线毛片网站| 欧美一区二区三区视频在线| www免费在线观看| 亚洲成人xxx| 日本综合字幕| 蜜臀久久99精品久久久无需会员 | 91黄色小视频| 麻豆tv免费在线观看| 日韩一区二区三区视频在线| 青春草视频在线| 亚洲欧美三级在线| 亚洲国产综合在线观看| 国内精品一区二区三区| 精品在线播放| 高清视频一区| 国产在线播精品第三| 99色精品视频| 一区二区三区欧美日韩| 黄色片视频在线观看| 亚洲福利视频久久| 精品国产三区在线| 97人人爽人人喊人人模波多| 日韩精品午夜| 亚洲乱码一区二区三区三上悠亚| 成人白浆超碰人人人人| 福利在线免费| 欧美一区2区视频在线观看| 成人mm视频在线观看| 国产成人av网址| 免费看黄裸体一级大秀欧美| av无码久久久久久不卡网站| 亚洲同性gay激情无套| h视频在线播放| 色噜噜国产精品视频一区二区| 欧美日韩播放| 久久波多野结衣| 99v久久综合狠狠综合久久| 天天夜夜亚洲| 日韩成人激情在线| 高清日韩中文字幕| 精品一区久久| 久久综合视频网| 超碰国产在线| 中文字幕亚洲欧美在线| 精品一二三区| 国产精品8888| 精品毛片三在线观看| 欧美精品总汇| 亚洲aⅴ日韩av电影在线观看| 国产成人在线免费观看| 中文字幕视频免费在线观看| 亚洲欧美国内爽妇网| 日韩电影免费网址| 国产美女作爱全过程免费视频| 亚洲地区一二三色| 美女毛片一区二区三区四区最新中文字幕亚洲 | 国产成人精品免费| 日韩高清国产精品| 巨胸喷奶水www久久久| 精品少妇一区二区三区在线视频| 国产美女高潮在线观看| 青草热久免费精品视频 | 亚洲永久在线| 亚洲激情一区二区| 国产黄人亚洲片| 一区二区不卡在线视频 午夜欧美不卡'| 久久精品国产精品亚洲精品| 青青在线免费观看| 欧美日韩精品久久久| 国内视频精品| 久草在线资源视频| 欧洲亚洲一区| 欧美大成色www永久网站婷| 欧美影视一区二区三区| 久久欧美中文字幕| 麻豆一区二区在线| **女人18毛片一区二区| 日韩欧美亚洲国产精品字幕久久久| 欧美午夜电影在线观看| 在线观看一区视频| 99久久99热这里只有精品| 欧美日韩水蜜桃| 国产精品22p| 日韩极品在线| 日韩毛片视频| 久久99精品久久久| 国产麻豆91精品| 中文字幕成人网| 亚洲日穴在线视频| 色综合久久99| 9191久久久久久久久久久| 日韩国产精品视频| 一本久久综合亚洲鲁鲁五月天 | 色婷婷av在线| 欧美一级视频免费看| 国产精品久久久久久久久久直播| 91在线精品播放| 欧美精品久久久久a| 久久香蕉频线观| 久久久国产精品x99av| 欧美草草影院在线视频| 欧美国产欧美综合| 国产精品久久久久久麻豆一区软件| 国产高清视频免费最新在线| 1区2区3区国产精品| 亚洲日本天堂| 欧美aaaaaa| 最新国产乱人伦偷精品免费网站| 麻豆freexxxx性91精品| 91精品国产66| 超碰97在线免费| 日本最新一区二区三区视频观看| 欧美精品tushy高清| 亚洲视频在线观看一区| 国产一区二区在线观看免费| 雨宫琴音一区二区三区| 香蕉视频一区二区三区| 中文字幕一区二区三区欧美日韩 | 亚洲高清视频一区二区| 亚洲午夜激情| 欧美中文字幕在线观看视频 | 久久av免费观看| 亚洲天堂网在线观看| 国产精品豆花视频| 欧美日韩爱爱| 波多野结衣一区| 欧美a级在线| 国产成+人+日韩+欧美+亚洲| 国产精品原创巨作av| 在线国产日韩| 亚洲精品进入| 成人网18免费网站| av在线免费观看网| 极品美女扒开粉嫩小泬| 国产精品9999久久久久仙踪林| 91福利视频导航| 欧美一卡2卡3卡4卡无卡免费观看水多多| 亚洲精品一区二区毛豆| 91短视频在线观看| 欧美大胆成人| 一本色道久久综合亚洲精品不卡| 国产精品理论在线观看| 亚洲小视频在线观看| 国产精品v欧美精品∨日韩| 久久青青视频| 欧美挠脚心网站| 福利小视频在线| av软件在线观看| 特黄特黄的视频| 男人天堂网在线观看| 一区二区三区视频播放|