14

관리되는 (C#) 코드와 관리되지 않는 (C++) 코드가 혼합되어있는 응용 프로그램에 문제가 있습니다. 기본적으로 우리는 한 무리의 어셈블리를 호출하는 exe를 가지고 있으며이 어셈블리 중 하나는 C + + 라이브러리의 MC++ 래퍼입니다. 응용 프로그램은 콘솔 응용 프로그램입니다. 대부분의 경우 잘 작동하지만 가끔 오류나 예외없이 중단됩니다.GC 스레드 교착 상태로 .NET 응용 프로그램이 응답하지 않음

메모리 덤프와 심볼을 사용하여 WinDbg에서 진단을 할 수 있었지만 실제로 어떤 것이 교착 상태인지 알 수 없습니다. 스택에 올라와 있지만 하나의 스레드가 메모리 할당을 시도하고 GC로 교착 상태가되는 경우를 찾을 수 없었던 CLR 메서드 이름을 검색했습니다.

지금까지 sos, sosex, psscor4 확장을 사용하여 WinDbg를 시도했습니다. intrestingly sosex는 교착 상태 (! dlk)를 확인하는 명령을 가지고 있지만 교착 상태는보고하지 않습니다.

크고 복잡한 앱이므로 코드를 게시하기가 어렵습니다. .NET 3.5와 4.0 어셈블리가 혼합되어 있습니다. 관리되는 코드와 관리되지 않는 코드 모두에 스레드가 있습니다.

누군가가 스택 추적을보고 이것이 GC 스레드로 인해 교착 상태가 될 수 있다고 확신하는 경우 나는 사과 할 것입니다. 또는 C# 및 MC++를 사용하는 .NET 응용 프로그램에서 교착 상태/중단을 디버깅하는 다른 방법을 제안 할 수 있다면 더 좋습니다. 스레드의

목록을 응용 프로그램이 정지 할 때 : 여기

는 지금까지이 무엇

ThreadCount:  8 
UnstartedThread: 0 
BackgroundThread: 5 
PendingThread: 0 
DeadThread:  0 
Hosted Runtime: no 
              PreEmptive             Lock 
     ID OSID  ThreadOBJ  State GC  GC Alloc Context     Domain   Count APT Exception 
    0 1 de0 00000000008069f0  a020 Enabled 0000000000000000:0000000000000000 00000000007fa280  0 MTA 
    2 2 2130 000000000080bd30  b220 Enabled 0000000000000000:0000000000000000 00000000007fa280  0 MTA (Finalizer) 
    4 3 14fc 000000001d182880 200b020 Enabled 0000000000000000:0000000000000000 00000000007fa280  0 MTA 
    5 4 20d0 000000001d18b400  b220 Enabled 0000000000000000:0000000000000000 00000000007fa280  2 MTA (GC) 
    6 5 18a8 000000001d19f6a0  b020 Enabled 0000000000000000:0000000000000000 00000000007fa280  0 MTA 
    7 6 18a0 000000001d1c6f10  220 Enabled 0000000000000000:0000000000000000 00000000007fa280  0 Ukn 
    8 7 12f4 000000001d1c1ee0  220 Enabled 0000000000000000:0000000000000000 00000000007fa280  0 Ukn 
    10 8 2170 000000001d1c2ad0  220 Enabled 0000000000000000:0000000000000000 00000000007fa280  0 Ukn 

     OSID  Special thread type 
    1 2570 DbgHelper 
    2 2130 Finalizer 
    5 20d0 SuspendEE 
    12 1890 GC 

이것은 GC 스레드의 스택 모습입니다 (스레드!) :

OS Thread Id: 0x1890 (12) 
Child-SP   RetAddr   Call Site 
0000000023e9f898 000000007799e4e8 ntdll!ZwWaitForSingleObject+0xa 
0000000023e9f8a0 000000007799e3db ntdll!RtlpWaitOnCriticalSection+0xe8 
0000000023e9f950 000007fef95d603e ntdll!RtlEnterCriticalSection+0xd1 
0000000023e9f980 000007fef947bc41 clr!UnsafeEEEnterCriticalSection+0x1f 
0000000023e9f9b0 000007fef947613a clr!CrstBase::Enter+0x1a1 
0000000023e9f9f0 000007fef95da3a2 clr!ThreadStore::LockThreadStore+0x9a 
0000000023e9fa20 000007fef9679675 clr!WKS::GCHeap::SuspendEE+0x82 
0000000023e9fb20 000007fef9677eb2 clr!WKS::gc_heap::bgc_suspend_EE+0x25 
0000000023e9fb50 000007fef98455b0 clr!WKS::gc_heap::background_mark_phase+0x236 
0000000023e9fbb0 000007fef9677b76 clr! ?? ::FNODOBFM::`string'+0x9f85d 
0000000023e9fc00 00000000773d652d clr!WKS::gc_heap::gc_thread_function+0xd3 
0000000023e9fc30 000000007797c521 KERNEL32!BaseThreadInitThunk+0xd 
0000000023e9fc60 0000000000000000 ntdll!RtlUserThreadStart+0x1d 

내게는 GC 스레드가 중요 섹션을 기다리고있는 것 같습니다. 크리티컬 섹션 주소를 찾아 소유자 스레드 (! critsec)를 찾을 수있었습니다. 소유자 스레드의 스택은 다음과 같습니다. 나는이 게시물을 짧게 유지하기 위해 그것을 다듬었다. 두 번째 호출 스택에서이 줄은 의심스러운

OS Thread Id: 0x20d0 (5) 
Child-SP   RetAddr   Call Site 
000000001fc5dd38 000007fefe0510dc ntdll!ZwWaitForSingleObject+0xa 
000000001fc5dd40 000007fef9478817 KERNELBASE!WaitForSingleObjectEx+0x79 
000000001fc5dde0 000007fef94787c0 clr!CLREvent::WaitEx+0x170 
000000001fc5de20 000007fef947866b clr!CLREvent::WaitEx+0xf8 
000000001fc5de80 000007fef967a15b clr!CLREvent::WaitEx+0x5e 
000000001fc5df20 000007fef967a001 clr!WKS::gc_heap::user_thread_wait+0x49 
000000001fc5df50 000007fef95dbb4e clr! ?? ::FNODOBFM::`string'+0x9fcc4 
000000001fc5e030 000007fef95da22e clr!WKS::GCHeap::GarbageCollectGeneration+0x14e 
000000001fc5e080 000007fef95d9e4e clr!WKS::gc_heap::try_allocate_more_space+0x25f 
000000001fc5e150 000007fef95d9fc8 clr!WKS::GCHeap::Alloc+0x7e 
000000001fc5e180 000007fef947407c clr!AllocateArrayEx+0xa6b 
000000001fc5e2f0 000007fef8555b75 clr!JIT_NewArr1+0x45c 
000000001fc5e4c0 000007fef8561103 mscorlib_ni!System.Reflection.CustomAttributeData.GetCustomAttributeRecords(System.Reflection.RuntimeModule, Int32)+0x115 
000000001fc5e590 000007fef855db55 mscorlib_ni!System.Reflection.CustomAttribute.IsCustomAttributeDefined(System.Reflection.RuntimeModule, Int32, System.RuntimeType, Boolean)+0x103 
000000001fc5e720 000007fef856c8ac mscorlib_ni!System.Reflection.CustomAttribute.IsDefined(System.RuntimeType, System.RuntimeType, Boolean)+0x75 
000000001fc5e770 000007fef857fe46 mscorlib_ni!System.Enum.InternalFormat(System.RuntimeType, System.Object)+0x2c 
000000001fc5e7b0 000007fef8554f3b mscorlib_ni!System.Text.StringBuilder.AppendFormat(System.IFormatProvider, System.String, System.Object[])+0x2e6 
000000001fc5e850 000007ff03c640fc mscorlib_ni!System.String.Format(System.IFormatProvider, System.String, System.Object[])+0x7b 
000000001fc5e8b0 000007ff03c638a6 MyLibrary1!NumberCache.NumberEntry.ToString()+0x26c 
+0

디버그 진단을 사용하여 덤프를 분석 할 수 있습니다. 이는 Sosex보다 몇 가지 교착 상태 패턴을 분석 할 수 있기 때문입니다. 그러나 교착 상태가 인간에 의해서조차 이해하기에는 너무 복잡하기 때문에 자동 도구로 모든 패턴을 식별 할 수는 없습니다. 여유가 있다면 http://support.microsoft.com을 통해 지원 사례를 열어 Microsoft에 문의하십시오. –

+0

@LexLi, Debug Diag 제안에 감사드립니다. 이전에 나왔지만 너무 특이한 것으로 보였으므로이를 기각했습니다. 이전 mem 덤프 중 하나를 통해 실행했고 기본적으로 동일한 스레드를 가리키는 것입니다. GC 스레드는 다른 스레드가 소유 한 crit 초를 기다리고 있습니다. 어느 쪽이 교착 상태에 대한 어떤 확신을 주는지. Debug Diag는 동일한 psscor4 확장을 사용합니다. 또한 우리는 MS 지원 옵션도 찾고 있습니다. 감사! – user1210698

+0

나는 모든 파이널 라이저 구현 (~)을 점검해야한다고 생각한다. finalizers에 교착 상태가있는 것 같습니다 – 6opuc

답변

2

(! dumpstack) :

000000001fc5df50 000007fef95dbb4e clr! ?? ::FNODOBFM::`string'+0x9fcc4 

봐 오프셋 주소가 얼마나 크고, 나는 모든 모듈의 이름이 표시되지 않습니다 - 일부 누락 기호?

아마도 라이브러리에 문제의 원인이되는 종료 기가있을 수 있습니다.

+0

메소드가 CLR의 일부인 것처럼 보이지만 심볼에 대해서는 확실하지 않습니다. – user1210698

+0

CLR의 일부인 것처럼 보이지만 심볼에 대해서는 잘 모르겠습니다. 또한 COM, C# 및 관리되는 C++ 어셈블리 만 사용하지 않습니다. 어쨌든 우리는 몇 가지 잠금 문을 Monitor.Enter로 바꾼 것처럼 많은 수정 작업을 수행했습니다. 작은 객체를 많이 할당하는 일부 논리에서는 GC.Collect를 추가했습니다. 결국 우리는 지난 몇 달 동안 문제를 보지 못했습니다. – user1210698

+0

종종 큰 오프셋 : + 0x9fcc4는 디버거가 찾을 수있는 마지막 위치에 스택 프레임이 있음을 의미 할 수 있으며 큰 오프셋은 마지막으로 알려진 지점과 현재 실행 지점 간의 차이로 나타납니다 정말이었다. 그러나, 나는 "FNODOBFM"을 봤는데, 그리고 이것을 발견 : http://bit.ly/KTLcZh이 : http://bit.ly/J5HqPJ (bitly이 코멘트에 대한 최대 문자를 오버플로하지). 그 라인은 옵티 마이저에 의한 재배치 때문일 것입니다 - 실제 스택을 아는 것을 어렵게 만듭니다. 어쩌면 그 기사가 도움이 될 수 있습니다. – JMarsch

0

큰 전문가는 아니지만 일부 리소스를 잠그는 동안 finalizer 스레드가 크래시되었는지 (궁극적으로 처리기 스레드에서 처리되지 않은 예외가 있음) 궁금해하고 GC 스레드가이를 획득하려고 시도하고 있습니까?

관련 문제