Ich verwende Windbg, um einen Deadlock zu analysieren, der in einem in Delphi geschriebenen Daten-Snap-Anwendungsserver auftritt."DebugInfo für CritSec verweist nicht auf den kritischen Abschnitt" beim Analysieren von Deadlock
Als ich
!analyze -hang -v
laufe ich dieses
:000:x86> !analyze -hang -v ******************************************************************************* * * * Exception Analysis * * * ******************************************************************************* GetPageUrlData failed, server returned HTTP status 404 URL requested: http://watson.microsoft.com/00000000.htm?Retriage=1 FAULTING_IP: +6ced240 00000000 ?? ??? EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 0000000000000000 ExceptionCode: 80000003 (Break instruction exception) ExceptionFlags: 00000000 NumberParameters: 0 FAULTING_THREAD: 0000000000000000 BUGCHECK_STR: HANG DEFAULT_BUCKET_ID: APPLICATION_HANG PROCESS_NAME: ********.exe ERROR_CODE: (NTSTATUS) 0xcfffffff - EXCEPTION_CODE: (NTSTATUS) 0xcfffffff - MOD_LIST: NTGLOBALFLAG: 0 APPLICATION_VERIFIER_FLAGS: 0 DERIVED_WAIT_CHAIN: Dl Eid Cid WaitType -- --- ------- -------------------------- 0 c7c.2634 Critical Section WAIT_CHAIN_COMMAND: ~0s;k;; BLOCKING_THREAD: 0000000000002634 PRIMARY_PROBLEM_CLASS: APPLICATION_HANG LAST_CONTROL_TRANSFER: from 0000000077138df4 to 000000007711f8b1 STACK_TEXT: 0018fc50 77138df4 00000c6c 00000000 00000000 ntdll_77100000!NtWaitForSingleObject+0x15 0018fcb4 77138cd8 00000000 00000000 03fe0940 ntdll_77100000!RtlpWaitOnCriticalSection+0x13e 0018fcdc 7369324f 736a3134 00000000 03fe0940 ntdll_77100000!RtlEnterCriticalSection+0x150 WARNING: Stack unwind information not available. Following frames may be wrong. 0018fcec 7369af5f 00000388 00000000 003d1e00 mswsock!GetLspGuid+0x19af 0018fd08 76366958 00000388 0018fd84 0018fd9c mswsock!GetLspGuid+0x96bf 0018fd38 0018fd58 763668cd 00000388 0018fd84 ws2_32!WSAAccept+0x84 00000000 00000000 00000000 00000000 00000000 0x18fd58 FOLLOWUP_IP: mswsock!GetLspGuid+19af 7369324f 33db xor ebx,ebx SYMBOL_STACK_INDEX: 3 SYMBOL_NAME: mswsock!GetLspGuid+19af FOLLOWUP_NAME: MachineOwner MODULE_NAME: C:\Windows\System32\mswsock IMAGE_NAME: lld DEBUG_FLR_IMAGE_TIMESTAMP: 4ce7c83d STACK_COMMAND: ~0s ; kb FAILURE_BUCKET_ID: APPLICATION_HANG_cfffffff_lld!Unloaded BUCKET_ID: X64_HANG_mswsock!GetLspGuid+19af WATSON_STAGEONE_URL: http://watson.microsoft.com/00000000.htm?Retriage=1 Followup: MachineOwner ---------
Ich habe dann
!locks -V
zu sehen, welche es Sperre wartet auf und zu meiner Überraschung es diese zurückkehrte,
0:000:x86> !locks -V CritSec ntdll!RtlCriticalSectionLock+0 at 0000000077057060 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 CritSec ntdll!LdrpLoaderLock+0 at 0000000077057490 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 CritSec ntdll!RtlpDynamicFunctionTableLock+0 at 0000000077057468 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 CritSec ntdll!FastPebLock+0 at 000000007705a900 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 CritSec ntdll!RtlpProcessHeapsListLock+0 at 000000007705a240 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 CritSec +270208 at 0000000000270208 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 1 CritSec ntdll!EtwProvCritSect+0 at 000000007705a120 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 CritSec ntdll!EtwPrivSessionCritSect+0 at 000000007705a1e0 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 CritSec +10208 at 0000000000010208 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 CritSec +276f40 at 0000000000276f40 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0 Scanned 10 critical sections
Von
STACK_TEXT: 0018fc50 77138df4 00000c6c 00000000 00000000 ntdll_77100000!NtWaitForSingleObject+0x15 0018fcb4 77138cd8 00000000 00000000 03fe0940 ntdll_77100000!RtlpWaitOnCriticalSection+0x13e 0018fcdc 7369324f 736a3134 00000000 03fe0940 ntdll_77100000!RtlEnterCriticalSection+0x150 WARNING: Stack unwind information not available. Following frames may be wrong. 0018fcec 7369af5f 00000388 00000000 003d1e00 mswsock!GetLspGuid+0x19af 0018fd08 76366958 00000388 0018fd84 0018fd9c mswsock!GetLspGuid+0x96bf 0018fd38 0018fd58 763668cd 00000388 0018fd84 ws2_32!WSAAccept+0x84 00000000 00000000 00000000 00000000 00000000 0x18fd58
ich bestimmt bei den Call-Stack sucht es 0x736a3134 (Erste Parameter RtlEnterCriticalSection bestanden), so lief ich diese
!critsec 736a3134
auf einem kritischen Abschnitt an der Adresse wartete mir dies gab
Ausgang0:000:x86> !critsec 736a3134 DebugInfo for CritSec at 00000000736a3134 does not point back to the critical section NOT an initialized critical section. CritSec mswsock!WSPStartup+6f64 at 00000000736a3134 WaiterWoken Yes LockCount -1 RecursionCount 11028 OwningThread c6c EntryCount 1f49dad6 ContentionCount 88000000 *** Locked
Jetzt fiel der Groschen, der Zeiger auf den kritischen Abschnitt geworden corru pted, möglicherweise wegen gleichzeitigem Thread-Zugriff und fehlender Synchronisation an anderer Stelle im Code
Meine Frage ist, wie finde ich heraus, wo das ist oder herausfinden, ob es ein anderes Problem ist?
PS: Dieser Fehler wird nur angezeigt, wenn die Anwendung mit vielleicht 700 Kunden verbunden
(es wird mit einem Thread pro Verbindung unter hohen Last ist und ich weiß, 32-Bit-Anwendungen werden auf dem Standard-Thread auf ca. 2000 Fäden begrenzt Stackgröße und das ist nicht der beste Ansatz)
PPS: Ich habe mehrere Crash-Dumps, wo die Anwendung hängt auf verschiedene kritische Abschnitte warten, in jedem Fall scheint der Zeiger für den kritischen Abschnitt nicht auf einen kritischen Abschnitt zu zeigen.
Können Sie den Fehler reproduzieren, während Sie den Delphi-Debugger angeschlossen haben? Wenn ja, können Sie die Callstacks überprüfen und ich denke in späteren Delphi-Versionen sogar einige Deadlock-Informationen innerhalb der IDE. Eine andere Sache zu erwähnen ist, dass kritische Abschnitte sehr sinnvoll sind, wenn falsche Initialisierungen, z. ein Code snipplet wie: critSect.Leave; critSect.Enter; kann sehr schlechte Nebenwirkungen haben. Wenn nichts hilft, schlage ich vor, Sie versuchen, zwei Dinge: 1.) FastMM im vollen Debug-Modus (Heap Korruption) 2.) fahren Sie Ihre eigenen kritischen Abschnitt Klasse und zählen für alle eingeben und verlassen Anrufe (schließlich plus einen Anruf param). – mrabat
Wir haben versucht, im Delphi-Debugger und nur Standalone zu reproduzieren, kann aber nicht, daher der Grund für die Verwendung von Windbg und Crash-Dumps. Wir vermuten, dass wir, um den Fehler zu bekommen, eine große Last auf dem Server erzeugen müssen und es auch zeitkritisch ist. Wir haben den gesamten Code überprüft und können einen Fehler mit der Sperrreihenfolge oder an einem anderen Ort, an dem wir eine Sperre oder Notwendigkeit für die Synchronisation verpasst haben, leicht erkennen, aber denken, dass wir etwas übersehen haben müssen. – MikeT
Es ist unwahrscheinlich, dass der Zeiger, den Sie identifiziert haben, ein Zeiger auf den kritischen Abschnitt ist. Verlassen Sie sich nicht darauf, dass Parameter im Stack korrekt bleiben, da sie überschrieben und wiederverwendet werden können. Zum einen ist der Zeiger 736a3134 in msswock dem Code-Segment sehr nahe, so dass er wahrscheinlich einer der Rückkehrzeiger ist. –