Windbg 为什么SynchronizationEvent会指向自身?

Windbg 为什么SynchronizationEvent会指向自身?,windbg,Windbg,我试图在内核级别理解死锁/活锁,并探索不同的等待对象。使用我创建了一个系统挂起并强制内存转储。显示notmyfault的进程时,我看到两个线程;一个正在尝试获取快速互斥并等待SynchronizationEvent,另一个正在等待多个对象—所有SynchronizationTimer THREAD fffffa800895f060 Cid 0f6c.0f5c Teb: 000007fffffde000 Win32Thread: fffff900c206bc20 WAIT: (WrFastMu

我试图在内核级别理解死锁/活锁,并探索不同的等待对象。使用我创建了一个系统挂起并强制内存转储。显示notmyfault的进程时,我看到两个线程;一个正在尝试获取快速互斥并等待SynchronizationEvent,另一个正在等待多个对象—所有SynchronizationTimer

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

我在第一个同步事件上检查调度标头:

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_块引起的(我猜这就是死锁的实际定义)

我遇到的问题是上面的dispatcher头和kwait块。我的假设是,第一个线程将等待使用同步计时器在自身上循环的线程。我假设我错过了一个步骤或者只是误解了,但是为什么NextWaitBlock会引用自己呢

编辑

此外,我还注意到,这些事件/计时器中没有一个表示它们已发出信号,但FFFFF A800948E060包含插入的计时器。我的理解是,因果事件必须处于信号状态,这是错误的还是我忽略了另一个等待对象

死锁似乎是由每个kwait_块在某种循环中相互引用引起的(我猜这就是死锁的实际定义)

您误解了KWAIT_块结构中NextWaitBlock字段的用法。为了清楚起见,让我从头开始(我知道您根据上述输出理解):

当线程进入睡眠状态等待调度程序对象发出信号时,该线程分配一个KWAIT_块结构,并将该结构排队到对象的调度程序_头。这个链接可以通过与线程FFFFF A800895F060相关的结构化线程的遍历看到。事件的DISPATCHER_头将KWAIT_块排入队列,从那里可以找到等待的线程

Windows还支持线程同时等待多个Dispatcher对象的能力。发生这种情况时,线程为每个Dispatcher对象分配一个KWAIT_块结构,将每个结构排队到适当的Dispatcher_头,然后通过NextWaitBlock字段将KWAIT_块结构链接在一起。然后线程选择是等待这些对象中的任何一个发出信号,还是等待所有这些对象发出信号。因此,NextWaitBlock字段只是将该线程正在等待的所有内容链接在一起,而不是某种无限循环

我遇到的问题是上面的dispatcher头和kwait块。我的假设是,第一个线程将等待使用同步计时器在自身上循环的线程

线程正在等待事件发出信号。这就是本例中的全部内容,给定事件,无法确定系统中的哪个线程应该设置它。这使得解决这些问题比使用KMUTANT Dispatcher对象解决死锁更加困难。KMUTANTs记录哪个线程拥有它们,所以从那里你知道下一步要去哪里

我假设我错过了一个步骤或者只是误解了,但是为什么NextWaitBlock会引用自己呢


这只是一个指示空列表的实现细节,此线程不等待除事件之外的任何其他Dispatcher对象。

列表项头引用自身以指示列表为空。KWAIT_BLOCK可能与此类似。因此,要明确的是,没有办法从等待线程跟踪事件的持有者?但是假设,如果我找到当前保存对象的事件,我应该在wait_块中看到等待线程,对吗?对,只是给定了事件,你不知道应该设置哪个线程。您可以知道哪些线程正在等待事件被设置,但是您不知道应该由谁来设置它。
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*