WinDbg 디버깅2007. 9. 23. 02:09
반응형

메모리릭과 마찬가지로 핸들릭도 원인을 찾기 어려운 문제중 하나입니다.

그 많은 핸들중에서 어떤 것이 릭이 발생하는 핸들인지 알아내는 것도 어렵고
도대체 어느 함수에서 그 핸들을 생성하고 닫지 않고 있는 것인지 알아내는 것도
어려운 문제입니다.

이 문제를 쉽게 풀어주는 명령어가 있으니 이것이 바로 !htrace 입니다.
XP 이후에서만 사용할 수 있고 커널모드 보다는 유저모드에서 좀 더 유용합니다.

자세한 사용법은 WinDbg Help 를 참고하시고 여기서는 사용예로 설명합니다.

일단 이 명령어는 그냥 사용할 수는 없습니다.
WinDbg Help 에는 해당 프로세스에 대해서 Application Verifier로 Detect invalid handle usage
옵션을 켜줘야 한다고 나와 있습니다. 반드시 이런 식으로 사용해야 한다면 무지 불편하겠지만
다행스럽게도 Applicaton Verifier 를 설치하지 않아도 아래와 같이 사용하면 동작합니다.

[사용예]
notepad.exe 가 핸들릭을 발생시키는 우리의 프로세스라고 가정합니다.

notepad.exe 를 실행하고 WinDbg 의 Attach Process 로 attach 합니다.
이 상태에서 !htrace 를 사용하면 다음과 같이 오류 메시지가 발생합니다.

0:001> !htrace
Handle tracing is not enabled for this process. Use "!htrace -enable" to enable it.

하지만 친절하게도 사용할 수 있는 방법을 가르쳐 주네요.
Application Verifier 없이도 -enable 옵션을 사용하면 동작합니다.

0:001> !htrace -enable
Handle tracing enabled.
Handle tracing information snapshot successfully taken.

이 때부터 사용하는 핸들은 내용 추적이 가능합니다.
g 로 진행시키고 notepad 에 몇자 적어놓고 나서 Break 를 잡습니다.

이제 !htrace 명령어를 수행하면 그동안 Open/Close 된 핸들의 정보가 나옵니다.
가장 유용한 정보는 Open/Close 가 수행된 콜스택을 보여준다는 부분입니다.
어떤 API 에 의해 Open 된 것인지 보이기 때문에 핸들의 타입을 정확히 알 수 있고
콜스택이 보이기 때문에 어떤 목적으로 어떤 행위를 하고 있었다는 것이 확인됩니다.

0:001> !htrace
--------------------------------------
Handle = 0x00000238 - CLOSE
Thread ID = 0x00000df8, Process ID = 0x00000708

0x77f56c74: ADVAPI32!RegCloseKey+0x00000076
0x3af3c261: imekr70!ImeToAsciiEx+0x00008278
0x3af3c285: imekr70!ImeToAsciiEx+0x0000829c
0x3af3b3c1: imekr70!ImeToAsciiEx+0x000073d8
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cfb89b: USER32!SendMessageWorker+0x000004a5
0x77d4b63b: USER32!SendMessageToUI+0x00000052
0x77d4c2de: USER32!ImeSetContextHandler+0x000001b8
0x77d4c6ec: USER32!ImeWndProcWorker+0x000002f4
--------------------------------------
Handle = 0x00000238 - OPEN
Thread ID = 0x00000df8, Process ID = 0x00000708

0x77f576eb: ADVAPI32!RegOpenKeyExA+0x00000119
0x3af3c232: imekr70!ImeToAsciiEx+0x00008249
0x3af3c285: imekr70!ImeToAsciiEx+0x0000829c
0x3af3b3c1: imekr70!ImeToAsciiEx+0x000073d8
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cfb89b: USER32!SendMessageWorker+0x000004a5
0x77d4b63b: USER32!SendMessageToUI+0x00000052
0x77d4c2de: USER32!ImeSetContextHandler+0x000001b8
0x77d4c6ec: USER32!ImeWndProcWorker+0x000002f4
--------------------------------------
Handle = 0x00000234 - CLOSE
Thread ID = 0x00000df8, Process ID = 0x00000708

0x746615d9: MSCTF!CCicEvent::Uninit+0x00000012
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------
Handle = 0x00000230 - CLOSE
Thread ID = 0x00000df8, Process ID = 0x00000708

0x746615d9: MSCTF!CCicEvent::Uninit+0x00000012
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------
Handle = 0x00000234 - OPEN
Thread ID = 0x00000df8, Process ID = 0x00000708

0x7c81325a: kernel32!OpenEventA+0x0000006a
0x7467d2a8: MSCTF!CCicEvent::Open+0x00000022
0x7467f672: MSCTF!HandleSendReceiveMsg+0x0000028c
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------
Handle = 0x00000230 - OPEN
Thread ID = 0x00000df8, Process ID = 0x00000708

0x7c81325a: kernel32!OpenEventA+0x0000006a
0x7467d2a8: MSCTF!CCicEvent::Open+0x00000022
0x7467f424: MSCTF!HandleSendReceiveMsg+0x0000005c
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------
Handle = 0x0000022c - CLOSE
Thread ID = 0x00000df8, Process ID = 0x00000708

0x746615d9: MSCTF!CCicEvent::Uninit+0x00000012
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------
Handle = 0x00000228 - CLOSE
Thread ID = 0x00000df8, Process ID = 0x00000708

0x746615d9: MSCTF!CCicEvent::Uninit+0x00000012
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------
Handle = 0x0000022c - OPEN
Thread ID = 0x00000df8, Process ID = 0x00000708

0x7c81325a: kernel32!OpenEventA+0x0000006a
0x7467d2a8: MSCTF!CCicEvent::Open+0x00000022
0x7467f672: MSCTF!HandleSendReceiveMsg+0x0000028c
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------
Handle = 0x00000150 - CLOSE
Thread ID = 0x00000df8, Process ID = 0x00000708

0x74661eeb: MSCTF!CCicFileMappingStatic::Close+0x00000021
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------
Handle = 0x00000228 - OPEN
Thread ID = 0x00000df8, Process ID = 0x00000708

0x7c81325a: kernel32!OpenEventA+0x0000006a
0x7467d2a8: MSCTF!CCicEvent::Open+0x00000022
0x7467f424: MSCTF!HandleSendReceiveMsg+0x0000005c
0x7467faff: MSCTF!CicMarshalWndProc+0x00000161
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
0x01002a12: notepad!WinMain+0x000000dc
0x01007511: notepad!WinMainCRTStartup+0x00000174
0x7c816fd7: kernel32!BaseProcessStart+0x00000023
--------------------------------------

...

--------------------------------------
Parsed 0xB2 stack traces.
Dumped 0xB2 stack traces.

주의할 점은 같은 핸들에 대해서 Open 되고 Close 된 것이 모두 나오기 때문에
차근차근 확인해 보셔야 합니다.

이 정보만 가지고도 많은 도움이 되지만 핸들이 닫히지 않고 계속 남아 있는 릭
상황을 확인할 때는 -diff 옵션을 사용하면 더 좋습니다.

-diff 옵션을 사용하면 -enable 을 실행할 때 snapshot 잡힌 정보와 -diff 할 때의
정보를 비교하여 닫히지 않고 열려있는 핸들만 보여줍니다. 핸들릭을 잡는 상황이면
이렇게 보여지는 핸들중에서 문제의 핸들을 찾는 것이 훨씬 쉬울 것입니다.

0:001> !htrace -diff
Handle tracing information snapshot successfully taken.
0xb2 new stack traces since the previous snapshot.
Ignoring handles that were already closed...
Outstanding handles opened since the previous snapshot:
--------------------------------------
Handle = 0x000000f4 - OPEN
Thread ID = 0x00000df8, Process ID = 0x00000708

0x7c8094b1: kernel32!CreateFileMappingA+0x0000006e
0x746657f3: MSCTF!CSharedBlockNT::Init+0x00000147
0x746949f9: MSCTF!CSharedHeap::Init+0x00000072
0x74694b22: MSCTF!EnsureSharedHeap+0x0000004a
0x74680357: MSCTF!CProxy::proxy_Param+0x00000031
0x74680ec5: MSCTF!CProxyITfLangBarItemSink::OnUpdate+0x0000003c
0x7467cd8f: MSCTF!CLangBarItemMgr::OnUpdateHandler+0x00000036
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
0x77cf8a10: USER32!DispatchMessageW+0x0000000f
--------------------------------------
Handle = 0x000000cc - OPEN
Thread ID = 0x00000df8, Process ID = 0x00000708

0x7c80e98b: kernel32!CreateMutexA+0x00000065
0x7466245b: MSCTF!CCicMutex::Init+0x00000016
0x74664b22: MSCTF!CSharedBlockNT::Init+0x000000c5
0x746949f9: MSCTF!CSharedHeap::Init+0x00000072
0x74694b22: MSCTF!EnsureSharedHeap+0x0000004a
0x74680357: MSCTF!CProxy::proxy_Param+0x00000031
0x74680ec5: MSCTF!CProxyITfLangBarItemSink::OnUpdate+0x0000003c
0x7467cd8f: MSCTF!CLangBarItemMgr::OnUpdateHandler+0x00000036
0x77cf8734: USER32!InternalCallWinProc+0x00000028
0x77cf8816: USER32!UserCallWinProcCheckWow+0x00000150
0x77cf89cd: USER32!DispatchMessageWorker+0x00000306
--------------------------------------
Displayed 0x2 stack traces for outstanding handles opened since the previous snapshot.

두 개의 핸들이 계속 남아 있었음을 보이고 있습니다.
하나는 파일맵핑 핸들이고 하나는 뮤텍스 핸들이네요.

이제 콜스택을 잘 보면서 어떤 목적으로 열어놓은 핸들인지 확인하고 이것을 왜 닫지 않는지
소스코드를 보면서 문제의 원인을 찾으면 됩니다.

좀 더 시간이 있었으면 예제를 만들어서 보기 좋게 보여드렸을 텐데 요즘 시간이 녹녹치 않네요. ^^
복잡하지만 활용하실 수 있을 정도만 적어 봤습니다. 모두에게 도움이 되시기 바랍니다.

http://www.driveronline.org/bbs/view.asp?tb=tipbbs&GotoPage=1&s_bulu=&s_key=&no=92

반응형
Posted by GreeMate