!deadlock

!deadlock 拡張は、Driver Verifier のDeadlock Detection オプションによって収集されたデッドロックに関する情報を表示します。

!deadlock 
!deadlock 1

DLL

Kdexts.dll

追加情報

ドライバー検証ツールの詳細については、Windows ドライバー キット (WDK) のドキュメントを参照してください。

解説

この拡張機能は、Driver Verifier のDeadlock Detectionオプションがロック階層違反を検出し、バグ チェック 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 で利用できました。 無料ビルドでは、1 行の後に切り捨てられる可能性があります。

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ダミーのミニポート ロックを取得しました。 その後、dummyQueueRecvBuffers と呼ばれ、ダミー グローバル ロックが発生しました。

  • スレッド 2: dummyRxInterruptOnCompletion がグローバル ロックを受け取りました。 その後、数行後、ミニポート ロックが発生しました。

この時点で、デッドロックは完全に明確になります。