Windbg,如何读取!locks输出?

问题描述 投票:3回答:4

我正在调试一个我怀疑可能存在死锁或其他与多线程相关的错误的程序,我按照人们的建议使用WinDBG打开故障转储文件,并使用!locks获得以下输出:

CritSec MSVCR100D!lclcritsects+48 at 73541e40
WaiterWoken        No
LockCount          6
RecursionCount     1
OwningThread       164c
EntryCount         0
ContentionCount    9
*** Locked

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for qsqlited4.dll - 
CritSec qsqlited4!qt_plugin_instance+a1b21 at 70fc301c
WaiterWoken        No
LockCount          0
RecursionCount     1
OwningThread       2344
EntryCount         0
ContentionCount    0
*** Locked

CritSec +73c2380 at 073c2380
WaiterWoken        No
LockCount          0
RecursionCount     4
OwningThread       2344
EntryCount         0
ContentionCount    0
*** Locked

CritSec +73bf9e8 at 073bf9e8
WaiterWoken        No
LockCount          0
RecursionCount     1
OwningThread       2344
EntryCount         0
ContentionCount    0    
*** Locked

Scanned 817 critical sections

我对输出感到困惑,有人可以帮忙解释一下吗?

c++ multithreading windbg
4个回答
9
投票
!锁可能会造成混淆。如果您确实想调试死锁情况,请执行〜* kvn(或kb),找到等待关键部分的线程,这些关键部分将以** WaitForSingleForSingleObject结尾,并在此之前进行RtlEnterCriticalSection调用。找到关键部分,大多数线程都在等待。转储关键部分。如果您正在调试基于x64的转储,并使用.frame / c post缩小到承载RtlCrticalSection的帧,则您处于线程上下文〜threads中,rbx将包含您的关键部分。

转储关键部分查找所有者。如果所有者正在等待,找出所有者正在等待什么,依此类推,直到我们到达连锁店的尽头或事情被阻止的原因。 !cs -l -o如果我们不将其放在上下文中,可能会造成混淆。

希望这会有所帮助。


3
投票
Teb是线程环境块的地址,暂停和冻结暂时不相关

假设它是32位方案,您可以通过以下方法揭示线程正在等待哪个关键部分:

a) Switch to the thread b) dump stack c) Find 1 argument to RtlEnterCriticalSection

((如果64遵循上述Addy的规定,则要使用]

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9lNmxacS5qcGcifQ==” alt =“在此处输入图像描述”>


1
投票
要查找由关键部分引起的死锁,请尝试SOSEX!dlk命令。尽管扩展名似乎仅适用于.NET,但!dlk命令还将识别本机关键部分中的死锁。

优点:如果它识别出死锁,则很容易阅读。如果没有,您仍然需要应用其他技术(例如,如果链中包括其他类型的同步对象)。

示例输出(不专门用于关键部分):

0:010> !dlk Deadlock detected: CLR thread 4 holds sync block 00000000024c6970 OBJ:000000007fff0f80[System.String] STRVAL=SYNC1 waits sync block 00000000024c6928 OBJ:000000007fff0fa8[System.String] STRVAL=SYNC2 CLR thread 5 holds sync block 00000000024c6928 OBJ:000000007fff0fa8[System.String] STRVAL=SYNC2 waits sync block 00000000024c6970 OBJ:000000007fff0f80[System.String] STRVAL=SYNC1 CLR Thread 4 is waiting at ConsoleTestApp.ConsoleTestApp.MonitorDeadlockThreadProc()+0xa4(IL) [C:\dev\ConsoleTestApp\ConsoleTestApp.cs, line 195] CLR Thread 5 is waiting at ConsoleTestApp.ConsoleTestApp.MonitorDeadlockThreadProc()+0xa4(IL) [C:\dev\ConsoleTestApp\ConsoleTestApp.cs, line 195] 1 deadlock detected.


0
投票
这是我对如何解释信息的理解,来自示例输出中显示的第一个锁:

CritSec MSVCR100D!lclcritsects+48 at 73541e40 - address of the lock WaiterWoken No - unclear, ignore LockCount 6 - how many threads are waiting to acquire the lock RecursionCount 1 - how many times the owner thread has acquired the lock OwningThread 164c - the thread ID of the owner, in hex EntryCount 0 - obsolete? ContentionCount 9 - the highest LockCount value seen *** Locked - this indicates that the critical is currently held

因此,我们可以看到线程164c拥有该锁,但不是递归的。有六个线程正在等待获取锁。在过去的某个时候,有九个线程试图获取该锁。

[您可能想要做的是切换到拥有的线程,然后查看它在做什么,为什么它仍然持有该锁,等等。您可以在windbg进程和线程号中查找该线程,或者在命令窗口中进行操作:

首先,列出所有线程:

~*

然后,找到感兴趣的线程,查找感兴趣的线程ID,然后切换到该线程。例如,您可能会找到以下输出:

9 Id: 15b8.164c Suspend: 0 Teb: fffa4000 Unfrozen Priority: 10

9是线程号15b8.164c是进程ID和线程ID。由于您要查找的是164c,这意味着感兴趣的线程是9号,因此您可以发出以下命令:

~9s

然后,您可以查看堆栈并了解发生了什么。就我而言,我发现我的线程在按住加载程序锁的同时正在等待事件,我们不必这样做。
© www.soinside.com 2019 - 2024. All rights reserved.