当前位置: 首页 > >

Windbg 分析程序死锁小结

发布时间:

当应用程序挂死后,使用windbg Attach到进程。


1. 使用 ~*kb,查看堆栈信息

8 Id: 368.bd4 Suspend: 1 Teb: 7ffd6000 Unfrozen ChildEBP RetAddr Args to Child 0614fd4c 7c92df5a 7c939b23 00000604 00000000 ntdll!KiFastSystemCallRet
0614fd50 7c939b23 00000604 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
0614fdd8 7c921046 0012fe08 5f401b5f 0012fe08 ntdll!RtlpWaitForCriticalSection+0x132 0614fde0 5f401b5f 0012fe08 0012fdfc 0614fedc ntdll!RtlEnterCriticalSection+0x46
0614fdf0 0040b207 ffffffff 77d2b326 03103ee0 MFC42D!CCriticalSection::Lock+0x14
0614fedc 5f438514 0012fd30 ffffffff 77d2b326 RecExtraction!CRecExtractionModule::ThreadAnalysis+0x185 [G:Codevc2012VSIPDigitalViewer_V1RecExtractionRecExtractionModule.cpp @ 331] 0614ff80 1020c323 0012f4f4 ffffffff 77d2b326 MFC42D!_AfxThreadEntry+0x2c4
0614ffb4 7c80b729 03103ee0 ffffffff 77d2b326 MSVCRTD!_beginthreadex+0x133
0614ffec 00000000 1020c2b0 03103ee0 00000000 kernel32!BaseThreadStart+0x37

?其中,上图中的8是线程编号,368是进程ID,bd4是线程ID。
可以看到ntdll!NtWaitForSingleObject ,没有拿到锁,说明死锁发生了。


0614fd4c 7c92df5a 7c939b23 00000604 00000000 ntdll!KiFastSystemCallRet
0614fd50 7c939b23 00000604 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
0614fdd8 7c921046 0012fe08 5f401b5f 0012fe08 ntdll!RtlpWaitForCriticalSection+0x132
这里的第一个是ebp,第二个是返回函数地址,接下来才是函数的参数。

? 要看下比如?ntdll!NtWaitForSingleObject参数定义:


NTSTATUS WINAPI NtWaitForSingleObject(
_In_ HANDLE Handle,
_In_ BOOLEAN Alertable,
_In_ PLARGE_INTEGER Timeout
);

??所以?00000604?00000000?00000000分别对应上面的Handle,Alrtable,Timeout.


2. 如果线程比较多,可以使用 !cs -l 仅显示死锁的临界区信息。
3.找到了死锁的临界区Handle,就可以查找锁的持有者了。

!cs 00000604

????如上所述,handle是00000604,


?


示例:


0:004> ~1kb
ChildEBP RetAddr Args to Child
0051fe48 7c92df5a 7c939b23 00000034 00000000 ntdll!KiFastSystemCallRet
0051fe4c 7c939b23 00000034 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
0051fed4 7c921046 00417140 00411420 00417140 ntdll!RtlpWaitForCriticalSection+0x132
*** WARNING: Unable to verify checksum for D:Project1 est2Debug est2.exe
0051fedc 00411420 00417140 00000000 00000000 ntdll!RtlEnterCriticalSection+0x46
0051ffb4 7c80b729 00000000 00000000 00000000 test2!thread1+0x50 [d:project1 est2 est2 est2.cpp @ 10]
0051ffec 00000000 00411122 00000000 00000000 kernel32!BaseThreadStart+0x37
0:004> !cs 00417140
-----------------------------------------
Critical section = 0x00417140 (test2!cs2+0x0)
DebugInfo = 0x7c99ea00
LOCKED
LockCount = 0x2
OwningThread = 0x00001f60
RecursionCount = 0x1
LockSemaphore = 0x34
SpinCount = 0x00000000

可以看出该临界区的持有者(OwningThread)是 0x00001f60


这个地址是线程在内核中的ID,需要转换为用户态的ID,使用~~[]命令。


~~[线程内核id]


通过转换,可以看到锁的持有者是2号线程。



友情链接: