我有一个简单的测试程序导致无限期等待锁定.
public class SyncBlock
{
}
class Program
{
public static SyncBlock sync = new SyncBlock();
private static void ThreadProc()
{
try
{
Monitor.Enter(sync);
}
catch (Exception)
{
//Monitor.Exit(sync);
Console.WriteLine("3rd party code threw an exception");
}
}
static void Main(string[] args)
{
Thread newThread = new Thread(ThreadProc);
newThread.Start();
Console.WriteLine("Acquiring lock");
Monitor.Enter(sync);
Console.WriteLine("Releasing lock");
Monitor.Exit(sync);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,主线程在尝试执行Monitor.Enter(sync)时基本上被锁定.如果我看着!clrStack在主线程上,其输出基本上表现出来,其意义,但是当我尝试看看栈的本机端,我期待看到通话的单/多对象类型的一些等待,但我没有看到它.任何人都可以解释它.谢谢
0:000> !CLRStack
Run Code Online (Sandbox Code Playgroud)
为的Mscorwks.dll PDB符号未加载
OS线程ID:0x1e8(0)
ESP EIP
0012f0a8 77455e74 [GCFrame:0012f0a8]
0012f178 77455e74 [HelperMethodFrame_1OBJ:0012f178] System.Threading.Monitor.Enter(System.Object的)0012f1d0 00a40177 ConsoleApplication1.Program.主(System.String [])
0012f400 70fc1b4c [GCFrame:0012f400]
0:000> kb的
ChildEBP RetAddr参数至儿童
警告:堆栈放松没有可用的信息.以下框架可能是错误的.
0012eeb4 710afb92 0012ee68 002d6280 00000000 NTDLL!KiFastSystemCallRet
0012ef1c 710af7c3 00000001 002d6280 00000000 mscorwks!StrongNameFreeBuffer + 0x1b1f2
0012ef3c 710af8cc 00000001 002d6280 00000000 mscorwks!StrongNameFreeBuffer + 0x1ae23
0012efc0 710af961 00000001 002d6280 00000000 mscorwks!StrongNameFreeBuffer + 0x1af2c
0012f010 710afae1 00000001 002d6280 00000000 mscorwks!StrongNameFreeBuffer + 0x1afc1
0012f06c 70fdc5ae FFFFFFFF 00000001 00000000 mscorwks!StrongNameFreeBuffer + 0x1b141
0012f080 710df68a FFFFFFFF 00000001 00000000 mscorwks!LogHelp_NoGuiOnAssert + 0x10562
0012f10c 710b1154 002aad90 FFFFFFFF 002aad90 mscorwks!StrongNameFreeBuffer + 0x4acea
0012f128 710b10d8 42b8b47d 00000000 002aad90 mscorwks!StrongNameFreeBuffer + 0x1c7b4
0012f1e0 70fc1b4c 0012f1f0 0012f230 0012f270 mscorwks!StrongNameFreeBuffer + 0x1c738
0012f1f0 70fd2219 0012f2c0 00000000 0012f290 mscorwks + 0x1b4c
0012f270 70fe6591 0012f2c0 00000000 0012f290 mscorwks!LogHelp_NoGuiOnAssert + 0x61cd
0012f3ac 70fe65c4 0023c038 0012f478 0012f444 mscorwks!CoUninitializeEE + 0x2ead
0012f3c8 70fe65e2 0023c038 0012f478 0012f444 mscorwks!CoUninitializeEE + 0x2ee0
0012f3e0 7103389d 0012f444 42b8b0f1 00000000 mscorwks!CoUninitializeEE + 0x2efe
0012f544 710337bd 002332e0 00000001 0012f580 mscorwks!GetPrivateContextsPerfCounters + 0xf546
0012f7ac 71033d0d 00000000 42b8b9c9 00000001 mscorwks!GetPrivateContextsPerfCounters + 0xf466
0012fc7c 71033ef7 00ce0000 00000000 42b8979 mscorwks!GetPrivateContextsPerfCounters + 0xf9b6
0012fccc 71033e27 00ce0000 42b8b8a1 00000000 mscorwks!CorExeMain + 0x168
*错误:找不到符号文件.默认导出C:\ Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll - 0012fd14 71cf55ab 71033d8f 0012fd30 71f37f16 mscorwks的符号!CorExeMain + 0x98
*错误:找不到符号文件.默认导出符号C:\ WINDOWS\SYSTEM32\mscoree.dll中-
0012fd20 71f37f16 00000000 71cf0000 0012fd44 mscoreei CorExeMain + 0x38!
0012fd30 71f34de3 00000000 7723d0e9 7ffd8000 mscoree CreateConfigStream + 0x13f!
0012fd44 774319bb 7ffd8000 084952f9 00000000 mscoree CorExeMain + 0x8中!
0012fd84 7743198e 71f34ddb 7ffd8000 00000000 ntdll!RtlInitializeExceptionChain + 0x63
0012fd9c 00000000 71f34ddb 7ffd8000 00000000 ntdll!RtlInitializeExceptionChain + 0x36
您必须将 Windbg 指向 microsoft windows 符号服务器才能获得良好的堆栈跟踪。
在 Windbg 命令窗口中输入以下内容:
.sympath srv*c:\websymbols*http://msdl.microsoft.com/download/symbols
另请参阅此:
另外,为了回答您关于如何调试此问题的原始问题,这里是食谱:
0:000> !clrstack 操作系统线程 ID:0x1358 (0) ESP电子IP 0012f328 7c90e514 [GC帧:0012f328] 0012f3f8 7c90e514 [HelperMethodFrame_1OBJ: 0012f3f8] System.Threading.Monitor.Enter(System.Object) 0012f450 00d10177 程序.Main(系统.字符串[]) 0012f688 79e71b4c [GC帧:0012f688]
在您的原始程序中,首先启动后台线程。所以,它获得了锁。然而它退出时没有释放锁。之后,您的主线程尝试获取锁,但它被卡住了,因为锁已经被拥有。
你如何找出谁拥有它?首先执行 !threads,然后执行 !syncblk。
0:000> !线程
线程数:3
未启动线程: 0
背景主题: 1
待处理线程:0
死线程:1
托管运行时:无
抢占式 GC 分配锁
ID OSID ThreadOBJ 状态 GC 上下文域计数 APT 异常
0 1 1358 0014bb00 200a020 启用 00000000:00000000 001540d0 0 MTA
2 2 1360 0015e320 b220 启用 00000000:00000000 001540d0 0 MTA(终结器)
XXXX 3 0 00175a98 9820 启用 00000000:00000000 001540d0 1 英国
0:000> !syncblk
索引 SyncBlock MonitorHeld 递归拥有线程信息 SyncBlock 所有者
2 0017903c 3 1 00175a98 0 XXX 013503cc 同步块
----------------------------
总计 2
逆时针0
RCW 0
ComClassFactory 0
免费 0
正如您所看到的, !syncblk 表示所属线程对象是00175a98。从 !threads 输出中,您可以看到线程对象 00175a98 是在拥有锁时退出的死线程。
希望这可以帮助。