|
注意LockCount字段的值-11:
0:000> dt _RTL_CRITICAL_SECTION 0x7c8897a0 mfc80u!_RTL_CRITICAL_SECTION +0x000 DebugInfo : 0x7c8897c0 _RTL_CRITICAL_SECTION_DEBUG +0x004 LockCount : -11
将其格式化为二进制:
0:003> .formats -0n11 Evaluate expression: Hex: fffffff5 Decimal: -11 Octal: 37777777765 Binary: 11111111 11111111 11111111 11110101 按照LockCount在Svr2K3 SP1起的定义:
- 最低位为1的含义是这个关键区对象此时(观察时——也就是DUMP时)没有锁定。
- 次低位的0含义是已经唤醒了等待这个关键区的一个线程。
- 余下的30位的补码(2)代表有多少个线程在等待这个关键区对象。
综合以上信息,可以作出这样一种猜测:
3号线程(1788.af8 )曾经和另外一个线程一起等待LdrLockLoaderLock这个关键区,当用于LdrLockLoaderLock的线程离开这个关键区时,系统唤醒了另外一个线程,但这个线程在关键区内意外退出了,系统在清理线程时,擦除了LdrLockLoaderLock中OwningThread中的登记......
那么这另外一个线程是谁呢?这从DUMP文件就较难获悉了,可以考虑以下方法:
1)启用MSI的诊断日志:http://msdn.microsoft.com/en-us/library/aa372847(VS.85).aspx
2)如果是在调试目标,那么把g_dmDiagnosticMode改为1,启用调试信息输出
3)使用如下命令之一,启用验证器的死锁检测功能(参见《软件调试》第19章):
appverif.exe -enable locks -for TestApplicaiton.exe gflags.exe -v IMAGE /enable TestApplicaiton.exe LOCK_CHECKS
因为等待最终是发生在内核态的,等待对象的很多属性也只有内核模式才看得到,所以最好同时配以内核调试,在抓取转储时,同时抓取内核转储。
|