繼續上次debug的階段
當我們把.NET在作什麼事情丟出來以後
如果要更深入的看裡面的變數也是可以的比方說我要在當下的 thread 裡看詳細是作了哪些事 (Dump Stack Objects)
0:054>!dso
OS Thread Id: 0xaf0 (54)
ESP/REG Object Name
15b3e4a8 05ba96a0 Microsoft.Win32.SafeHandles.SafeWaitHandle
15b3e4d0 05b0f710 System.AsyncCallback
15b3e564 01f9befc System.Object[] (System.Object[])
15b3e570 01f9bf88 System.String D:xxxCacheAdPV671671_2010101416.txt
15b3e574 01f9beb8 System.String D:xxxCacheAdPV671
15b3e578 05b78060 System.String 1
15b3e60c 05b0f710 System.AsyncCallback
15b3e620 01f9bf50 System.String 671_2010101416.txt
15b3e634 01b0af64 System.String D:xxxCacheAdPV
15b3e650 05bab274 System.String Start
15b3e664 05af01d0 System.String
15b3e688 01b0af64 System.String D:xxxCacheAdPV
15b3e68c 01b0b320 System.Configuration.KeyValueInternalCollection
15b3e698 05b10220 System.Text.UTF8Encoding
15b3e6bc 01b09724 System.String 3
15b3e6c0 01b0b320 System.Configuration.KeyValueInternalCollection
15b3e6d0 05b10220 System.Text.UTF8Encoding
15b3e6dc 01f9a708 System.Object[] (xxx.Data.Advertisement[])
………………………………..
中間 Object 下 8位 16 進制的就是記憶體位址
表示在這個位址裡面放了右邊所執行的命令
針對有些像是陣列或是object, 我們可以繼續下指令去dump看裡面到底包了什麼
共有以下三種指令 da dd do
說實在我並不清楚這三種的差別是什麼, 但最顯而易見的就是下對指令才dump的出來
0:054> !do 01f9a708
Name: System.Object[]
MethodTable: 793042f4
EEClass: 790eda64
Size: 28(0x1c) bytes
Array: Rank 1, Number of elements 3, Type CLASS
Element Type: xxx.Data.Advertisement
Fields:
None
0:054> !da 01f9a708
Name: xxx.Data.Advertisement[]
MethodTable: 793042f4
EEClass: 790eda64
Size: 28(0x1c) bytes
Array: Rank 1, Number of elements 3, Type CLASS
Element Methodtable: 0f867160
[0] 01f998f8
[1] 01f9a6ac
[2] 01f9a650
上面可以看到do拿他沒皮條時我換用da來下, 接著又出現三個address
繼續下指令去扒
0:054> !do 01f998f8
Name: Pushba.Data.Advertisement
MethodTable: 0f867160
EEClass: 0f945078
Size: 92(0x5c) bytes
(C:WINDOWSMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET Filesroot141ebe66ccec38aeassemblydl3102e98b9ac990b34_d244cb01xxx.Data.DLL)
Fields:
MT Field Offset Type VT Attr Value Name
79332d70 4000044 14 System.Int32 1 instance 671 id
79332d70 4000045 18 System.Int32 1 instance 3 venderID
79330b24 4000046 4 System.String 0 instance 01f9983c authKey
79330b24 4000047 8 System.String 0 instance 05af01d0 imageUrl
79330b24 4000048 c System.String 0 instance 01f9985c navigateUrl
79330b24 4000049 10 System.String 0 instance 01f998c4 alternateText
79332d70 400004a 1c System.Int32 1 instance 0 impressions
79332d70 400004b 20 System.Int32 1 instance 21907 viewed
79332d70 400004c 24 System.Int32 1 instance 5 clicked
7932a368 400004d 28 System.Single 1 instance 0.010000 valuePerView
7932a368 400004e 2c System.Single 1 instance 0.000000 valuePerClick
79332d70 400004f 30 System.Int32 1 instance 30000 viewQuota
79332d70 4000050 34 System.Int32 1 instance 1000000 clickQuota
793045f0 4000051 3c System.Boolean 1 instance 1 enabled
00000000 4000052 40 1 instance 01f99938 startDate
00000000 4000053 4c 1 instance 01f99944 endDate
79332d70 4000054 38 System.Int32 1 instance 0 orderID
因為直接貼文字的關係對齊有點亂掉
不過還是可以看出來在這段記憶體裡面擺了什麼東西
欄位從4000044開始, offset為記憶體的偏移植
比較重要的是你可以根據Name跟 Value來檢查到底發生問題時有沒有什麼值出錯了
其實在debug的階段經驗是很重要的
因為我們不可能把這麼多的thread一一分析
有經驗的工程師可以依照其經驗來判斷哪裡可能有問題並快速的驗證
由於我很菜, 這個bug還真花了我不少時間
因此分享一下解決的過程, 希望遇到類似困難的人看到這篇可以減少摸索的時間
首先既然我們不可能去分析所有的thread, 那麼就先來猜出可能搞鬼的是誰
由於每次發生deadlock時總是在線程數60以上
因此我們可以合理的懷疑某個thread死占著資源不放
而這支程式又常常被呼叫到, 導致後面大排長龍
先做一個表格來統計到底發生deadlock時, 到底這60多條thread在幹嘛…
在整理好之後我發現我應該抓出兇手了
程式再讀寫快取的thread竟然占了40條
顯然是因為快取檔案資源占用造成後面陸續要讀寫快取的線程塞爆了
這邊可以對照剛剛dump出來的資訊
0:054> !dso
OS Thread Id: 0xaf0 (54)
ESP/REG Object Name
15b3e4a8 05ba96a0 Microsoft.Win32.SafeHandles.SafeWaitHandle
15b3e4d0 05b0f710 System.AsyncCallback
15b3e564 01f9befc System.Object[] (System.Object[])
15b3e570 01f9bf88 System.String D:xxxCacheAdPV671671_2010101416.txt
15b3e574 01f9beb8 System.String D:xxxCacheAdPV671
15b3e578 05b78060 System.String 1
15b3e60c 05b0f710 System.AsyncCallback
有好幾個thread都在吃這支D:xxxCacheAdPV671671_2010101416.txt
然後就在那邊癡癡的等 (System.AsyncCallback)
難怪造成服務的deadlock
幸好在花了這麼多時間後把問題給解了
沒想到網站上遇到的問題也可以memory dump
在debug上來講真的是很有威力
不過整個過程真是有點辛苦, 拜託網站不要再出包了…
大部分的指令參考自 http://www.cnblogs.com/juqiang/category/261813.html
裡面還有很多更進階的指令介紹喔