중요 섹션 시간 초과
스택의 위쪽 근처에 있는 일상적인 RtlpWaitForCriticalSection 을 보여 주는 스택 추적이 있을 때 일부 유형의 중요한 섹션 시간 초과를 식별할 수 있습니다. 또 다른 다양한 중요한 섹션 시간 초과는 교착 상태 애플리케이션 오류일 수 있습니다.
리소스 시간 초과와 마찬가지로 !ntsdexts.locks 확장은 현재 보유하고 있는 잠금 목록과 해당 잠금을 소유한 스레드를 제공합니다. 리소스 시간 초과와 달리 지정된 스레드 ID는 즉시 유용하지 않습니다. 스레드 번호에 직접 매핑되지 않는 시스템 ID입니다.
ExpWaitForResourceXxx와 마찬가지로 잠금 식별자는 **RtlpWaitForCriticalSection의 첫 번째 매개 변수입니다. 루프가 발견되거나 최종 스레드가 중요한 섹션 시간 초과를 기다리지 않을 때까지 대기 체인 추적을 계속합니다.
추가 정보
중요한 섹션 정보를 표시할 수 있는 다른 명령 및 확장은 중요 섹션 표시를 참조하세요. 중요한 섹션에 대한 자세한 내용은 Microsoft Windows SDK 설명서 및 Mark Russinovich 및 David Solomon의 Microsoft Windows Internals를 참조하세요.
중요한 시간 제한 디버깅의 예
먼저 스택을 표시합니다.
0:024> kb
ChildEBP RetAddr Args to Child
0569fca4 77f79c78 77f71000 002a6b88 7fffffff ntdll!_DbgBreakPoint
0569fd04 77f71048 5ffa9f9c 5fef0b4b 5ffa9f9c ntdll!_RtlpWaitForCriticalSection+0x89
0569fd0c 5fef0b4b 5ffa9f9c 002a6b88 002a0019 ntdll!_RtlEnterCriticalSection+0x48
0569fd70 5fedf83f 002a6b88 0569fdc0 0000003e winsrv!_StreamScrollRegion+0x1f0
0569fd8c 5fedfa5b 002a6b88 00190000 00000000 winsrv!_AdjustCursorPosition+0x8e
0569fdc0 5fedf678 0569ff18 0031c200 0335ee88 winsrv!_DoWriteConsole+0x104
0569fefc 5fe6311b 0569ff18 0569ffd0 00000005 winsrv!_SrvWriteConsole+0x96
0569fff4 00000000 00000000 00000024 00000024 csrsrv!_CsrApiRequestThread+0x4ff
이제 !ntsdexts.locks 확장을 사용하여 중요한 섹션을 찾습니다.
0:024> !locks
CritSec winsrv!_ScrollBufferLock at 5ffa9f9c 5ffa9f9c is the first one
LockCount 5
RecursionCount 1
OwningThread 88 // here's the owning thread ID
EntryCount 11c
ContentionCount 135
*** Locked
CritSec winsrv!_gcsUserSrv+0 at 5ffa91b4 //second critical section found below
LockCount 8
RecursionCount 1
OwningThread 6d // second owning thread
EntryCount 1d6c
ContentionCount 1d47
*** Locked
이제 ID 번호가 0x6D 스레드를 검색합니다.
0:024> ~
0 id: 16.15 Teb 7ffdd000 Unfrozen
1 id: 16.13 Teb 7ffdb000 Unfrozen
2 id: 16.30 Teb 7ffda000 Unfrozen
3 id: 16.2f Teb 7ffd9000 Unfrozen
4 id: 16.2e Teb 7ffd8000 Unfrozen
5 id: 16.6c Teb 7ff6c000 Unfrozen
6 id: 16.6d Teb 7ff68000 Unfrozen // this thread owns the second critical section
7 id: 16.2d Teb 7ffd7000 Unfrozen
8 id: 16.33 Teb 7ffd6000 Unfrozen
9 id: 16.42 Teb 7ff6f000 Unfrozen
10 id: 16.6f Teb 7ff6e000 Unfrozen
11 id: 16.6e Teb 7ffd5000 Unfrozen
12 id: 16.52 Teb 7ff6b000 Unfrozen
13 id: 16.61 Teb 7ff6a000 Unfrozen
14 id: 16.7e Teb 7ff69000 Unfrozen
15 id: 16.43 Teb 7ff67000 Unfrozen
16 id: 16.89 Teb 7ff50000 Unfrozen
17 id: 16.95 Teb 7ff65000 Unfrozen
18 id: 16.90 Teb 7ff64000 Unfrozen
19 id: 16.71 Teb 7ff63000 Unfrozen
20 id: 16.bb Teb 7ff62000 Unfrozen
21 id: 16.88 Teb 7ff61000 Unfrozen // this thread owns the first critical section
22 id: 16.cd Teb 7ff5e000 Unfrozen
23 id: 16.c1 Teb 7ff5f000 Unfrozen
24 id: 16.bd Teb 7ff5d000 Unfrozen
스레드 21은 첫 번째 중요 섹션을 소유합니다. 활성 스레드를 만들고 스택 추적을 가져옵니다.
0:024> ~21s
ntdll!_ZwWaitForSingleObject+0xb:
77f71bfb c20c00 ret 0xc
0:021> kb
ChildEBP RetAddr Args to Child
0556fc44 77f79c20 00000110 00000000 77fa4700 ntdll!_ZwWaitForSingleObject+0xb
0556fcb0 77f71048 5ffa91b4 5feb4f7e 5ffa91b4 ntdll!_RtlpWaitForCriticalSection+0x31
0556fcb8 5feb4f7e 5ffa91b4 0556fd70 77f71000 ntdll!_RtlEnterCriticalSection+0x48
0556fcf4 5fef0b76 01302005 00000000 fffffff4 winsrv!__ScrollDC+0x14
0556fd70 5fedf83f 002bd880 0556fdc0 00000025 winsrv!_StreamScrollRegion+0x21b
0556fd8c 5fedfa5b 002bd880 00190000 00000000 winsrv!_AdjustCursorPosition+0x8e
0556fdc0 5fedf678 0556ff18 002bdf70 002a4d58 winsrv!_DoWriteConsole+0x104
0556fefc 5fe6311b 0556ff18 0556ffd0 00000005 winsrv!_SrvWriteConsole+0x96
0556fff4 00000000 00000000 00000024 00000024 csrsrv!_CsrApiRequestThread+0x4ff
스레드 6은 두 번째 중요 섹션을 소유합니다. 스택도 검사합니다.
0:021> ~6s
winsrv!_PtiFromThreadId+0xd:
5fe8429a 394858 cmp [eax+0x58],ecx ds:0023:7f504da8=000000f8
0:006> kb
ChildEBP RetAddr Args to Child
01ecfeb4 5fecd0d7 00000086 00000000 7f5738e0 winsrv!_PtiFromThreadId+0xd
01ecfed0 5feccf62 00000086 01ecfff4 00000113 winsrv!__GetThreadDesktop+0x12
01ecfefc 5fe6311b 01ecff18 01ecffd0 00000005 winsrv!___GetThreadDesktop+0x8b
01ecfff4 00000000 00000000 00000024 00000024 csrsrv!_CsrApiRequestThread+0x4ff
스레드 21에는 스택의 맨 위에 RtlpWaitForCriticalSection 이 있습니다. 스레드 6은 그렇지 않습니다. 따라서 스레드 21을 더 조사하여 대기 중인 내용을 확인해야 합니다. 잠금이 제대로 유지되고 해제되었는지 확인하려면 잠긴 스레드와 연결된 소스 코드를 검사합니다.
애플리케이션 검증 도구
애플리케이션 검증 도구는 잘못된 잠금 사용을 감지하기 위해 호출을 가로채고 래핑할 수 있습니다. 애플리케이션 검증 도구는 다음 문제를 찾는 데 도움이 될 수 있습니다.
- 초기화되지 않은 중요 섹션 사용
- 스레드가 소유하지 않은 중요 섹션을 해제합니다.
- 중요 섹션을 다시 초기화합니다.
- 중요 섹션을 과도하게 릴리스합니다.
- 잠금을 소유하지 않아야 하는 상태의 스레드(ExitThread, TerminateThread, ThreadPool, RPC Threads)이지만 실제로는 잠금을 소유합니다.
자세한 내용은 Application Verifier - 개요를 참조하세요.
추가 정보
분리된 중요 섹션의 코드 샘플 및 디버깅 세션 예제는 Mario Hewardt 및 Daniel Pravat의 고급 Windows 디버깅 을 참조하세요.
중요 섹션 시간 초과 (사용자 모드)