windbg - 为什么 SynchronizationEvent 会指向自身?

标签 windbg

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

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

我检查第一个同步事件的调度 header :

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

以及等待列表标题上的 kwait block 。

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 在某种循环中相互引用引起的(我猜这是死锁的实际定义)。

我遇到的问题是上面的调度程序 header 和 kwait block 。我的假设是第一个线程将等待使用同步计时器自行循环的线程。我假设我错过了一个步骤或者只是误解了,但为什么 NextWaitBlock 引用了它自己呢?

编辑:

此外,我注意到这些事件/计时器均未表明它们已收到信号,但 fffffa800948e060 包含插入的计时器。我的理解是,致病事件必须处于有信号状态,这是不正确的还是有另一个我忽略的等待对象?

最佳答案

The deadlock appears to be caused by each of the kwait_blocks referencing each other in a sort of loop (which I guess is the actual definition of a deadlock).

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

当线程进入休眠状态等待 Dispatcher 对象收到信号时,该线程会分配一个 KWAIT_BLOCK 结构并将该结构排队到该对象的 DISPATCHER_HEADER 中。通过您对与线程 fffffa800895f060 相关的结构化的了解,可以看到这种联系。该事件的 DISPATCHER_HEADER 已将 KWAIT_BLOCK 排队到其中,从那里您可以找到等待的线程。

Windows 还支持线程同时等待多个调度程序对象的能力。发生这种情况时,线程为每个 Dispatcher 对象分配一个 KWAIT_BLOCK 结构,将每个结构排队到适当的 DISPATCHER_HEADER,然后通过 NextWaitBlock 字段将 KWAIT_BLOCK 结构链接在一起。然后,线程选择是否要等待这些对象中的任何一个变为有信号状态,还是等待所有这些对象变为有信号状态。因此,NextWaitBlock 字段只是将该线程正在等待的所有事物链接在一起,而不是某种无限循环。

The problem I'm having is with the dispatcher header and kwait block above. My assumption would have been that the first thread would be waiting on the thread that is looping on itself with the synchronization timers.

线程正在等待事件发出信号。这就是在这种情况下您得到的所有内容,鉴于事件,无法确定系统中的哪个线程应该设置它。这使得解决这些问题比解决 KMUTANT 调度程序对象的死锁更加困难。 KMUTANT 记录哪个线程拥有它们,因此从那里您知道下一步该看哪里。

I'm assuming that I have missed a step or am simply misunderstanding but why does the NextWaitBlock reference itself instead?

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

关于windbg - 为什么 SynchronizationEvent 会指向自身?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26948712/

相关文章:

visual-studio - 如何从 windbg/dbgeng api 获取部分信息/偏移权限?

.net - 未加载 ngen-ed 程序集的符号

c++ - 内存堆损坏和 GFlags/windbg

c# - 应如何配置 windbg 以对 Microsoft 报告进行故障排除(在 Visual Studio 2008 中创建)

visual-studio - 从 VS 调试器切换到 WinDbg

qt-creator - 配置 Qt Creator 以使用 CDB

windows - 创建 QEmu guest 操作系统的 WinDbg 可读转储

windows - 何时以及如何使用 windbg 内核调试

heap-memory - !heap -x -v 和 !heap -flt s 之间的矛盾

windbg - 每次命中时如何在windbg中从执行中跳过一行?