Delen via


Impasses voor foutopsporing - DRIVER_VERIFIER_DETECTED_VIOLATION (C4): 0x1001

Wanneer Driver Verifier een schending van de spin lock-hiërarchie detecteert, genereert Driver Verifier Bugcontrole 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION met een parameter 1-waarde van 0x1001.

Wanneer de optie Impassedetectie actief is (Impassedetectie maakt deel uit van de standaardopties voor stuurprogrammaverifier), houdt stuurprogrammaverifier elke toegewezen spinvergrendeling bij en de volgorde waarin deze is verkregen en vrijgemaakt. Een schending van de hiërarchie van de vergrendeling betekent dat Driver Verifier een situatie heeft gedetecteerd waarbij LockA in ten minste één geval wordt verkregen en vastgehouden voordat LockB wordt verkregen, en in een ander geval LockB wordt verkregen en bewaard voordat LockA is vereist.

Belangrijk Deze foutcontrole treedt op wanneer Driver Verifier detecteert dat de hiërarchie-schending heeft plaatsgevonden, niet wanneer er een werkelijke impassesituatie optreedt. Deze schending dringt sterk aan op dat vergrendelingen die worden gedeeld tussen de verschillende onderdelen van een stuurprogramma altijd moeten worden verkregen en vrijgegeven in een volgorde waardoor het doodlopen van twee threads onmogelijk wordt.

Nieuw in Windows 8.1 Wanneer stuurprogrammaverificator deze schending tegenkomt, als het foutopsporingsprogramma is gekoppeld, vraagt het foutopsporingsprogramma u om invoer over de fout. In Windows 8 en eerdere versies van Windows leidt deze schending tot een onmiddellijke foutcontrole.

************ Verifier Detected a Potential Deadlock *************
**
** Type !deadlock in the debugger for more information.
**
*****************************************************************

*** Verifier assertion failed ***
(B)reak, (I)gnore, (W)arn only, (R)emove assert?

Als u deze schending op een computer met Windows 8.1 wilt debuggen, kiest u B (Verbreken) en voert u de voorgestelde debugger-opdracht (!deadlock) in:

kd> !deadlock
issue: 00001001 97dd800c 86858ce0 00000000 

Deadlock detected (2 locks in 2 threads):

Thread 0: A B.
Thread 1: B A.

Where:

Thread 0 = TERMINATED.
Thread 1 = c4ae2040.

Lock A =   97dd800c (MyTestDriver!AlphaLock+0x00000000) - Type 'Spinlock'.
Lock B =   97dd8008 (MyTestDriver!BravoLock+0x00000000) - Type 'Spinlock'.

De opdracht !deadlock3 kan ook worden gebruikt om meer informatie weer te geven, inclusief de stack op het moment van laatste verkrijging:

kd> !deadlock 3
issue: 00001001 97dd800c 86858ce0 00000000 

Deadlock detected (2 locks in 2 threads):
# 

Thread 0: TERMINATED took locks in the following order:

Lock A =     97dd800c (MyTestDriver!AlphaLock+0x00000000) - Type 'Spinlock'.

    Node:    8685acd8

    Stack:   97dd65b7 MyTestDriver!SystemControlIrpWorker+0x00000027 
             97dd605a MyTestDriver!Dispatch_SystemControl+0x0000001a 
             820c4b4d nt!IovCallDriver+0x000002cc 
             81ca3772 nt!IofCallDriver+0x00000062 
             81eb165e nt!IopSynchronousServiceTail+0x0000016e 
             81eb5518 nt!IopXxxControlFile+0x000003e8 
             81eb4516 nt!NtDeviceIoControlFile+0x0000002a 
             81d27e17 nt!KiSystemServicePostCall+0x00000000 

Lock B =     97dd8008 (MyTestDriver!BravoLock+0x00000000) - Type 'Spinlock'.

    Node:    86833578

    Stack:   97dd65c5 MyTestDriver!SystemControlIrpWorker+0x00000a4a 
             97dd605a MyTestDriver!Dispatch_SystemControl+0x0000001a 
             820c4b4d nt!IovCallDriver+0x000002cc 
             81ca3772 nt!IofCallDriver+0x00000062 
             81eb165e nt!IopSynchronousServiceTail+0x0000016e 
             81eb5518 nt!IopXxxControlFile+0x000003e8 
             81eb4516 nt!NtDeviceIoControlFile+0x0000002a 
             81d27e17 nt!KiSystemServicePostCall+0x00000000
# 

Thread 1: c4ae2040 (ThreadEntry = 86833a08) took locks in the following order:

Lock B =     97dd8008 (MyTestDriver!BravoLock+0x00000000) - Type 'Spinlock'.

    Node:    86858ce0

    Stack:   97dd65ef MyTestDriver!DeviceControlIrpWorker+0x0000005f 
             97dd605a MyTestDriver!Dispatch_DeviceControl+0x0000001a 
             820c4b4d nt!IovCallDriver+0x000002cc 
             81ca3772 nt!IofCallDriver+0x00000062 
             81eb165e nt!IopSynchronousServiceTail+0x0000016e 
             81eb5518 nt!IopXxxControlFile+0x000003e8 
             81eb4516 nt!NtDeviceIoControlFile+0x0000002a 
             81d27e17 nt!KiSystemServicePostCall+0x00000000 

Lock A =     97dd800c (MyTestDriver!AlphaLock+0x00000000) - Type 'Spinlock'.

    Stack:   << Current stack trace - use kb to display it >>

De debugger stelt voor om de kb-opdracht (Stack backtrace weergeven) te gebruiken om de huidige stack trace weer te geven.

kd> kb
ChildEBP RetAddr  Args to Child              
89b2cac4 820da328 97dd800c 86858ce0 00000000 nt!VfReportIssueWithOptions+0x86
89b2caf4 820d92a2 00000001 00000000 97dd65fd nt!ViDeadlockAnalyze+0x1d1
89b2cb7c 820d424e 86858ce0 00000000 97dd65fd nt!VfDeadlockAcquireResource+0x2fd
89b2cb9c 97dd65fd 00007780 89b2cbbc 97dd605a nt!VerifierKfAcquireSpinLock+0x8c
89b2cba8 97dd605a 9a9e7780 88d08f48 00000000 MyTestDriver!DeviceControlIrpWorker+0x54a
89b2cbbc 820c4b4d 9a9e7780 88d08f48 820c4881 MyTestDriver!Dispatch_DeviceControl+0x1a
(Inline) -------- -------- -------- -------- nt!IopfCallDriver+0x47
89b2cbe0 81ca3772 81eb165e b3c9ff80 88d08f48 nt!IovCallDriver+0x2cc
89b2cbf4 81eb165e 88d08fdc 88d08f48 00000000 nt!IofCallDriver+0x62

De uitvoer van de debugger laat zien dat het betreffende stuurprogramma deze regel heeft geschonden door Lock A te verkrijgen en vast te houden voordat Lock B op één thread werd verkregen, en nu op een andere thread Lock B heeft verkregen en probeert Lock A te verkrijgen. Houd er rekening mee dat de eerste thread (Thread 0) wordt beëindigd, dus de verwerving en daaropvolgende vrijgave van deze twee vergrendelingen vond op enig moment plaats sinds de afbeelding van de driver was geladen.

Wanneer de juiste symbolen voor de testdriver worden geladen, toont het foutopsporingsprogramma de functie waarin de vergrendeling op dat moment is verkregen. In dit voorbeeld gebeurt het dus dat zowel Lock A als Lock B worden verkregen in dezelfde functie. In Thread 0 worden beide in SystemControlIrpWorker verkregen. In Thread 1 worden ze beide verkregen in DeviceControlIrpWorker (weergegeven in de Lock B-uitvoer van !deadlock 3 en de huidige stack-uitvoer (kb).

Op dit moment moet een beoordeling van de broncode van elke functie aantonen dat er een codepad bestaat waar de vergrendelingen in een dergelijke volgorde kunnen worden verkregen.

Beide MyTestDriver! AlphaLock en MyTestDriver! BravoLock zijn objecten wereldwijd beschikbaar in de driver:

include "MyTestDriverHeader.h"

// Locks used to control access to various objects
extern KSPIN_LOCK AlphaLock;
extern KSPIN_LOCK BravoLock;

Binnen de functie SystemControlIrpWorker bestaat er een pad waar AlphaLock (Lock A in de uitvoer van !deadlock) wordt verkregen en vastgehouden wanneer BravoLock (Lock B) wordt verkregen. Het is ook de moeite waard om te vermelden dat de sloten correct worden vrijgegeven in de omgekeerde volgorde waarin ze worden verkregen. (De volgende code wordt sterk bewerkt om alleen de elementen weer te geven die nodig zijn om dit scenario te genereren).

NTSTATUS SystemControlIrpWorker(_In_ PIRP Irp)
{
    KIRQL IrqlAlpha;
    KIRQL IrqlBravo;
    // <<Other local variable declarations removed>>

    // <<Various lines of code not shown>>

    KeAcquireSpinLock (&AlphaLock, &IrqlAlpha);

    // <<Various lines of code not shown>>

    KeAcquireSpinLock (&BravoLock, &IrqlBravo);

    // <<Various lines of code not shown>>

    KeReleaseSpinLock (&BravoLock, IrqlBravo);
    KeReleaseSpinLock (&AlphaLock, IrqlAlpha);

    // <<Various lines of code not shown>>
}

Als u de volgende voorbeeldfunctie van DeviceControlIrpWorker bekijkt, kunt u zien dat het mogelijk is om de vergrendelingen in omgekeerde volgorde te verkrijgen. Dat wil zeggen, BravoLock kan worden verkregen en gehouden wanneer men probeert AlphaLock te verkrijgen. Het volgende voorbeeld is vereenvoudigd, maar het laat zien dat er een mogelijk pad is waar een schending kan optreden.

NTSTATUS DeviceControlIrpWorker(_In_ PIRP Irp, 
                                _In_ BOOLEAN bSomeCondition)
{
    KIRQL IrqlAlpha;
    KIRQL IrqlBravo;
    // <<Other local variable declarations removed>>

    if (bSomeCondition == FALSE)
    {
        //
        // Note that if bSomeCondition is FALSE, then AlphaLock is acquired here
        // If bSomeCondition is TRUE, it is not needed to be acquired right now
        //
        KeAcquireSpinLock (&AlphaLock, &IrqlAlpha);
    }

    // <<Various lines of code not shown>>

    KeAcquireSpinLock (&BravoLock, &IrqlBravo);

    // <<Various lines of code not shown>>

    if (bSomeCondition == TRUE)
    { 
        //
        // Need to acquire AlphaLock here for upcoming code logic
        //
        KeAcquireSpinLock (&AlphaLock, &IrqlAlpha);

        // <<Various lines of code not shown>>

        KeReleaseSpinLock (&AlphaLock, IrqlAlpha);
    }

    // <<Various lines of code not shown>>

    KeReleaseSpinLock (&BravoLock, IrqlBravo);

    if (bSomeCondition == FALSE)
    {
        //
        // Release the AlphaLock, which was acquired much earlier
        //
        KeReleaseSpinLock (&AlphaLock, IrqlAlpha);
    }

    // <<Various lines of code not shown>>
}

Om deze mogelijke schending op te lossen, is het juiste om ervoor te zorgen dat wanneer de bestuurder probeert AlphaLock te verkrijgen, het controleert en ervoor zorgt dat BravoLock niet wordt vastgehouden. De eenvoudigste oplossing kan zijn om BravoLock vrij te geven en opnieuw te verkrijgen zodra AlphaLock is verkregen. Maar belangrijkere codewijzigingen kunnen nodig zijn als het essentieel is dat de gegevens die BravoLock beveiligt, niet veranderen terwijl wordt gewacht op AlphaLock en de heraankoop van BravoLock.

Zie Spin Locks voor meer informatie over spinvergrendelingen en andere synchronisatietechnieken.

spinlocks

Foutcontrole 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION

!patstelling