windbg 经典死锁调试

代码

// Deadlock_Debug.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "windows.h"
#include <process.h>

// All the thread must get all of critial_section
// Classic Deadlock


CRITICAL_SECTION gCritSecFirst;
CRITICAL_SECTION gCritSecSecond;
CRITICAL_SECTION gCritSecThird;

unsigned __stdcall Thread1Func(void* dummy)
{
printf("Enter Thread 1 \n");
EnterCriticalSection(&gCritSecThird);
{
Sleep(5000);
EnterCriticalSection(&gCritSecFirst);
EnterCriticalSection(&gCritSecSecond);
LeaveCriticalSection(&gCritSecSecond);
LeaveCriticalSection(&gCritSecFirst);
}
LeaveCriticalSection(&gCritSecThird);
printf("Exit thread func 1 \n");
return 1;
}


unsigned __stdcall Thread2Func(void* dummy)
{
printf("Enter Thread 2 \n");
EnterCriticalSection(&gCritSecFirst);
EnterCriticalSection(&gCritSecSecond);
{
Sleep(2000); 
EnterCriticalSection(&gCritSecThird);
Sleep(5000); 
LeaveCriticalSection(&gCritSecThird);
}
LeaveCriticalSection(&gCritSecSecond);
LeaveCriticalSection(&gCritSecFirst);
printf("Exit thread func 2 \n");
return 1;
}


int _tmain(int argc, _TCHAR* argv[])
{
unsigned threadID;
InitializeCriticalSection(&gCritSecFirst);
InitializeCriticalSection(&gCritSecSecond);
InitializeCriticalSection(&gCritSecThird);

_beginthreadex( NULL, 0, &Thread1Func, NULL, 0, &threadID );
_beginthreadex( NULL, 0, &Thread2Func, NULL, 0, &threadID );
while(1);
return 0;
} 

这是一个经典死锁,开启两个线程,一个以123的次序拿锁,一个以321次序拿锁,互相等待着对方的锁而均不释放自己手中的锁。(此处锁也指CriticalSection)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
开启WINDBG 附加死锁进程,查看
0:003> ~* kv
 
0 Id: 2b8.2f0 Suspend: 1 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0012ff6c 0042e346 00000001 003c30b8 003c3168 Deadlock_Debug+0x2d85c
0012ffb8 0042e21f 0012fff0 7c816d4f 0007da50 Deadlock_Debug+0x2e346
0012ffc0 7c816d4f 0007da50 7c92e1fe 7ffd9000 Deadlock_Debug+0x2e21f
0012fff0 00000000 0042b523 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])
 
1 Id: 2b8.1e0 Suspend: 1 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr Args to Child
0059fe00 7c92e9c0 7c93901b 00000030 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0059fe04 7c93901b 00000030 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0059fe8c 7c92104b 004944f0 0042d5e0 004944f0 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [1,26,4])
0059fe94 0042d5e0 004944f0 57565554 5b5a5958 ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])
WARNING: Stack unwind information not available. Following frames may be wrong.
0059ff6c 0042e123 00000000 2d7b25f9 57565554 Deadlock_Debug+0x2d5e0
0059ffa8 0042e094 00000000 0059ffec 7c80b50b Deadlock_Debug+0x2e123
0059ffb4 7c80b50b 003c2c20 57565554 5b5a5958 Deadlock_Debug+0x2e094
0059ffec 00000000 0042dff0 003c2c20 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])
 
2 Id: 2b8.1e4 Suspend: 1 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr Args to Child
0069fe00 7c92e9c0 7c93901b 00000034 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0069fe04 7c93901b 00000034 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0069fe8c 7c92104b 004944c0 0042d714 004944c0 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [1,26,4])
0069fe94 0042d714 004944c0 57565554 5b5a5958 ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])
WARNING: Stack unwind information not available. Following frames may be wrong.
0069ff6c 0042e123 00000000 2d4b25f9 57565554 Deadlock_Debug+0x2d714
0069ffa8 0042e094 00000000 0069ffec 7c80b50b Deadlock_Debug+0x2e123
0069ffb4 7c80b50b 003c2e60 57565554 5b5a5958 Deadlock_Debug+0x2e094
0069ffec 00000000 0042dff0 003c2e60 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])
 
# 3 Id: 2b8.948 Suspend: 1 Teb: 7ffdc000 Unfrozen
ChildEBP RetAddr Args to Child
0038ffc8 7c9707a8 00000005 00000004 00000001 ntdll!DbgBreakPoint (FPO: [0,0,0])
0038fff4 00000000 00000000 00000000 00000000 ntdll!DbgUiRemoteBreakin+0x2d (FPO: [Non-Fpo])
 
////////////////////////////////////////////////////
在切换到线程2 1进行观察 可以看到均是在等待CriticalSection
0:003> ~2 kv
ChildEBP RetAddr Args to Child
0069fe00 7c92e9c0 7c93901b 00000034 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0069fe04 7c93901b 00000034 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0069fe8c 7c92104b 004944c0 0042d714 004944c0 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [1,26,4])
0069fe94 0042d714 004944c0 57565554 5b5a5958 ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0]
 
0:003> ~1 kv
ChildEBP RetAddr Args to Child
0059fe00 7c92e9c0 7c93901b 00000030 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0059fe04 7c93901b 00000030 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0059fe8c 7c92104b 004944f0 0042d5e0 004944f0 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [1,26,4])
0059fe94 0042d5e0 004944f0 57565554 5b5a5958 ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])
//////////////////////////////////////////////
使用!LOCKS指令查看当前的锁
0:003> !locks
 
CritSec Deadlock_Debug+944f0 at 004944f0
LockCount 1
RecursionCount 1
OwningThread 1e4
EntryCount 1
ContentionCount 1
*** Locked
 
CritSec Deadlock_Debug+944d8 at 004944d8
LockCount 0
RecursionCount 1
OwningThread 1e4
EntryCount 0
ContentionCount 0
*** Locked
 
CritSec Deadlock_Debug+944c0 at 004944c0
LockCount 1
RecursionCount 1
OwningThread 1e0
EntryCount 1
ContentionCount 1
*** Locked

比对线程等待的锁 及个锁的拥有者和锁定情况变可以判断
线程编号1e4 也就是线程2 等待004944c0 的锁(根据堆栈的RtlEnterCriticalSection函数部分查看)
0069fe94 0042d714 004944c0 57565554 5b5a5958 ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])

而004844c0的锁由线程编号1e0 就是线程1持有
而线程编号1e0 就是线程1 等待004944f0 的锁 该所有线程编号1e4持有
0059fe94 0042d5e0 004944f0 57565554 5b5a5958 ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])

死锁!!!
找到原因就好修正了。

 

 

windbg 经典死锁调试,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。