!교착 상태

!deadlock 확장은 드라이버 검증 도구의 교착 상태 검색 옵션에 의해 수집된 교착 상태에 대한 정보를 표시합니다.

!deadlock 
!deadlock 1

DLL

Kdexts.dll

추가 정보

드라이버 검증 도구에 대한 자세한 내용은 WDK(Windows 드라이버 키트) 설명서를 참조하세요.

설명

이 확장은 드라이버 검증 도구의 교착 상태 검색 옵션이 잠금 계층 위반을 감지하고 버그 검사 0xC4(DRIVER_VERIFIER_DETECTED_VIOLATION)를 발급한 경우에만 유용한 정보를 제공합니다.

인수가 없으면 !deadlock 확장으로 인해 기본 잠금 계층 구조 토폴로지가 표시됩니다. 문제가 단순한 순환 교착 상태가 아닌 경우 이 명령은 발생한 상황을 설명합니다.

!deadlock 1 확장으로 인해 스택 추적이 표시됩니다. 표시되는 스택은 잠금을 획득할 때 활성 상태인 스택입니다.

예를 들어 다음과 같습니다.

0:kd> !deadlock

Deadlock detected (2 resources in 2 threads):

Thread 0: A B
Thread 1: B A

Where:
Thread 0 = 8d3ba030
Thread 1 = 8d15c030
Lock A =   bba2af30 Type 'Spinlock'
Lock B =   dummy!GlobalLock Type 'Spinlock'

그러면 어떤 스레드와 어떤 잠금이 관련되어 있는지 알 수 있습니다. 그러나 요약을 위한 것이며 상황을 적절하게 디버그하기에 충분한 정보가 아닐 수 있습니다.

!deadlock 1을 사용하여 교착 상태에 참여하는 각 잠금을 획득할 때 호출 스택의 내용을 출력합니다. 이러한 추적은 런타임 스택 추적이므로 검사 빌드를 사용하는 경우 더 완료됩니다. 확인된 빌드는 Windows 10 버전 1803 이전 버전의 Windows에서 사용할 수 있었습니다. 무료 빌드에서는 한 줄만 지나면 잘려질 수 있습니다.

0:kd> !deadlock 1

Deadlock detected (2 resources in 2 threads):

Thread 0 (8D14F750) took locks in the following order:

    Lock A -- b7906f30 (Spinlock)
    Stack:   dummy!DummyActivateVcComplete+0x63
             dummy!dummyOpenVcChannels+0x2E1
             dummy!DummyAllocateRecvBufferComplete+0x436
             dummy!DummyAllocateComplete+0x55
             NDIS!ndisMQueuedAllocateSharedHandler+0xC9
             NDIS!ndisWorkerThread+0xEE

    Lock B -- dummy!GlobalLock (Spinlock)
    Stack:   dummy!dummyQueueRecvBuffers+0x2D
             dummy!DummyActivateVcComplete+0x90
             dummy!dummyOpenVcChannels+0x2E1
             dummy!DummyAllocateRecvBufferComplete+0x436
             dummy!DummyAllocateComplete+0x55

Thread 1 (8D903030) took locks in the following order:

    Lock B -- dummy!GlobalLock (Spinlock)
    Stack:   dummy!dummyRxInterruptOnCompletion+0x25D
             dummy!DummyHandleInterrupt+0x32F
             NDIS!ndisMDpcX+0x3C
             ntkrnlpa!KiRetireDpcList+0x5D

    Lock A -- b7906f30 (Spinlock)
    Stack:   << Current stack >>

이 정보를 사용하면 현재 스택을 제외하고 필요한 거의 모든 항목이 있습니다.

0: kd> k
ChildEBP RetAddr
f78aae6c 80664c58 ntkrnlpa!DbgBreakPoint
f78aae74 8066523f ntkrnlpa!ViDeadlockReportIssue+0x2f
f78aae9c 806665df ntkrnlpa!ViDeadlockAnalyze+0x253
f78aaee8 8065d944 ntkrnlpa!VfDeadlockAcquireResource+0x20b
f78aaf08 bfd6df46 ntkrnlpa!VerifierKeAcquireSpinLockAtDpcLevel+0x44
f78aafa4 b1bf2d2d dummy!dummyRxInterruptOnCompletion+0x2b5
f78aafc4 bfde9d8c dummy!DummyHandleInterrupt+0x32f
f78aafd8 804b393b NDIS!ndisMDpcX+0x3c
f78aaff4 804b922b ntkrnlpa!KiRetireDpcList+0x5d

이를 통해 어떤 잠금이 관련되었는지, 어디에서 잠금을 획득했는지 확인할 수 있습니다. 교착 상태를 디버깅하기에 충분한 정보여야 합니다. 소스 코드를 사용할 수 있는 경우 디버거를 사용하여 문제가 발생한 위치를 정확하게 확인할 수 있습니다.

0: kd> .lines
Line number information will be loaded

0: kd> u dummy!DummyActivateVcComplete+0x63 l1
dummy!DummyActivateVcComplete+63 [d:\nt\drivers\dummy\vc.c @ 2711]:
b1bfe6c9 837d0c00         cmp     dword ptr [ebp+0xc],0x0

0: kd> u dummy!dummyQueueRecvBuffers+0x2D l1
dummy!dummyQueueRecvBuffers+2d [d:\nt\drivers\dummy\receive.c @ 2894]:
b1bf4e39 807d0c01         cmp     byte ptr [ebp+0xc],0x1

0: kd> u dummy!dummyRxInterruptOnCompletion+0x25D l1
dummy!dummyRxInterruptOnCompletion+25d [d:\nt\drivers\dummy\receive.c @ 1424]:
b1bf5d05 85f6             test    esi,esi

0: kd> u dummy!dummyRxInterruptOnCompletion+0x2b5 l1
dummy!dummyRxInterruptOnCompletion+2b5 [d:\nt\drivers\dummy\receive.c @ 1441]:
b1bf5d5d 8b4648           mov     eax,[esi+0x48]

이제 원본 파일의 이름과 인수가 발생한 줄 번호를 알게 되었습니다. 이 경우 원본 파일은 스레드가 다음과 같이 동작했음을 표시합니다.

  • 스레드 1: DummyActivateVcComplete는 더미 미니포트 잠금을사용했습니다. 그런 다음 더미 큐에RecvBuffers라고, 더미 글로벌 잠금을했다.

  • 스레드 2: dummyRxInterruptOnCompletion 이 전역 잠금을 수행했습니다. 그런 다음, 몇 줄 후, 그것은 미니 포트 잠금을했다.

이 시점에서 교착 상태는 완전히 명확해집니다.