天天看點

.NET調試執行個體-實驗1:死鎖 (原創翻譯)

1、首先,作者詳細介紹了如何重制問題,即如何培養一隻小白鼠。

2、其次,作者簡單介紹了如何擷取Dump。

3、再次,作者在此基礎上提出了若幹問題(Q),一步步啟發讀者去靠自己的實踐和思考定位和解決問題。

4、最後,作者給出了幾篇跟死鎖有關的文章索引,供讀者在實踐的時候參考。

.NET調試執行個體-實驗1:死鎖 (原創翻譯)

lock (x)

.NET調試執行個體-實驗1:死鎖 (原創翻譯)

{

.NET調試執行個體-實驗1:死鎖 (原創翻譯)

    DoSomething();

.NET調試執行個體-實驗1:死鎖 (原創翻譯)

}

.NET調試執行個體-實驗1:死鎖 (原創翻譯)
.NET調試執行個體-實驗1:死鎖 (原創翻譯)
.NET調試執行個體-實驗1:死鎖 (原創翻譯)

This is equivalent to:

.NET調試執行個體-實驗1:死鎖 (原創翻譯)
.NET調試執行個體-實驗1:死鎖 (原創翻譯)

System.Object obj = (System.Object)x;

.NET調試執行個體-實驗1:死鎖 (原創翻譯)

System.Threading.Monitor.Enter(obj);

.NET調試執行個體-實驗1:死鎖 (原創翻譯)

try

.NET調試執行個體-實驗1:死鎖 (原創翻譯)
.NET調試執行個體-實驗1:死鎖 (原創翻譯)
.NET調試執行個體-實驗1:死鎖 (原創翻譯)
.NET調試執行個體-實驗1:死鎖 (原創翻譯)

finally

.NET調試執行個體-實驗1:死鎖 (原創翻譯)
.NET調試執行個體-實驗1:死鎖 (原創翻譯)

    System.Threading.Monitor.Exit(obj);

.NET調試執行個體-實驗1:死鎖 (原創翻譯)
.NET調試執行個體-實驗1:死鎖 (原創翻譯)

 希望大家能真正親自動手實踐,然後踴躍留言啊!

這是關于.NET調試的10個實驗裡的第一個。這個實驗的對象是個名叫BuggyBits的站點,就像名字暗示的一樣,蟲子的攻擊是非常兇猛地!(buggy:多蟲的, 臭蟲成災的)

我想大家在動手實踐的時候可能會遇到很多問題,盡管我會盡可能地多回答留言欄裡的問題,但是我不能保證回答所有的問題,是以請大家遇到你們能解答的問題的時候,請盡可能地直言相告。這裡還要強調一下,請確定你已經嚴格遵守了所有的安裝說明。

注意:實驗中的問題(Q: …)隻是定位解決問題時可能會用到的幫助資訊。在我釋出對應的實驗回顧(為了給大家一段沒有答案的時間思考,實驗回顧大約在原實驗釋出一周後釋出)之前,我将适當地控制一些包含答案的評論。

請大家在評論裡暢所欲言,無論好與壞,這樣我才能知道在未來的實驗裡做那些改進。

不多說了,現在我們開始實驗1:

重制問題:

2.打開5個以上的浏覽器同時浏覽這個頁面,并且同時重新整理。

注意每一個頁面的執行時間并確定它們的開始時間幾乎都完全一樣。(如果開始時間不同,你有可能是沒有執行那個reg檔案)

Q:執行時間怎麼樣?

Q:問題重制的時候,w3wp.exe程序的CPU使用率怎麼樣?高還是低?

Q:出現死鎖症狀的潛在原因是什麼? 

擷取記憶體轉儲檔案:

1.打開一個指令行視窗,然後進入到你的調試器工具集目錄。輸入下面的指令行準備擷取轉儲檔案,但是暫時先不要執行。

adplus –hang –pn w3wp.exe –quiet

2.重制問題,使用剛才同時重新整理5個浏覽器的方法或者通過下面的指令行使用tinyget給那個網頁施壓的方法。

tinyget -srv:localhost -uri:/BuggyBits/FeaturedProducts.aspx -threads:30 -loop:50

3.在剛才的adplus視窗敲回車就可以在所有請求正在執行的時候獲得記憶體轉儲檔案。

Q:adplus處于挂起模式的時候,什麼觸發了生成記憶體轉儲檔案?

Q:你需要有什麼樣的權限才可以擷取到一個程序的記憶體轉儲檔案?

Q:轉儲檔案被建立在那裡? 提示:查閱一下Windbg的幫助檔案,關于adplus/挂起模式部分。 

使用windbg.exe打開轉儲檔案

1.啟動Windbg,使用"File/Open Crash dump"菜單打開剛才獲得的記憶體轉儲檔案。

檢查堆棧

1.檢查本地調用堆棧

~* kb 2000

2.檢查.NET調用堆棧

~* e !clrstack

Q:你是否發現了一些某個線程正在等待其它同步機制的典型迹象或者在調用堆棧上看出某些可能性?

定位并解決死鎖

1.确定持有鎖的線程的ID.

!syncblk

Q:什麼線程擁有鎖?

Q:有多少線程在等待解鎖? 

提示:MonitorHeld = 1時表示這個線程持有鎖,MonitorHeld = 2時表示這個線程被阻塞!

2.挑選一個堵塞線程(提示:堵塞線程位于AwareLock::Enter),看看它在做什麼?

    ~5s              (切換到線程5)

    kb 2000         (檢查本地堆棧)

    !clrstack        (檢查.NET堆棧)

Q:堵塞線程等待的鎖在那個.NET函數裡?

3.檢查持有鎖的線程在做什麼?

    ~5s             (切換到線程5)

    kb 2000        (檢查本地堆棧)

    !clrstack       (檢查.NET堆棧)

Q:為什麼會發生死鎖?

4.檢查代碼,看是否有方法使用了鎖,進一步證明你的假設。

提示

下面的文章在定位和解決這個死鎖問題的時候可能會用到:

<a href="http://blogs.msdn.com/tess/archive/2007/04/02/things-to-ignore-when-debugging-an-asp-net-hang-update-for-net-2-0.aspx">Things to ignore when debugging an ASP.NET Hang - Update for .NET 2.0</a>

<a href="http://blogs.msdn.com/tess/archive/2006/01/09/510773.aspx">A Hang Scenario, Locks and Critical Sections</a>

<a href="http://blogs.msdn.com/tess/archive/2006/10/16/net-hang-debugging-walkthrough.aspx">.NET Hang Debugging Walkthrough</a>

<a href="http://blogs.msdn.com/tess/archive/2007/12/12/automated-net-hang-analysis.aspx">Automated .NET Hang Analysis</a>

.NET調試執行個體-實驗1:死鎖 (原創翻譯)

-部落格園.Debug探索團隊 

-By Justin/2008年7月8日 21:07:32

本文轉自Justin部落格園部落格,原文連結:http://www.cnblogs.com/justinw/archive/2008/07/08/1238457.html,如需轉載請自行聯系原作者

繼續閱讀