Windbg 를 이용한 Handle leak 찾기

Windbg 를 사용할 경우 !handle 명령을 사용하여 현재 Process 내의 모든 Handle 정보를 확인할 수 있습니다. 이는 Process explorer 를 사용하는 방법과 동일하지만 Process Explorer 에서는  어떤 Handle 이 생성되어 있는지는 확인할 수 있으나 어떤 함수를 통해서 Handle 이 생성되었는지는 알 수 없습니다. 이때 gflags.exe 에서 Object 관련 값을 설정하면 좀더 많은 정보를 확인할 수 있습니다.

Handle leak 이 의심되는 프로그램을 실행시킨 후 WinDbg 를 실행시켜 Attach 시킵니다. 그리고 “!htrace –enable” 명령을 실행하면 간단하게 Handle 이 생성되는 함수가 무엇인지 call stack 을 저장할 수 있습니다.

0:000> !htrace -enable

Handle tracing enabled.

Handle tracing information snapshot successfully taken.

Handle leak 이 의심되는 동작을 하기 전 “!htrace –snapshot” 명령을 수행하여 현재 Handle 정보의 snapshot을 저장한 후 Handle leak 이 의심되는 동작을 한 후 “!htrace -diff” 명령을 실행하면 snapshot 을 설정한 이후 Open Close 되는 모든 Handle 정보를 확인할 수 있습니다. Handle 이 Process, Thread 정보와 함께 Call stack 이 출력되어 어떠한 함수 경로를 통해 Handle 이 Open 되고 Close 되는지 확인할 수 있습니다.

Event 를 생성해서 대기하는 예제를 실행 시키고 WinDbg 를 Attach 시킨 후 “!htrace –enable” 명령을 사용하여 Handle 에 대한 trace 를 enable 시킨 후 Event 를 생성한 후 “!htrace -diff" 명령을 사용하면 다음과 같이 새로운 Event Handle 이 생성된 것을 확인할 수 있습니다.

0:001> !htrace -diff

Handle tracing information snapshot successfully taken.

0x1a7 new stack traces since the previous snapshot.

Ignoring handles that were already closed...

Outstanding handles opened since the previous snapshot:

--------------------------------------

Handle = 0x00000280 - OPEN

Thread ID = 0x00001e10, Process ID = 0x00000d0c

0x7c81bd9f: kernel32!CreateEventA+0x00000022

0x00412d06: ProcessHangApp!CProcessHangAppDlg::OnBtnHung+0x00000036

0x786a75a2: mfc90d+0x000c75a2

0x786a7cea: mfc90d+0x000c7cea

0x7867da93: mfc90d+0x0009da93

0x786408b4: mfc90d+0x000608b4

0x7863f529: mfc90d+0x0005f529

0x7863f462: mfc90d+0x0005f462

0x7863c8e0: mfc90d+0x0005c8e0

0x7863cea6: mfc90d+0x0005cea6

--------------------------------------

Displayed 0x1 stack traces for outstanding handles opened since the previous snapshot.

 

Event 를 생성한 함수를 살펴 보도록 하겠습니다.

0:001> lsa ProcessHangApp!CProcessHangAppDlg::OnBtnHung

170: return (HCURSOR) m_hIcon;

171: }

172:

173: void CProcessHangAppDlg::OnBtnHung()

> 174: {

175: // NAMED EVENT »ý¼º(¾ò±â)

176: HANDLE hNmdEvent = CreateEvent(NULL, // security attribute

177: FALSE, // manual reset

178: TRUE, // signaled

179: _T("Win32UserDebug"));

 

Handle 280

Type Event

Attributes 0

GrantedAccess 0x1f0003:

Delete,ReadControl,WriteDac,WriteOwner,Synch

QueryState,ModifyState

HandleCount 2

PointerCount 4

Name \BaseNamedObjects\Win32UserDebug

Object Specific Information

Event Type Auto Reset

Event is Waiting