Delen via


Een processorvreter opsporen

Als de ene toepassing ('hogging') alle aandacht van de processor verbruikt, zullen andere processen uiteindelijk 'honger' krijgen en kunnen ze niet worden uitgevoerd.

Gebruik de volgende procedure om een bug van dit type te corrigeren.

Fouten opsporen in een toepassing die gebruikmaakt van alle CPU-cycli

  1. Bepaal welke toepassing dit probleem veroorzaakt: Gebruik Taakbeheer of Perfmon om te bepalen welk proces 99% of 100% van de processorcycli gebruikt. Dit kan u ook de foutieve thread aangeven.

  2. Koppel WinDbg, KD of CDB aan dit proces.

  3. Bepaal welke thread het probleem veroorzaakt: Onderbreek de overtredende toepassing. Gebruik de extensie !runaway 3 om een 'momentopname' te maken van waar alle CPU-tijd heen gaat. Gebruik g (Go) en wacht een paar seconden. Pauzeer en gebruik !runaway 3 opnieuw.

    0:002> !runaway 3
     User Mode Time
     Thread    Time
     4e0        0:12:16.0312
     268        0:00:00.0000
     22c        0:00:00.0000
     Kernel Mode Time
     Thread    Time
     4e0        0:00:05.0312
     268        0:00:00.0000
     22c        0:00:00.0000
    
    0:002> g
    
    0:001> !runaway 3
     User Mode Time
     Thread    Time
     4e0        0:12:37.0609
     3d4        0:00:00.0000
     22c        0:00:00.0000
     Kernel Mode Time
     Thread    Time
     4e0        0:00:07.0421
     3d4        0:00:00.0000
     22c        0:00:00.0000
    

    Vergelijk de twee sets getallen en zoek naar de thread waarvan de tijd in de gebruikersmodus of kernelmodus het meest is toegenomen. Omdat !runaway sorteert op aflopende CPU-tijd, is de verstorende thread meestal de thread bovenaan de lijst. In dit geval veroorzaakt thread 0x4E0 het probleem.

  4. Gebruik de opdrachten ~ (threadstatus) en ~s (Huidige thread instellen) om dit de huidige thread te maken:

    0:001> ~
       0  Id: 3f4.3d4 Suspend: 1 Teb: 7ffde000 Unfrozen
    .  1  Id: 3f4.22c Suspend: 1 Teb: 7ffdd000 Unfrozen
     2  Id: 3f4.4e0 Suspend: 1 Teb: 7ffdc000 Unfrozen
    
    0:001> ~2s
    
  5. Gebruik kb (Display Stack Backtrace) om een stacktrace van deze thread te verkrijgen:

    0:002> kb
    FramePtr  RetAddr   Param1   Param2   Param3   Function Name
    0b4ffc74  77f6c600  000000c8.00000000 77fa5ad0 BuggyProgram!CreateMsgFile+0x1b
    0b4ffce4  01836060  0184f440 00000001 0b4ffe20 BuggyProgram!OpenDestFileStream+0xb3
    0b4ffd20  01843eba  02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3
    0b4ffe20  01855924  0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4
    0b4ffe5c  77e112e6  01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34
    0b4ffeb0  77e11215  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0
    0b4ffed0  77e1a3b1  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41
    0b4fff40  77e181e4  02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b
    0b4fff60  77e1a5df  02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91
    0b4fff90  77e1ac1c  77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76
    
  6. Stel een onderbrekingspunt in op het adres van de huidige actieve functie. In dit geval wordt het adres van de afzender op de eerste regel weergegeven als 0x77F6C600. Het retouradres is gelijk aan de functie-offset die op de tweede regel wordt weergegeven (BuggyProgram! OpenDestFileStream+0xB3). Als er geen symbolen beschikbaar zijn voor de toepassing, wordt de functienaam mogelijk niet weergegeven. Gebruik de opdracht g (Go) om uit te voeren totdat dit retouradres is bereikt, met behulp van het symbolische of hexadecimale adres:

    0:002> g BuggyProgram!OpenDestFileStream+0xb3
    
  7. Als dit onderbrekingspunt wordt bereikt, herhaalt u het proces. Stel dat dit onderbrekingspunt is bereikt. De volgende stappen moeten worden uitgevoerd:

    0:002> kb
    FramePtr  RetAddr   Param1   Param2   Param3   Function Name
    0b4ffce4  01836060  0184f440 00000001 0b4ffe20 BuggyProgram!OpenDestFileStream+0xb3
    0b4ffd20  01843eba  02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3
    0b4ffe20  01855924  0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4
    0b4ffe5c  77e112e6  01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34
    0b4ffeb0  77e11215  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0
    0b4ffed0  77e1a3b1  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41
    0b4fff40  77e181e4  02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b
    0b4fff60  77e1a5df  02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91
    0b4fff90  77e1ac1c  77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76
    
    0:002> g BuggyProgram!SaveMsgToDestFolder+0xb3
    

    Als dit wordt bereikt, gaat u verder met:

    0:002> kb
    FramePtr  RetAddr   Param1   Param2   Param3   Function Name
    0b4ffd20  01843eba  02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3
    0b4ffe20  01855924  0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4
    0b4ffe5c  77e112e6  01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34
    0b4ffeb0  77e11215  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0
    0b4ffed0  77e1a3b1  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41
    0b4fff40  77e181e4  02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b
    0b4fff60  77e1a5df  02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91
    0b4fff90  77e1ac1c  77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76
    
    0:002> g BuggyProgram!DispatchToConn+0xa4
    
  8. Ten slotte vindt u een onderbrekingspunt dat niet wordt bereikt. In dit geval moet u ervan uitgaan dat de laatste g-opdracht het doel in werking heeft gezet en dat het niet is gestopt. Dit betekent dat de functie SaveMsgToDestFolder() nooit wordt geretourneerd.

  9. Onderbreek de thread opnieuw en stel een onderbrekingspunt in op BuggyProgram!SaveMsgToDestFolder+0xB3 met de opdracht bp (onderbrekingspunt instellen). Gebruik vervolgens de opdracht g herhaaldelijk. Als dit breekpunt onmiddellijk wordt aangeslagen, ongeacht hoe vaak u het doel hebt uitgevoerd, is het zeer waarschijnlijk dat u de problematische functie hebt geïdentificeerd.

    0:002> bp BuggyProgram!SaveMsgToDestFolder+0xb3
    
    0:002> g 
    
    0:002> g 
    
  10. Gebruik de opdracht p (Step) om door te gaan met de functie totdat u de plaats identificeert waar de lusvolgorde van instructies zich bevindt. Vervolgens kunt u de broncode van de toepassing analyseren om de oorzaak van de draaiende thread te identificeren. De oorzaak is meestal een probleem in de logica van een while, do-while, goto of for loop.