류짱:Beyond MySelf

Testlimit.exe를 이용한 Handle leak 테스트 본문

Microsoft/Windows Platform

Testlimit.exe를 이용한 Handle leak 테스트

リュちゃん 2011. 12. 1. 00:25

최근 몇일 사이 Windows server 2008과 2003 에서 특정 프로세의 handle Leak으로 시스템의 성능이 매우 느려진 사례가 있었습니다. 

물론 다른 여러 현상에 의해서 성능 이슈가 발생 할 수 있기는 하지만 시스템의 성능 이슈가 발생하면 언제나 가장 먼저 확인 해 봐야 하는 것이 작업 관리자에서 『커널 메모리(kernel memory)』부분과 『Handle(핸들)』 부분이 아닌가 생각합니다.
 x86의 시스템에 발생하는 시스템 hang이나 성능 이슈의 대부분은 커널 리소스 문제 부족 때문이었으며 이 것을 가장 빨리 확인 해 볼 수 있는 방법이 작업 관리자의 커널 리소스를 확인 해 보는 것입니다. 물론 x64 머신의 경우에도 성능 이슈가 느껴진다면 이 부분을 확인 해 볼 필요가 있습니다^^

관련해서 최근 발생한 프로세스의 handle leak 현상을 testlimit.exe 프로그램을 이용해서 재현을 해 보았습니다.
먼저 정상적인 시스템의 작업 관리자를 보면 아래와 같이 커널 리소스의 사용량이 얼마 되지 않습니다.
handles -> 5539
Paged pool -> 10616kb / Nonpaged pool 89222kb입니다
.

자 이제 Testlimit.exe라는 tool을 이용해서 해당 시스템에 handle leak을 유발 해 보도록 하겠습니다.먼저 아래 파일을 다운로드 합니다.
testlimit.exe  다운로드
http://download.sysinternals.com/Files/Testlimit.zip

위 링크를 통해 다운 받은 파일의 압축을 해제 후  C:\ 루트에 copy를 하였습니다.  그리고는 아래와 같은 명령프롬프트를 실행 후  명령어를 실행 합니다.

맨 마지막에 부여한 -c 옵션은 실제 생성할 핸들 수를 지정 하는 옵션입니다 .이 옵션을 사용하지 않을 경우에는 시스템에서 핸들을 생성 할 수 있을 때 까지 계속 생성합니다.

C:\>Testlimit.exe -h -u -c 1000000      // 백만개의핸들을 생성 합니다.
Testlimit v5.04 - test Windows limits
By Mark Russinovich - www.sysinternals.com

Creating handles...
Created 1000000 handles. Lasterror: 0
The operation completed successfully.


** 옵션에 대한 자세한 설명은 testlimit.exe /?  실행 하신 후 확인 할 수 있습니다
 -a       Leak Address Windowing Extensions (AWE) memory in
          specified MBs (default is 1).
 -c       Count of number of objects to allocate (default is as many as possible).
            This must be the last option specified.
 -d       Leak and touch memory in specified MBs (default is 1).
 -g       Create GDI handles of specified size (default 1 byte).
          Specify a size of 0 to cause GDI object exhaustion.
 -h       Create handles. Specify -u to also allocate file objects.
 -i       Exhaust USER desktop heap.
 -l       VirtualLock memory in specified MBs (default is 1).
 -m       Leak memory in specified MBs (default is 1).
 -p       Create processes - add -n to set min working set. Add -n to
          set min working set of processes to smallest.
 -r       Reserve memory in specified MBs (default is 1).
 -s       Leak shared memory in specified MBs (default is 1).
 -t       Create threads - add -n to specfy minimum stack reserve (in KB).
 -u       Create USER handles to menus.
 -w       Reset working set minimum to highest possible value.

위 명령어 실행 후 작업 관리자를 확인 하면 아래와 같이 hanldes와 paged pool 그리고 nonpaged pool의 사이즈가 현격하게 변화 된 것을 확인 할 수 있습니다.

핸들의 수가 백만개가 늘었으며 커널 리소스 또한 많이 상승이 되었습니다.

실제 어떤 프로세스가 많은 핸들을 open 한 것인지 확인하기 위해 아래와 작업관리자의 메뉴에서 [보기 ]-> [컬럼 선택]을 클릭 합니다. 

컬럼을 선택하는 화면이 팝업 되면 아래와 같이 핸들 카운터 (Handle count) 체크 박스에 체크를 합니다.

그리고 프로세스 탭을 선택 한 후  핸들(handles) 를 클릭하여 가장 많은 handle을 open한  프로세스를 확인 합니다.
Cmd를 통해서 실행한 testlimit.exe 프로세스가 오픈한 핸들이 1,000,018  임을 확인 할 수 있습니다.


만약 해당 서버에 Windows debugging tool이 설치 되어 있고  로컬 커널 디버깅을 실행 할 수 있는 상태라면  아래와 같이 커널 리소스를 추가로 상세하게 확인 할 수 있습니다.

*심볼을  fix 한 후 reload 한 후 아래 명령어를 실행 합니다. 

lkd> !vm 1  -> nonpaged pool과 paged pool의 현재 사용량과 최대 값을 확인 합니다.

*** Virtual Memory Usage ***
 Physical Memory:      262008 (   1048032 Kb)
 Page File: \??\C:\pagefile.sys
   Current:   1572864 Kb  Free Space:   1565416 Kb
   Minimum:   1572864 Kb  Maximum:      3145728 Kb
 Available Pages:      139839 (    559356 Kb)
 ResAvail Pages:       200212 (    800848 Kb)
 Locked IO Pages:         114 (       456 Kb)
 Free System PTEs:      51647 (    206588 Kb)
 Free NP PTEs:           2779 (     11116 Kb)
 Free Special NP:           0 (         0 Kb)
 Modified Pages:          541 (      2164 Kb)
 Modified PF Pages:       541 (      2164 Kb)
 NonPagedPool Usage:    49084 (    196336 Kb) // Nonpaged pool의 현재 사용량
 NonPagedPool Max:      51960 (    207840 Kb)
// Nonpaged pool의 최대 값
 ********** Excessive NonPaged Pool Usage *****  // Nonpaged pool이 거의 다 소진 되었음을 확인 할 수 있음

 PagedPool 0 Usage:      3711 (     14844 Kb)
 PagedPool 1 Usage:     17391 (     69564 Kb)
 PagedPool 2 Usage:     16942 (     67768 Kb)
 PagedPool Usage:       38044 (    152176 Kb)
 PagedPool Maximum:     70656 (    282624 Kb)
 Session Commit:          160 (       640 Kb)
 Shared Commit:          2196 (      8784 Kb)
 Special Pool:              0 (         0 Kb)
 Shared Process:         2257 (      9028 Kb)
 PagedPool Commit:      38051 (    152204 Kb)
 Driver Commit:          1238 (      4952 Kb)
 Committed pages:       98775 (    395100 Kb)
 Commit limit:         632325 (   2529300 Kb) 

lkd> !poolused /t5 2 ->nonpaged pool을 가장 많이 사용한  top 5 pool tag 확인
Sorting by NonPaged Pool Consumed

Pool Used:
NonPaged Paged
Tag Allocs Used Allocs Used
File 1001336 152203760 0 0 File objects  --> File 이라는  tag가  약 150M 이상의 nonpaged pool을 사용함
LSwi 1 2576384 0 0 initial work context
TCPt 29 1422336 0 0 TCP/IP network protocol , Binary: TCP
MmCm 11 581904 0 0 Calls made to MmAllocateContiguousMemory , Binary: nt!mm
LSwr 128 416768 0 0 raw work context
TOTAL 1020161 161159168 2029611 155126792

lkd> !process 0 0 testlimit.exe //
PROCESS 85933d88  SessionId: 1  Cid: 06a4    Peb: 7ffd4000  ParentCid: 0410
    DirBase: 3c1e6380  ObjectTable: e11ef3a0  HandleCount: 1000018.
    Image: Testlimit.exe

실제 수백만개의 핸들이 오픈 되고 커널 리소스가 부족 해진 상황에서는 작업 관리자를 확인 하는 것 조차 어려울 수 도 있습니다만 만약에라도 확인이 가능 한 상태라면 반드시 커널 리소스와 핸들을 반드시 먼저 확인 해 보시기 바랍니다.

[참고 자료]
Pushing the Limits of Windows: Handles
http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx

Understanding Pool Consumption and Event ID: 2020 or 2019
http://blogs.msdn.com/b/ntdebugging/archive/2006/12/18/understanding-pool-consumption-and-event-id_3a00_--2020-or-2019.aspx

감사합니다.