|
Finalizer Thread는 CLR 메모리 덤프에서 볼 수 있는 특이한 Thread 중에 하나이다. 오브젝트가 Garbage Collected 될 때, 오브젝트의 Finalize Method는 Finalizer에 의해서 수행이 된다. 일반적으로 이러한 Finalization이 필요한 오브젝트는 File 이나 Unmanaged Memory와 같은 Unmanaged Resource를 사용하는 오브젝트이며, 필요에 의해 Finalize Method를 구현하여 이와 같은 Unmanaged resource의 누수를 방지하는 역할을 하는 것이 Finalizer Thread이다. 일반적으로 Finalizer Thread를 확인하는 방법은 !threads의 출력으로 다음과 같이 확인할 수 있다. 0:026> !threads ThreadCount: 12 UnstartedThread: 0 BackgroundThread: 12 PendingThread: 0 DeadThread: 0 PreEmptive GC Alloc Lock ID ThreadOBJ State GC Context Domain Count APT Exception 16 0xf44 0x000d23e0 0xa220 Enabled 0x06953ce0:0x06954ff4 0x00113b98 1 MTA 20 0x7bc 0x000d3910 0xb220 Enabled 0x00000000:0x00000000 0x000cd460 0 MTA (Finalizer) 22 0xf64 0x000ef538 0x1800220 Enabled 0x00000000:0x00000000 0x000cd460 0 MTA (Threadpool Worker) 그리고, 대부분의 메모리 덤프에서는 다음과 같은 Finalizer Thread의 Callstack을 확인할 수 있다. 0:020> kbL ChildEBP RetAddr Args to Child 023ffdf8 7c967d19 7c82202c 00000002 023ffe48 ntdll!KiFastSystemCallRet 023ffdfc 7c82202c 00000002 023ffe48 00000001 ntdll!NtWaitForMultipleObjects+0xc 023ffea4 7c822fbe 00000002 793effc8 00000000 kernel32!WaitForMultipleObjectsEx+0x11a 023ffec0 7926ed87 00000002 793effc8 00000000 kernel32!WaitForMultipleObjects+0x18 023ffee0 792034b2 000002f0 00000000 7922ec48 mscorsvr!WaitForFinalizerEvent+0x5a 023fff24 7922ec3f 00000000 809a1724 7ff97000 mscorsvr!GCHeap::FinalizerThreadStart+0x96 023fffb8 7c82482f 000d3ad8 00000000 00000000 mscorsvr!Thread::intermediateThreadProc+0x44 023fffec 00000000 7922ebfe 000d3ad8 00000000 kernel32!BaseThreadStart+0x34 일반적으로 Finalizer Thread를 쳐다볼 일은 없을 것이다. 하지만, Finalizer Thread의 Blocking으로 인해서 예상치 못한 메모리 누수현상이 발생할 수 있다. 쉽게 isolation 할 수 있는 것은 ü Hang Dump를 몇 차례 수집하였을 때, !finalizequeue의 결과의 추이를 살펴보는 것일 것이다. 계속해서 Finalizequeue 에 오브젝트들이 쌓이고 있다면, Finalizer Thread의 Block을 의심할 수 있다. ü GC가 정상적으로 수행되지 않는 다고 생각될 경우에도 Finalizer Thread를 살펴보는 것이 좋을 것 같다. 일반적으로 메모리 누수의 원인이 되는 오브젝트들이 Reference를 갖고 있지 않는 경우라면, 다음 GC가 수행되었을 때, 메모리가 반환될 것이다. 하지만, 이러한 참조되지 않는 오브젝트가 대량으로 메모리를 차지 하고 있다면, GC의 수행이 그다지 Health한 상태가 아닐 수 있기 때문에 GC Thread와 더불어 Finalizer Thread 역시 확인 대상이 된다. 다음의 Thread Stack은 흥미롭다. Finalizer thread가 맞다. 하지만, EnterCriticalSection에서 Waiting을 하고 있다. 다음의 Managed Callstack 은 임의의 Finalize Method가 처리되고 있는 것이 눈에 띈다. 만일, 지속적으로 이와 같은 Callstack이 Stuck 되고 있다면, 이는 Finalizer Thread가 Block 된 상태로 보면 된다. 해당 Finalize Method와 연관된 CriticalSection Lock 또는 관련 Thread Stack을 Check해보는 것이 우선일 수 있다. 0:002> kbL ChildEBP RetAddr Args to Child 00c9f9fc 7c967d29 7c97d266 000011d8 00000000 ntdll!KiFastSystemCallRet 00c9fa00 7c97d266 000011d8 00000000 00000000 ntdll!NtWaitForSingleObject+0xc 00c9fa3c 7c97d2b1 000011d8 00000002 04b2b008 ntdll!RtlpWaitOnCriticalSection+0x1a3 00c9fa5c 608fa5af 08ddbf68 00c9fcc4 61ccc1ae ntdll!RtlEnterCriticalSection+0xa8 WARNING: Stack unwind information not available. Following frames may be wrong. 00c9fa68 61ccc1ae 006e2628 0487af7c 00000000 oracore10!sltsmna+0xf 00c9fcc4 61ccb998 08b60128 00000004 00000000 OraClient10!kpufhndl0+0x80e 00c9fcd8 61c2602c 08b60128 00000004 00c9fcf8 OraClient10!kpufhndl+0x10 00c9fce8 1000706c 08b60128 00000004 00c9fd7c OraClient10!OCIHandleFree+0x1a 00c9fd9c 7c966f69 00c9fe30 79215bdd 00c9fe20 oci!OCIHandleFree+0x18 00c9fda4 79215bdd 00c9fe20 7921d108 ffffffff ntdll!ZwDelayExecution+0xc 00c9fe30 79215ca5 0167b394 0015e1e0 0014c698 mscorwks!MethodTable::CallFinalizer+0xee 00c9fe44 791e0984 0167b394 7c822311 00000000 mscorwks!CallFinalizer+0x84 00c9fedc 791b997b 0167b394 00000000 00000000 mscorwks!FinalizeAllObjects+0xd5 00c9ff24 791c94b4 00000000 809a1724 7ffdb000 mscorwks!GCHeap::FinalizerThreadStart+0xc2 00c9ffb8 7c82482f 0015e398 00000000 00000000 mscorwks!Thread::intermediateThreadProc+0x44 00c9ffec 00000000 791c9473 0015e398 00000000 kernel32!BaseThreadStart+0x34 0:002> !dumpstack -EE Thread 2 Current frame: ChildEBP RetAddr Caller,Callee 00c9fd28 0393d63f (MethodDesc 0x320be10 +0xf System.Data.OracleClient.TracedNativeMethods.OCIHandleFree) 00c9fd34 0393bb47 (MethodDesc 0x320c1f8 +0xf7 System.Data.OracleClient.OciHandle.Dispose) 00c9fd7c 00879c75 (MethodDesc 0x320c188 +0x1d System.Data.OracleClient.OciHandle.Finalize)
|
카테고리
이글루링크
최근 등록된 덧글
그러세요
by 강세윤 at 12/15 오늘 많이 헤매다..알게 .. by youna at 12/14 글 잘 읽었습니다 . 전 .. by 위시 at 11/26 어렷다 by klhk at 11/09 dhjjgbem by kl at 11/09 17번부터 어떻게 접는지.. by tykim0131 at 10/28 ATL이나 MFC를 이용하.. by 김명신 at 09/24 복원되었군요.. 제 RSS.. by 강세윤 at 09/24 허걱, 하고 있는 것으로.. by 강세윤 at 09/15 RSS 주소 서비스는 안 .. by 정성태 at 09/15 이글루 파인더
| |||