2014-11-15 83 views
3

我想了解內核級別的死鎖/活鎖並探索不同的等待對象。使用notmyfault我創建了一個系統掛起並強制內存轉儲。顯示notmyfault的進程我看到兩個線程;一個正在嘗試獲取快速互斥體,正在等待SynchronizationEvent,另一個正在等待多個對象 - 所有SynchronizationTimers。爲什麼SynchronizationEvent指向自己?

THREAD fffffa800895f060 Cid 0f6c.0f5c Teb: 000007fffffde000 Win32Thread: fffff900c206bc20 WAIT: (WrFastMutex) KernelMode Non-Alertable 
    fffff88006ed0198 SynchronizationEvent 

THREAD fffffa800895c060 Cid 0f6c.0f20 Teb: 000007fffffdc000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Alertable 
    fffffa80069d8ef0 SynchronizationTimer 
    fffffa80093d28c0 SynchronizationTimer 
    fffffa800948e060 SynchronizationTimer 

我檢查在第一次同步事件分派首:

3: kd> dt nt!_DISPATCHER_HEADER fffff88006ed0198 
    *SNIP* 
    +0x008 WaitListHead  : _LIST_ENTRY [ 0xfffffa80`0895f168 - 0xfffffa80`0895f168 ] 

和等待表頭中的kwait塊。

3: kd> dt nt!_KWAIT_BLOCK 0xfffffa80`0895f168 
    +0x000 WaitListEntry : _LIST_ENTRY [ 0xfffff880`06ed01a0 - 0xfffff880`06ed01a0 ] 
    +0x010 Thread   : 0xfffffa80`0895f060 _KTHREAD 
    +0x018 Object   : 0xfffff880`06ed0198 Void 
    +0x020 NextWaitBlock : 0xfffffa80`0895f168 _KWAIT_BLOCK 
    *SNIP* 

綜觀其他線程的等待名單似乎是有道理的對我說:僵局似乎是由每個kwait_blocks引用對方一種循環的(我想原因引起的實際定義死鎖)。

我遇到的問題是上面的調度器頭和kwait塊。我的假設是,第一個線程將等待在使用同步定時器循環的線程上。我假設我已經錯過了一個步驟,或者僅僅是誤解,但爲什麼NextWaitBlock會引用它自己呢?

編輯

另外我注意到,沒有這些事件/定時器表示,他們已經發出信號,但fffffa800948e060包含一個插入的計時器。我的理解是,致病事件必須處於信號狀態,這是不正確的還是有另一個我忽略的等待對象?

+0

LIST_ENTRY標頭引用自身以指示列表爲空。 KWAIT_BLOCK可能類似。 –

回答

4

死鎖看起來是由每個kwait_block在某種循環中引用彼此引起的(我猜是死鎖的實際定義)。

您誤解了KWAIT_BLOCK結構中NextWaitBlock字段的用法。爲了清晰起見,讓我從頭開始(我知道你基於上面的輸出瞭解):

當一個線程進入休眠狀態,等待Dispatcher對象變成信號時,線程分配一個KWAIT_BLOCK結構並將結構排隊到Object的DISPATCHER_HEADER。這種聯繫可以通過你的結構相關的線程fffffa800895f060看到。事件的DISPATCHER_HEADER有KWAIT_BLOCK排隊,並從那裏你可以找到等待的線程。

Windows還支持線程一次等待多個Dispatcher對象的功能。發生這種情況時,線程爲每個Dispatcher對象分配一個KWAIT_BLOCK結構,將每個結構排隊到相應的DISPATCHER_HEADER,然後通過NextWaitBlock字段將KWAIT_BLOCK結構鏈接在一起。然後,線程選擇是否等待這些對象中的任何一個變爲信號,或者所有這些對象都變成信號。因此,NextWaitBlock字段只是將此線程正在等待的所有內容鏈接在一起,而不是某種無限循環。

我遇到的問題是上面的調度器頭和kwait塊。我的假設是,第一個線程將等待在使用同步定時器循環的線程上。

線程正在等待事件發出信號。這就是你在這種情況下得到的全部內容,因爲Event沒有辦法確定系統中的哪個線程應該設置它。這使得解決這些問題比使用KMUTANT Dispatcher Object的死鎖更困難。 KMUTANTs記錄哪個線程擁有它們,因此從那裏你知道接下來要看什麼。

我假設我已經錯過了一個步驟,或者只是誤解,但爲什麼NextWaitBlock引用自己呢?

這只是一個實現細節,表示一個空列表,此線程並未等待除事件外的其他任何Dispatcher對象。

+0

所以 - 要清楚 - 沒有辦法從等待線程中追蹤事件的持有者?假設,如果我發現當前持有對象的事件,我應該看到wait_block中的等待線程,對嗎? – GamerJ5

+1

正確,只要事件你不知道哪個線程應該設置它。你可以知道哪些線程正在等待事件設置,但是你不知道誰應該設置它。 – snoone