我正在调试一个我怀疑可能存在死锁或其他与多线程相关的错误的程序,我按照人们的建议使用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
我对输出感到困惑,有人可以帮忙解释一下吗?
转储关键部分查找所有者。如果所有者正在等待,找出所有者正在等待什么,依此类推,直到我们到达连锁店的尽头或事情被阻止的原因。 !cs -l -o如果我们不将其放在上下文中,可能会造成混淆。
希望这会有所帮助。
假设它是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 =“在此处输入图像描述”>
!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.
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
然后,您可以查看堆栈并了解发生了什么。就我而言,我发现我的线程在按住加载程序锁的同时正在等待事件,我们不必这样做。