使用Windbg的!clrstack命令调试死锁问题

11

当我执行clrstack命令时,我得到了以下输出。它是一个拥有死锁并导致死锁的阻塞线程的调用堆栈。这是它的确切目的吗?它是否还有其他作用(没有任何参数)。我在哪里可以获得更多信息?

!clrstack
OS Thread Id: 0x1b2c (6956)
ESP       EIP     
0012f370 7c90e514 [HelperMethodFrame: 0012f370] System.Threading.Thread.SleepInternal(Int32)
0012f3c4 79299275 System.Threading.Thread.Sleep(Int32)
0012f3c8 00e0030f testlock.LockTest.Test()
0012f420 00e00146 testlock.Program.Main(System.String[])
0012f69c 79e71b4c [GCFrame: 0012f69c] 

如下所述,此命令仅用于显示当前线程上下文的托管调用堆栈。因此,如果您正在调试死锁问题,应尝试将其与其他命令结合使用。 - Lex Li
这对我来说看起来不像死锁。堆栈显示了对Sleep的调用。对于死锁,您应该在堆栈上看到Wait调用。 - Brian Rasmussen
3个回答

23

使用Steve Johnson的sosex工具。该工具包含一个命令,可以帮助您检测死锁。

从链接中下载并加载该扩展,例如:

.load D:\sosex_32\sosex.dll

然后出现问题

!dlk

示例输出(来自Steve的网站)

0:010> !dlk 检测到死锁:CLR线程4持有同步块00000000024c6970 OBJ:000000007fff0f80[System.String] STRVAL=SYNC1 等待同步块00000000024c6928 OBJ:000000007fff0fa8[System.String] STRVAL=SYNC2 CLR线程5持有 同步块00000000024c6928 OBJ:000000007fff0fa8[System.String] STRVAL=SYNC2 等待同步块00000000024c6970 OBJ:000000007fff0f80[System.String] STRVAL=SYNC1 CLR线程4正在等待 ConsoleTestApp.ConsoleTestApp.MonitorDeadlockThreadProc()+0xa4(IL) [C:\dev\ConsoleTestApp\ConsoleTestApp.cs,第195行] CLR线程5正在等待 ConsoleTestApp.ConsoleTestApp.MonitorDeadlockThreadProc()+0xa4(IL) [C:\dev\ConsoleTestApp\ConsoleTestApp.cs,第195行]

另请参见链接以获取全面解析。


18

如何使用WinDbg调试死锁?

WinDbg / SOS速查表

CLRStack [-a] [-l] [-p] [-n] 提供仅有托管代码的堆栈跟踪。

  • -p选项显示托管函数的参数。

  • -l选项显示帧中的本地变量信息。SOS调试扩展无法检索本地名称,因此本地名称的输出格式为 = 。

  • -a(全部)选项是-l和-p组合的快捷方式。

  • -n选项禁用显示源文件名和行号。如果调试器指定了SYMOPT_LOAD_LINES选项,则SOS将查找每个托管框架的符号,并在成功后显示相应的源文件名和行号。可以使用-n(无行号)参数来禁用此行为。

SOS调试扩展在x64和IA-64平台上不显示过渡帧。

更新:(感谢@Liran)要查看应用程序中所有线程的调用堆栈,请运行以下命令:

 ~*e!clrstack 

(这基本上意味着,"遍历所有的线程,并在每个线程上执行命令'!clrstack'"。)


1
谢谢回复。我的应用程序有2个线程。但是!clrstack命令只显示了一个线程的调用堆栈。在发布问题之前,我已经阅读了文档。 - Maanu
1
@Maanu,这个命令是针对每个线程发出的。如果要针对应用程序中的所有线程发出此命令,您需要使用以下命令:~*e!clrstack(基本上意味着“遍历所有线程,并在每个线程上执行'!clrstack'命令”)。 - Liran

1

Tess发布了许多关于windbg的有用信息。这里有一篇文章可能会有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接