我正在使用 Windbg 分析在用 delphi 编写的数据快照应用程序服务器中发生的死锁。
当我跑
!analyze -hang -v
我明白了
:000:x86> !analyze -hang -v ****************************************************** ***************************** * * * 异常分析 * * * ****************************************************** ***************************** GetPageUrlData 失败,服务器返回 HTTP 状态 404 请求的 URL:http://watson.microsoft.com/00000000.htm?Retriage=1 FAULTING_IP: +6ced240 00000000 ?? ??? EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff) 异常地址:0000000000000000 ExceptionCode:80000003(Break指令异常) 异常标志:00000000 编号参数:0 FAULTING_THREAD:0000000000000000 BUGCHECK_STR:挂起 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 临界区 WAIT_CHAIN_COMMAND: ~0s;k;; BLOCKING_THREAD:0000000000002634 PRIMARY_PROBLEM_CLASS:APPLICATION_HANG LAST_CONTROL_TRANSFER:从 0000000077138df4 到 000000007711f8b1 堆栈文本: 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 警告:堆栈展开信息不可用。以下框架可能是错误的。 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:机器所有者 模块名称:C:\Windows\System32\mswsock IMAGE_NAME:lld DEBUG_FLR_IMAGE_TIMESTAMP:4ce7c83d STACK_COMMAND: ~0s ; KB FAILURE_BUCKET_ID:APPLICATION_HANG_cfffffff_lld!卸载 BUCKET_ID: X64_HANG_mswsock!GetLspGuid+19af WATSON_STAGEONE_URL:http://watson.microsoft.com/00000000.htm?Retriage=1 跟进:MachineOwner ---------
然后我做了
!locks -V
查看它在等待哪个锁,令我惊讶的是它返回了这个,
0:000:x86> !locks -V CritSec ntdll!RtlCriticalSectionLock+0 在 0000000077057060 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 CritSec ntdll!LdrpLoaderLock+0 at 0000000077057490 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 CritSec ntdll!RtlpDynamicFunctionTableLock+0 at 0000000077057468 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 CritSec ntdll!FastPebLock+0 在 000000007705a900 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 CritSec ntdll!RtlpProcessHeapsListLock+0 at 000000007705a240 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 CritSec +270208 在 0000000000270208 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 1 CritSec ntdll!EtwProvCritSect+0 在 000000007705a120 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 CritSec ntdll!EtwPrivSessionCritSect+0 在 000000007705a1e0 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 CritSec +10208 在 0000000000010208 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 CritSec +276f40 在 0000000000276f40 LockCount 未锁定 递归计数 0 拥有线程 0 条目数 0 争用计数 0 扫描了 10 个关键部分
从查看调用堆栈
堆栈文本: 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 警告:堆栈展开信息不可用。以下框架可能是错误的。 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
我确定它正在等待地址 0x736a3134 的关键部分(传递给 RtlEnterCriticalSection 的第一个参数)所以我运行了这个
!critsec 736a3134
这给了我这个输出
0:000:x86> !critsec 736a3134 位于 00000000736a3134 的 CritSec 的 DebugInfo 未指向临界区 不是初始化的临界区。 CritSec mswsock!WSPStartup+6f64 at 00000000736a3134 服务员醒来 是的 锁定计数 -1 递归计数 11028 拥有线程 c6c 条目计数 1f49dad6 争用计数 88000000 *** 锁定
现在一分钱掉了,指向临界区的指针已经损坏,可能是由于并发线程访问和代码中其他地方缺乏同步
我的问题是我如何追踪它在哪里或找出它是否是另一个问题?
PS:此错误仅在应用程序负载过重且可能连接了 700 个客户端时出现
(每个连接使用一个线程,我知道 32 位应用程序将被限制为默认线程堆栈大小的大约 2000 个线程,这不是最好的方法)
PPS:我有多个故障转储,其中应用程序挂起等待不同的关键部分,在每种情况下,关键部分的指针似乎都没有指向关键部分。