Crash Dump Analysis Patterns (Part 9b)
Crash Dump Analysis Patterns (Part 9b)
원문링크: https://www.dumpanalysis.org/blog/index.php/2007/07/03/crash-dump-analysis-patterns-part-9b/
번역: 김희준 ( Heejune Kim, drost@naver.com, https://insidekernel.net, 2007-09-01 )
지난번 데드락 패턴에 이어지는 내용입니다. 이번 파트에서는 윈도우 커널에서의 ERESOURCE 데드락에 대해서 보여드리겠습니다.
ERESOURCE (executive resource)는 소유권 개념(ownership semantics)을 가지고 있는 윈도우 동기화 객체입니다.
Executive resource는 배타(exclusive)적으로 소유권을 갖도록 하거나, 소유권을 공유하도록 할 수도 있습니다. 즉 파일 공유와 유사합니다: 파일이 쓰기 권한으로 오픈되었다면 다른 객체들은 읽거나 쓸 수 없습니다; 만약 읽기 권한으로 파일을 오픈했다면 다른 객체들은 그것을 읽을 수는 있지만 쓰기는 할 수 없습니다.
ERESOURCE 구조체는 리스트로 링크되어져 있으며 스레드를 소유자로 가집니다. 이 스레드를 통해 우리가 커널 덤프나 전체 메모리 덤프에서 !locks 명령어를 사용했을 때 데드락을 빨리 찾아낼 수 있게 해 줍니다. 다음은 x86와 x64 윈도우에서의 _ERESOURCE의 정의입니다:
0: kd> dt -r1 _ERESOURCE
+0x000 SystemResourcesList : _LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY
+0x008 OwnerTable : Ptr32 _OWNER_ENTRY
+0x000 OwnerThread : Uint4B
+0x004 OwnerCount : Int4B
+0x004 TableSize : Uint4B
+0x00c ActiveCount : Int2B
+0x00e Flag : Uint2B
+0x010 SharedWaiters : Ptr32 _KSEMAPHORE
+0x000 Header : _DISPATCHER_HEADER
+0x010 Limit : Int4B
+0x014 ExclusiveWaiters : Ptr32 _KEVENT
+0x000 Header : _DISPATCHER_HEADER
+0x018 OwnerThreads : [2] _OWNER_ENTRY
+0x000 OwnerThread : Uint4B
+0x004 OwnerCount : Int4B
+0x004 TableSize : Uint4B
+0x028 ContentionCount : Uint4B
+0x02c NumberOfSharedWaiters : Uint2B
+0x02e NumberOfExclusiveWaiters : Uint2B
+0x030 Address : Ptr32 Void
+0x030 CreatorBackTraceIndex : Uint4B
+0x034 SpinLock : Uint4B
0: kd> dt -r1 _ERESOURCE
nt!_ERESOURCE
+0x000 SystemResourcesList : _LIST_ENTRY
+0x000 Flink : Ptr64 _LIST_ENTRY
+0x008 Blink : Ptr64 _LIST_ENTRY
+0x010 OwnerTable : Ptr64 _OWNER_ENTRY
+0x000 OwnerThread : Uint8B
+0x008 OwnerCount : Int4B
+0x008 TableSize : Uint4B
+0x018 ActiveCount : Int2B
+0x01a Flag : Uint2B
+0x020 SharedWaiters : Ptr64 _KSEMAPHORE
+0x000 Header : _DISPATCHER_HEADER
+0x018 Limit : Int4B
+0x028 ExclusiveWaiters : Ptr64 _KEVENT
+0x000 Header : _DISPATCHER_HEADER
+0x030 OwnerThreads : [2] _OWNER_ENTRY
+0x000 OwnerThread : Uint8B
+0x008 OwnerCount : Int4B
+0x008 TableSize : Uint4B
+0x050 ContentionCount : Uint4B
+0x054 NumberOfSharedWaiters : Uint2B
+0x056 NumberOfExclusiveWaiters : Uint2B
+0x058 Address : Ptr64 Void
+0x058 CreatorBackTraceIndex : Uint8B
+0x060 SpinLock : Uint8B
만약 !locks 명령을 통해서 리소스들의 리스트를 확인할 수 있다면 그 리소스들을 소유하고 있는 스레드를 살펴볼 수 있습니다. 소유자 스레드는 스타 캐릭터(*)로 표시되어 있습니다:
0: kd> !locks
**** DUMP OF ALL RESOURCE OBJECTS ****
KD: Scanning for held locks......
Resource @ 0x8815b928 Exclusively owned
Contention Count = 6234751
NumberOfExclusiveWaiters = 53
Threads: 89ab8db0-01<*>
Threads Waiting On Exclusive Access:
8810fa08 880f5b40 88831020 87e33020
880353f0 88115020 88131678 880f5db0
89295420 88255378 880f8b40 8940d020
880f58d0 893ee500 880edac8 880f8db0
89172938 879b3020 88091510 88038020
880407b8 88051020 89511db0 8921f020
880e9db0 87c33020 88064cc0 88044730
8803f020 87a2a020 89529380 8802d330
89a53020 89231b28 880285b8 88106b90
8803cbc8 88aa3020 88093400 8809aab0
880ea540 87d46948 88036020 8806e198
8802d020 88038b40 8826b020 88231020
890a2020 8807f5d0
여기에서 우리는 _KTHREAD 89ab8db0가 _ERESOURCE 8815b928 릴리즈 하기를 53개의 스레드가 기다리고 있는 것을 확인할 수 있습니다. 이 스레드 주소를 검색해보면 아래 내용을 알 수 있습니다:
Resource @ 0x88159560 Exclusively owned
Contention Count = 166896
NumberOfExclusiveWaiters = 1
Threads: 8802a790-01<*>
Threads Waiting On Exclusive Access:
89ab8db0
우리는 스레드 89ab8db0가 스레드 8802a790이 리소스 88159560을 릴리즈 하기를 기다리고 있는 것을 확인할 수 있습니다. 우리는 스레드 8802a790이 다른 스레드를 기다리는 경우를 계속해서 찾아보았습니다:
Resource @ 0x881f7b60 Exclusively owned
Threads: 8802a790-01<*>
Resource @ 0x8824b418 Exclusively owned
Contention Count = 34
Threads: 8802a790-01<*>
Resource @ 0x8825e5a0 Exclusively owned
Threads: 8802a790-01<*>
Resource @ 0x88172428 Exclusively owned
Contention Count = 5
NumberOfExclusiveWaiters = 1
Threads: 8802a790-01<*>
Threads Waiting On Exclusive Access:
880f5020
계속 찾아보았을 때 스레드 8802a790이 스레드 880f5020이 리소스 89bd7bf0를 릴리즈 하기를 기다리고 있음을 알 수 있습니다:
Resource @ 0x89bd7bf0 Exclusively owned
Contention Count = 1
NumberOfExclusiveWaiters = 1
Threads: 880f5020-01<*>
Threads Waiting On Exclusive Access:
8802a790
자세히 살펴보면 우리는 위에서 이미 스레드 880f5020을 본 적이 있습니다. 그 부분을 다시 살펴봅시다(컬러로 표시):
Resource @ 0x88172428 Exclusively owned
Contention Count = 5
NumberOfExclusiveWaiters = 1
Threads: 8802a790-01<*>
Threads Waiting On Exclusive Access:
880f5020
우리는 스레드 880f5020이 스레드 8802a790을 기다리고 있고 스레드 8802a790은 스레드 880f5020을 기다리고 있는 것을 볼 수 있습니다.
이것으로 전통적인 형태의 데드락을 확인해보았습니다. 이제 우리가 해야 할 일은 이들 스레드들의 스택 트레이스를 통해서 어떤 컴포넌트들이 연관되어 있는지 알아내는 것입니다.
- Dmitry Vostokov @ DumpAnalysis.org -
Comments
- Anonymous
September 17, 2008
PingBack from http://www.easycoded.com/crash-dump-analysis-patterns-part-9b/