2017-02-23 2 views
4

WCF 응용 프로그램 중 하나에서 메모리 누수가 발생했으며 누군가가 나를 명확하게 할 수 있는지 궁금합니다. windbg를 사용하여! finalizequeue를 실행하고 각 힙에 "완료 준비 완료"로 표시된 수천 개의 객체를 표시합니다.Finalizer 스레드 Id

Heap 0 
generation 0 has 464 finalizable objects (0000000033877190->0000000033878010) 
generation 1 has 52 finalizable objects (0000000033876ff0->0000000033877190) 
generation 2 has 19958 finalizable objects (0000000033850040->0000000033876ff0) 
Ready for finalization 228791 objects (0000000033878010->0000000033a36dc8) 
------------------------------ 
Heap 1 
generation 0 has 1508 finalizable objects (000000002ee2e168->000000002ee31088) 
generation 1 has 91 finalizable objects (000000002ee2de90->000000002ee2e168) 
generation 2 has 23498 finalizable objects (000000002ee00040->000000002ee2de90) 
Ready for finalization 249421 objects (000000002ee31088->000000002f0182f0) 
------------------------------ 
Heap 2 
generation 0 has 66 finalizable objects (00000000292660d0->00000000292662e0) 
generation 1 has 63 finalizable objects (0000000029265ed8->00000000292660d0) 
generation 2 has 19411 finalizable objects (0000000029240040->0000000029265ed8) 
Ready for finalization 238531 objects (00000000292662e0->00000000294380f8) 
------------------------------ 
Heap 3 
generation 0 has 510 finalizable objects (0000000034e470d8->0000000034e480c8) 
generation 1 has 77 finalizable objects (0000000034e46e70->0000000034e470d8) 
generation 2 has 19910 finalizable objects (0000000034e20040->0000000034e46e70) 
Ready for finalization 226933 objects (0000000034e480c8->0000000035003470) 
Statistics for all finalizable objects (including all objects ready for finalization): 

파이널 라이저 스레드가 멈췄다 고합니다. 그래서 종료 자 스레드 ID를 얻기 위해 WinDBG로에서! 스레드 명령을 실행하고이

ThreadCount:  2969 
UnstartedThread: 0 
BackgroundThread: 187 
PendingThread: 0 
DeadThread:  2782 
Hosted Runtime: no 
                             Lock 
     ID OSID ThreadOBJ   State GC Mode  GC Alloc Context     Domain   Count Apt Exception 
XXXX 2 19e8 0000000001f64b10 80039220 Preemptive 0000000000000000:0000000000000000 000000000d4aacb0 0  Ukn (Finalizer) 
    18 3 cb4 000000000d9bf7a0 102a220 Preemptive 0000000000000000:0000000000000000 000000000150e940 0  MTA (Threadpool Worker) 
    19 4 1a24 000000000f762720 21220 Preemptive 0000000000000000:0000000000000000 000000000150e940 0  Ukn 
    20 6 e1c 0000000010f4eae0 3029220 Preemptive 0000000000000000:0000000000000000 000000000d4aacb0 0  MTA (Threadpool Worker) 
    22 48 1548 000000001feb1880 21220 Preemptive 0000000000000000:0000000000000000 000000000150e940 0  Ukn 
    23 49 11a4 000000001feb2050 21220 Preemptive 0000000000000000:0000000000000000 000000000150e940 0  Ukn 
    24 50 a64 000000001feb2820 21220 Preemptive 0000000000000000:0000000000000000 000000000150e940 0  Ukn 

목록의 첫 번째 스레드가 종료 자 스레드와 스레드 ID는 XXXX입니다 .... 그것을 보여줍니다 것입니다. 그게 무슨 뜻 이죠? 나는 스레드가 더 이상 존재하지 않거나 실행 중이 아님을 의미합니다. 누군가가 내 이해를 확인하거나 수정할 수 있습니까?

UPDATE 나는 ~ 2 초를 실행;의 Kjell 군나르 같은 킬로바이트 명령이 의견에서 제시하고 여기에 출력합니다.

0:028> ~2s;kb 
ntdll!ZwRemoveIoCompletion+0xa: 
00000000`77c1bdca c3    ret 
RetAddr   : Args to Child               : Call Site 
000007fe`fe0e16ad : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!ZwRemoveIoCompletion+0xa 
00000000`776f9991 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNELBASE!GetQueuedCompletionStatus+0x39 
000007fe`fb7f6bb1 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!GetQueuedCompletionStatusStub+0x11 
00000000`777059cd : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nativerd!NOTIFICATION_THREAD::ThreadProc+0x71 
00000000`77bfa561 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd 
00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d 

ZwRemoveIoCompletion의 의미는 무엇입니까? 당신이 볼

+0

마무리 자 스레드의 교착 상태는 매우 흔한 사고입니다.스택 트레이스를 살펴 봐야 할 것이다. –

+0

그 일을하려고했는데 스택 트레이스를보기 위해 파이널 라이저의 스레드 인덱스가 필요하지 않습니까? 아니면 다른 방법이 있습니까? 나는이 예제를 따르고 있었다. - http://dotnetdebug.net/2005/06/22/blocked-finalizer-thread/ –

+0

~ 명령을 실행하면 모든 스레드가 살아있다. 2 Id : .19e8 또는 시도하십시오 : ~ 2s; kb –

답변

1

세 첫번째 열은

  • WinDbg를 스레드 ID

    이다. 예 : ~xs 명령에서이를 사용하십시오. 여기서 x은 스레드의 ID입니다.
  • .NET 힙의 Thread 개체와 관련된 CLR 스레드 ID (!dumpheap -type Thread 및 스레드 개체의 !do을 시도한 후 m_ManagedThreadId 참조). 나는 그것을위한 실제 사용 사례를 찾지 못했다.
  • 커널 스레드 ID. 작업 관리자 또는 프로세스 탐색기

몇 가지 특수한 경우가 있으며 그 중 하나를 실행 한 것으로 보입니다. 첫 번째 열이 XXXX이면 .NET에 고정 된 물리적 OS 스레드가 할당되어 있지 않습니다. 이것은 .NET 런타임에 의해 관리되는 스레드에서 발생할 수 있습니다. 스레드 풀에서 스레드. 어느 시점에서 다시 물리적 스레드를 얻을 수 있습니다.

또한 .NET이 OS 스레드 (다음 예제의 첫 번째 줄, OS ID f28)를 기억하고 있지 않을 때 (OS ID가 0 인 두 번째 및 세 번째 줄) : 그것은 ~의 출력 (1098는 프로세스 ID이다)와 관련이 있기 때문에

XXXX 3 f28 00000087c5f974c0 80030228 Preemptive 00000087C6033180:00000087C6033FD0 00000087c4213450 0  Ukn 
XXXX 4 0 00000087c5fa24b0 39820 Preemptive 0000000000000000:0000000000000000 00000087c4213450 0  MTA 
XXXX 5 0 00000087c5fd0eb0 39820 Preemptive 0000000000000000:0000000000000000 00000087c4213450 0  MTA 

일반적으로 OS 스레드 ID가 유용하다. 하지만, 내 덤프 파일에서 ID f28와 네이티브 스레드가 없습니다 : 당신이 확인할 수 있습니다

0:009> ~ 
    0 Id: 1098.564 Suspend: 0 Teb: 000007f5`ffd3d000 Unfrozen 
    1 Id: 1098.1e98 Suspend: 0 Teb: 000007f5`ffd3b000 Unfrozen 
    2 Id: 1098.1d6c Suspend: 0 Teb: 000007f5`ffd39000 Unfrozen 
    3 Id: 1098.458 Suspend: 0 Teb: 000007f5`ffd35000 Unfrozen 
    4 Id: 1098.13d4 Suspend: 0 Teb: 000007f5`ffd33000 Unfrozen 
    5 Id: 1098.1b20 Suspend: 0 Teb: 000007f5`ffb5e000 Unfrozen 
    6 Id: 1098.80c Suspend: 0 Teb: 000007f5`ffb52000 Unfrozen 
    7 Id: 1098.944 Suspend: 0 Teb: 000007f5`ffb5c000 Unfrozen 
    8 Id: 1098.90 Suspend: 0 Teb: 000007f5`ffb5a000 Unfrozen 
. 9 Id: 1098.1738 Suspend: 0 Teb: 000007f5`ffb58000 Unfrozen 

것은 귀하의 경우 80039220로보고 스레드 상태입니다. 이것은 우리를 제공합니다

0:009> !ThreadState 80039220 
    Legal to Join 
    Background 
    CLR Owns 
    In Multi Threaded Apartment 
    Reported Dead 
    Fully initialized 
    Detached 

Reported dead은 당신의 슬픔을 확인하는 것 같다.

+0

그냥 내 이해를 위해 : .NET finalizer 스레드가 '2'OS 스레드에서 실행 된 '19e8'? 만약 교착 상태라면, OP는 여전히'19e8'의 스택 추적을 얻을 수 있어야합니까? –

+0

@LievenKeersmaekers :이 실제 스레드가 다른 작업을 위해 다시 사용 되었기 때문에 IMHO가 아닙니다. 나열된 OS 스레드가 더 이상 존재하지 않을 수도 있습니다 (본 예제에서와 같이). –

+1

@LievenKeersmaekers : 더 이상 실제 스레드가없는 .NET 스레드 스택에 액세스하는 방법에 대해서는 아직 모릅니다. 나는 그걸 알아 내려고 노력하고 있는데, 어딘가에 있어야하기 때문이다. 일반적으로 레지스터와 명령어 포인터는 커널 객체의 일부로 컨텍스트 구조에 보관되지만 여기서는 적용 할 수 없습니다. –

관련 문제