HowTo: Track down a handle leak in your code – trace the stacks



Hi


 


This is also a test in posting images in my blog .. 


 


 


In this scenario you may have  noticed a handle leak in an application  via perfmon using the Process counters:


 



 


 


Or simply via Task Manager :


 


 



 


Once you know which process is leaking handles you can approach it in a more direct manner. Depending on the code size it may be easy to track down where the bug is, but in my case .. the OS is a pretty big piece of code to try and find the leak without some help. I suppose I could set a break on access for the handle table and log the stacks everytime we increment the count, but that could get ugly.


 


I think this would be easier…





Download and install Application verifier


 


 Configure it to track handles:


 


 



 


Let the application run for a bit – presumably leaking like a sieve.


 


Attach the debugger to the process, and make sure you have good symbols. For this example I used the Microsoft public symbols server:


 


0:005> .sympath


Symbol search path is: SRV*c:\symbols*http://msdl.microsoft.com/download/symbols


 


 


0:005> !htrace


————————————–


Handle = 0x000001A6 – CLOSE


Thread ID = 0x000008B4, Process ID = 0x00000564


 


0x77DA2DDC: ADVAPI32!BaseRegCloseKeyInternal+0x0000004F


0x77DA2D8D: ADVAPI32!RegCloseKey+0x00000075


0x7738D531: SHELL32!CDrivesFolder::_FillIDDrive+0x0000007F


0x7738EF07: SHELL32!CDrivesFolder::ParseDisplayName+0x00000088


0x7738D68A: SHELL32!CRegFolder::ParseDisplayName+0x0000007A


0x7738ECC0: SHELL32!CDesktopFolder::_ChildParseDisplayName+0x00000020


0x7738EC00: SHELL32!CDesktopFolder::ParseDisplayName+0x0000007C


0x7738D68A: SHELL32!CRegFolder::ParseDisplayName+0x0000007A


0x773916AC: SHELL32!SHSimpleIDListFromFindData+0x00000077


0x773917A1: SHELL32!SHGetFileInfoW+0x0000011C


0x762B205A: comdlg32!GetFileTitleX+0x0000007A


 


<snip>


 


0x77DA2DDC: ADVAPI32!BaseRegCloseKeyInternal+0x0000004F


0x77DA2D8D: ADVAPI32!RegCloseKey+0x00000075


0x772B3440: SHLWAPI!CAssocShellElement::SetString+0x00000055


0x77395956: SHELL32!CAssocArray::_GetElement+0x0000003B


0x77395C53: SHELL32!CAssocArray::_FirstElement+0x00000016


0x773996EA: SHELL32!CFileSysItemString::AssocCreate+0x0000009C


0x773F7DA9: SHELL32!CFileSysItemString::_ClassFlags+0x00000060


0x7738E11B: SHELL32!CFileSysItemString::GetJunctionClsid+0x0000007B


0x7738FDAC: SHELL32!CFSFolder::GetAttributesOf+0x00000273


0x762B348E: comdlg32!SHGetAttributes+0x00000051


0x762B5D5F: comdlg32!CFileOpenBrowser::IncludeObject+0x0000005C


————————————–


Handle = 0x000005DC – OPEN


Thread ID = 0x000008B4, Process ID = 0x00000564


 


0x77DA4985: ADVAPI32!BaseRegOpenClassKeyFromLocation+0x0000011A


0x77DA4873: ADVAPI32!BaseRegOpenClassKey+0x0000005F


0x77DA4D60: ADVAPI32!LocalBaseRegOpenKey+0x000000E4


0x77DA1949: ADVAPI32!RegOpenKeyExW+0x0000010B


0x5A61ABD0: verifier!AVrfpRegOpenKeyExW+0x00000060


0x772B3305: SHLWAPI!CRegistrySource::Init+0x0000003A


0x772B32B7: SHLWAPI!QuerySourceCreateFromKey+0x0000004F


0x77298F1A: SHLWAPI!CAssocProgidElement::_InitSource+0x00000073


0x772B3440: SHLWAPI!CAssocShellElement::SetString+0x00000055


0x77395956: SHELL32!CAssocArray::_GetElement+0x0000003B


————————————–


Handle = 0x00000600 – CLOSE


Thread ID = 0x000008B4, Process ID = 0x00000564


 


0x77DA4E2A: ADVAPI32!BaseRegConstructUserClassPrefix+0x0000005C


0x77DA4DEC: ADVAPI32!BaseRegTranslateToUserClassKey+0x00000020


0x77DA4901: ADVAPI32!BaseRegOpenClassKeyFromLocation+0x00000084


0x77DA4873: ADVAPI32!BaseRegOpenClassKey+0x0000005F


0x77DA4D60: ADVAPI32!LocalBaseRegOpenKey+0x000000E4


0x77DA1949: ADVAPI32!RegOpenKeyExW+0x0000010B


 


————————————–


Parsed 0x892 stack traces.


Dumped 0x892 stack traces


 


 


If you are doing this from Kernel, you specify the process and you will see the stacks reflect the calls to the Object Manager to open and close the handles.


 


NOTE: if you cant do a live debug you can get a kernel dump of the machine and it will contain the stacks.  A user mode dump will not have the stack data.


 


 


Now, unfortunately there is no snap comparison tool like UMDH to compare and log the ‘bad stacks’ but it wouldnt be too hard to do this when you look at unmatched opens.


 


I am pretty sure this only works on XP and greater…


 


July 17 2005- added this:


Looks like its user mode only..


———————————————————


!htrace -enable

!htrace -snapshot
… leak code
!htrace -diff
———————————————————


 


Hope it helps someone one day ;o)


 


 


Spat


 


 


Additonal random posts I found interesting this morning:


New Rootkit Revealer available!


Why does the debugger show me the wrong virtual function?


HOWTO: Setup for SmartPhone Development (UPDATED)


Ourmedia.org and Brightcove: 2 sides of the broadband content coin – this one is pretty cool. I may try to host some video here soon. 


 



 [ edit — guess that didnt work so well eh? I’ll try to fix it in a bit — tips from anyone else on how to do this? :: UPDATE – looks like it did work after all]


 

Comments (2)

  1. silvstedt victoria says:

    Very good!!! 🙂

    silvstedt victoria

  2. David says:

    I have a serious handle leak in "System". Can you assist me from this point?

    Thanks