Understanding handle leaks and how to use !htrace to find them

Sign in to queue

Description

Hello, my name is Jeff Dailey, I’m an Escalation Engineer for the Global Escalation Services Platforms team.   I’d like to show you how to debug and find leaking handles within your application or other process.  We can do this with the !htrace command in windbg .  Windbg is the Microsoft Windows Debugger most of us use in GES/CPR  for debugging.   

 

Handles are a value we use in user mode, that when passed to a call that transitions to kernel, are used as an offset in your handle table to reference kernel mode objects.  Kernel mode objects are generally allocated from pool.   If you are having pool consumption problems and seeing errors like 2020 or 2019’s reported there is a good chance you may have a handle leak associated with them.  This is generally due to not doing a CloseHandle() on the handle when you have finished using it.

 

The following is the sample source for a handle leak that we will be debugging in our demo video.

 

// leakyhandles.cpp : Defines the entry point for the console application.

//

 

#include "stdafx.h"

#include <windows.h>

 

 

void fun1(void);

void fun2(void);

void fun3(void);

void fun4(void);

 

int main(int argc, char* argv[])

{

      while(1)

      {

            fun1();

            fun2();

            Sleep(100);

      }

      return 0;

}

 

void fun1(void)

{

      fun3();

}

 

void fun2(void)

{

      fun4();

 

}

void fun3(void)

{

      HANDLE hEvent;

 

      hEvent = CreateEvent(NULL,TRUE,TRUE,NULL);

      CloseHandle(hEvent);

}

void fun4(void)

{

    HANDLE hEvent2;

 

      hEvent2 = CreateEvent(NULL,TRUE,TRUE,NULL);

}

 

Thank you.

Jeff Dailey

Escalation Engineer (Platforms core team)

Embed

Download

Download this episode

The Discussion

  • User profile image
    jigarmehtam​scit

    Seems like the CHM which you have shown comes with MS confidential (private) version of windbg...

    (though there is not much difference in the page thats shown!)

    But thanks for taking initiative and start giving nice small tutorials on debugging with windbg..

  • User profile image
    dcook
    For the record, the "internal" version is essentially used for communication between the people maintaining the CHM. It doesn't have any "secrets" in it -- just boring stuff like "this needs to be cleaned up" or "can you check with Bob to see if there is an easier way to do this". Tongue Out
  • User profile image
    vve
    Thanks Jeff!

    Hope to see more of those trainings in future...

    Cheers,
    Volker

    http://www.voneinem-windbg.blogspot.com/
  • User profile image
    MythTW

    i have tried for several times to watch this video, but every time after it played about 1 or 2 mins, it just stopped...

    i have no way to finish watching the video, is there anyway i can do about it?? my bandwidth is 12mb download/1mb upload, so it's not a bandwidth problem.

    is there anyway i can download the video or just think a way to help me be able to watch it....

  • User profile image
    MythTW
    ha, using a tool, i can download the wmv file and finally be able to watch it.
    Going to play with this method on my machine now...
    thanks for the tutorial..
  • User profile image
    sang

    I am alos not able to watch the video ....which tool helped to donwload wmv...?

  • User profile image
    c0decafe

     

    You can click on the "Formats:" drop-down and in the list, right-click the WMV and choose "Save-As". At least that worked for me. This was the direct link from that:

    http://mschnlnine.vo.llnwd.net/d1/ch9/1/2/6/7/5/2/341851_leakyhandles.wmv

  • User profile image
    anonymous

    Hi, that video was very helpful, thanks for that Jeff. And thanks to c0decafe for the download link.

  • User profile image
    adrian.h

    This is interesting, but seems that the stack depth is limited which doesn't help me.  I need a deeper stack to be able to see what my code is doing, because the handles are being allocated in some other library and that is going through several levels of indirection within the system dlls.  Here are 2 examples:

    Handle = 0x000000000000231c - OPEN
    Thread ID = 0x0000000000006ab8, Process ID = 0x00000000000067c0

    0x00007ffbd64720aa: ntdll!NtTraceControl+0x000000000000000a
    0x0000000076eb8953: wow64!whNtTraceControl+0x0000000000000143
    0x0000000076eba45b: wow64!Wow64SystemServiceEx+0x00000000000000fb
    0x0000000076f01dc5: wow64cpu!ServiceNoTurbo+0x000000000000000b
    0x0000000076ec21aa: wow64!RunCpuSimulation+0x000000000000000a
    0x0000000076ec20e2: wow64!Wow64LdrpInitialize+0x0000000000000172
    0x00007ffbd64a3cf5: ntdll!LdrpInitializeProcess+0x0000000000001591
    0x00007ffbd648245e: ntdll!_LdrpInitialize+0x000000000008977e
    0x00007ffbd63f8c8e: ntdll!LdrInitializeThunk+0x000000000000000e
    0x0000000076f4dcec: ntdll_76f10000!NtTraceControl+0x000000000000000c
    0x0000000076f72a5c: ntdll_76f10000!EtwpRegisterProvider+0x00000000000000ad
    --------------------------------------
    Handle = 0x000000000000228c - OPEN
    Thread ID = 0x0000000000006ab8, Process ID = 0x00000000000067c0

    0x00007ffbd647173a: ntdll!NtOpenKeyEx+0x000000000000000a
    0x0000000076ebb5ea: wow64!whNtOpenKeyEx+0x00000000000000ea
    0x0000000076eba45b: wow64!Wow64SystemServiceEx+0x00000000000000fb
    0x0000000076f01dc5: wow64cpu!ServiceNoTurbo+0x000000000000000b
    0x0000000076ec21aa: wow64!RunCpuSimulation+0x000000000000000a
    0x0000000076ec20e2: wow64!Wow64LdrpInitialize+0x0000000000000172
    0x00007ffbd64a3cf5: ntdll!LdrpInitializeProcess+0x0000000000001591
    0x00007ffbd648245e: ntdll!_LdrpInitialize+0x000000000008977e
    0x00007ffbd63f8c8e: ntdll!LdrInitializeThunk+0x000000000000000e
    0x0000000076f4d37c: ntdll_76f10000!NtOpenKeyEx+0x000000000000000c
    0x000000007624470f: KERNELBASE!LocalBaseRegOpenKey+0x00000000000000ff
    0x00000000762448d7: KERNELBASE!RegOpenKeyExInternalW+0x0000000000000137
    0x000000007624495c: KERNELBASE!RegOpenKeyExW+0x000000000000001c

    How do I go deeper?

  • User profile image
    adrian.h

    Oh, also, this doesn't seem to work for GDI handles and gflags doesn't seem to have an option for that either.  Am I correct in my assessment?  If so, can this be corrected?

Add Your 2 Cents