日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

记一次 .NET WPF布草管理系统 挂死分析

發(fā)布時間:2023/12/4 windows 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 记一次 .NET WPF布草管理系统 挂死分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一:背景

1. 講故事

這幾天看的 dump 有點多,有點傷神傷腦,晚上做夢都是dump,今天早上頭暈暈的到公司就聽到背后同事抱怨他負責的WPF程序掛死了,然后測試的小姑娘也跟著抱怨。。。嗨,也不知道是哪一個迭代改出來的問題,反正客戶不起義問題都不大。????????????

不過我聽到程序無響應,內(nèi)心深處真的是一拘靈。。。本能反應吧,給他發(fā)了一個 procdump 過去生成兩個 dump 發(fā)過來。

話說回來,WPF這種帶UI界面的掛死問題其實很好分析的,無非就是 UI線程 失去響應了,至于為啥失去響應了,肯定是做了什么見不得光的事情,比如耍小聰明用 Task.Result,還有一點要特別注意的是 UI 獨有的 SynchronizationContext,如 Winform 的 :WindowsFormsSynchronizationContext ,WPF 的 DispatcherSynchronizationContext,后面我準備開一篇文章用 Windbg 深入剖析一下這個死鎖形成的原因,好,說了這么多,dump 也到了,上 Windbg 分析吧。

二:windbg 分析

1. 審查UI線程

做法很簡單,先通過 ~0s 切到0號,也就是UI線程,再通過 !dumpstack 調(diào)出UI線程的托管和非托管棧,為了保護隱私,我就稍微精簡下。

0:000>?~0s eax=00000000?ebx=01855bf8?ecx=00000000?edx=00000000?esi=00000000?edi=00000000 eip=776a171c?esp=014fe3b8?ebp=014fe410?iopl=0?????????nv?up?ei?pl?nz?na?pe?nc cs=0023??ss=002b??ds=002b??es=002b??fs=0053??gs=002b?????????????efl=00000206 ntdll!NtWaitForSingleObject+0xc: 776a171c?c20c00??????????ret?????0Ch 0:000>?!dumpstack OS?Thread?Id:?0x4ee0?(0) Current?frame:?ntdll!NtWaitForSingleObject+0xc ChildEBP?RetAddr??Caller,?Callee 014fe3b4?7468a9c5?mswsock!SockWaitForSingleObject+0x125,?calling?ntdll!NtWaitForSingleObject 014fe410?7469932c?mswsock!SockDoConnectReal+0x36b,?calling?mswsock!SockWaitForSingleObject 014fe4b4?74698df7?mswsock!SockDoConnect+0x482,?calling?mswsock!SockDoConnectReal 014fe544?74699861?mswsock!WSPConnect+0x61,?calling?mswsock!SockDoConnect 014fe564?77316cf7?ws2_32!WSAConnect+0x77 014fe5a0?6422aeea?(MethodDesc?64088970?+0x5a?DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr,?Byte[],?Int32,?IntPtr,?IntPtr,?IntPtr,?IntPtr)) 014fe5d4?6422aeea?(MethodDesc?64088970?+0x5a?DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr,?Byte[],?Int32,?IntPtr,?IntPtr,?IntPtr,?IntPtr)) 014fe5f4?641c72eb?(MethodDesc?63ff4310?+0x4b?System.Net.Sockets.Socket.DoConnect(System.Net.EndPoint,?System.Net.SocketAddress)),?calling?1d4d538c 014fe628?642160c5?(MethodDesc?640847c4?+0x7d?System.Net.Sockets.Socket.Connect(System.Net.EndPoint)),?calling?(MethodDesc?63ff4310?+0?System.Net.Sockets.Socket.DoConnect(System.Net.EndPoint,?System.Net.SocketAddress)) 014fe644?1d4d5bd3?(MethodDesc?1c93d404?+0x33?xxx.SocketHelper.xxxSocket.Connect(System.Net.IPEndPoint)),?calling?(MethodDesc?640847c4?+0?System.Net.Sockets.Socket.Connect(System.Net.EndPoint)) 014fe660?1d4d5834?(MethodDesc?1c01df50?+0x114?xxx.MainWindow.Connect()),?calling?(MethodDesc?1c93d404?+0?xxx.Utilities.SocketHelper.xxxSocket.Connect(System.Net.IPEndPoint)) 014fe714?1d4d8d84?(MethodDesc?1c01e094?+0x9c?xxx.MainWindow.<IniTimer>b__18_0(System.Object,?System.EventArgs)),?calling?(MethodDesc?1c01df50?+0?xxx.MainWindow.Connect())

從上面的調(diào)用堆棧可以看出,MainWindow 中做了一個 Socket.Connect 連接,最后卡死在非托管的 mswsock!SockDoConnectReal方法上,應該是 Socket 連不上造成的,既然是 Socket ,把它的 ip 和 port 拿出來 telnet 一下不就好啦,對吧,可以用 !dso 把當前線程棧中所有的托管對象找出來。

0:000>?!dso OS?Thread?Id:?0x4ee0?(0) ESP/REG??Object???Name 014FE4D8?03a47588?System.Net.SafeCloseSocket+InnerSafeCloseSocket 014FE598?03a476bc?System.Net.EndpointPermission 014FE5E4?03a4762c?System.Byte[] 014FF068?03681374?System.AppDomain 014FF4D8?03681238?System.SharedStatics 014FE6B4?036a4dfc?System.String????9901 014FE6C4?036a4ba0?System.String????192.168.1.79

哈哈,從最后兩行可以看出,socket 地址就是:192.168.1.79:9901, telnet 一下果然不通,問了下,原來是測試機最近重啟了, Socket 服務端并沒有隨機器啟動,貌似問題就這樣找到了。。。

是不是覺得有哪里不對勁呢?對, 就是為啥要在主線程做 Connect 呢?萬一 Socket 連不上,這不就是把自己陷入不仁不義的地步嘛,問了下實施,說WPF和SocketServer都是一同部署的,據(jù)說在現(xiàn)場也偶爾遇到,可能坑踩多了他們自己也摸索出來了,把 SockerServer 重啟一下就搞定了,不過這次可能研發(fā)自己都看不下去了吧 ????????????, 真是自曝家丑。。。

2. 查看問題代碼

問題還是要解決的,先把問題代碼導出來,用 !name2ee + !savemodule 即可。

0:000>?!name2ee?*!xxx.MainWindow.Connect Module:??????01754044 Assembly:????xxx.exe Token:???????06000af5 MethodDesc:??1c01df50 Name:????????xxx.MainWindow.Connect() JITTED?Code?Address:?1d4d5720 0:000>?!savemodule?01754044??E:\dumps\3.dll 3?ps?in?file p?0?-?VA=2000,?VASize=3835b4,?FileAddr=200,?FileSize=383600 p?1?-?VA=386000,?VASize=3520,?FileAddr=383800,?FileSize=3600 p?2?-?VA=38a000,?VASize=c,?FileAddr=386e00,?FileSize=200

然后用 ILSpy 打開 3.dll ,查看精簡后的代碼如下:

private?void?Window_Loaded(object?sender,?RoutedEventArgs?e){Connect();}private?bool?Connect(){string?ipString?=?ConfigurationManager.AppSettings["ServerSocketIp"];IPAddress?address?=?IPAddress.Parse(ipString);IPEndPoint?iPEndPoint?=?new?IPEndPoint(address,?Convert.ToInt32(ConfigurationManager.AppSettings["ServerPort"]));sockClient?=?(xxxSocket)(object)new?xxxSocket(AddressFamily.InterNetwork,?SocketType.Stream,?ProtocolType.Tcp);try{sockClient.Connect(iPEndPoint);((Socket)(object)sockClient).IOControl(IOControlCode.KeepAliveValues,?KeepAlive(1,?1000,?1000),?(byte[])null);sockClient.add_RecievedMessage((EventHandler<SocketMessage>)sockClient_RecievedMessage);}catch?(SocketException?ex){return?false;}return?true;}

很清楚的看到在主線程做了 Connect 操作,這是大忌哈。。。可能這段 Socket 代碼也是網(wǎng)上找的,應該也沒注意太多吧。。。

三:總結

知道前因后果之后,優(yōu)化辦法就比較簡單了。

  • 把 Connect 丟到 Task.Run 中,釋放主線程,簡單粗暴,

private?async?void?Window_Loaded(object?sender,?RoutedEventArgs?e){Task.Run(()=>?{?Connect()?});}
  • 使用 async, await

在這個 1+1 都要使用異步寫法的時代,不用它真的感覺落伍了。。。這里我就不費腦子怎么用 XXXAsync 家族了哈。

private?async?void?Window_Loaded(object?sender,?RoutedEventArgs?e){string?address?=?"192.168.1.79";int?port?=?9901;var?socket?=?new?Socket(AddressFamily.InterNetwork,?SocketType.Stream,?ProtocolType.Tcp);socket.SendTimeout?=?1000?*?10;socket.ReceiveTimeout?=?1000?*?10;await?socket.ConnectAsync(address,?port);//....}

這個真實案例很簡單,難度等級0, 不知道您學會了嗎?其實有時也感嘆一下,像這種案例會 Windbg 3分鐘解決,不會要摸頭一上午。

END

工作中的你,是否已遇到 ...?

1. CPU爆高

2. 內(nèi)存暴漲

3. 資源泄漏

4. 崩潰死鎖

5. 程序呆滯

等緊急事件,全公司都指望著你能解決...? 危難時刻才能展現(xiàn)你的技術價值,作為專注于.NET高級調(diào)試的技術博主,歡迎微信搜索: 一線碼農(nóng)聊技術,免費協(xié)助你分析Dump文件,希望我能將你的踩坑經(jīng)驗分享給更多的人。

總結

以上是生活随笔為你收集整理的记一次 .NET WPF布草管理系统 挂死分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。