odd handle leak
Asked Answered
P

3

13

My application (base application is MFC interop with C++/CLI but it also contains a lot of C#, Windows Forms, WPF) has has a handle leak. Shortly after application start I can see the handle count in the task manager grow continuously (at a rate of 10 new handles per second). So I used handles.exe to see what kind of handles they are. I found out that the leaking handles are process handles. And they are process handles to the process of my application.

So I wonder what operations would typically create a handle to the process it runs in. Any idea? Have you ever seen something like this? What else could I do to track down the leak, considering that I can't use debug DLLs and that I can only use tools that can be xcopy deployed.

Update:

I was able to throw windbg and !handle, !htrace at it and found out that the process handles are all created using the following stack traces (ordered by frequency):

0x79f7570b: mscorwks!CorExitProcess+0x00022055
0x79f03edd: mscorwks!GetPrivateContextsPerfCounters+0x0000b6fe
0x79f04b87: mscorwks!GetPrivateContextsPerfCounters+0x0000c3a8
0x79f04b03: mscorwks!GetPrivateContextsPerfCounters+0x0000c324
0x79f919bf: mscorwks!CorExitProcess+0x0003e309
0x79f91b28: mscorwks!CorExitProcess+0x0003e472
0x792d6b4c: mscorlib_ni+0x00216b4c
0x1391a663: +0x1391a663
0x1391a0b1: +0x1391a0b1
0x7a9ea544: System_ni+0x005aa544
0x792a842f: mscorlib_ni+0x001e842f

or

0x7c8106f5: kernel32!CreateThread+0x0000001e
0x79f04bb2: mscorwks!GetPrivateContextsPerfCounters+0x0000c3d3
0x79f04b03: mscorwks!GetPrivateContextsPerfCounters+0x0000c324
0x79f919bf: mscorwks!CorExitProcess+0x0003e309
0x79f91b28: mscorwks!CorExitProcess+0x0003e472
0x792d6b4c: mscorlib_ni+0x00216b4c
0x1391a663: +0x1391a663
0x1391a0b1: +0x1391a0b1
0x7a9ea544: System_ni+0x005aa544
0x792a842f: mscorlib_ni+0x001e842f

or

0x08ec2eba: +0x08ec2eba
0x792b8277: mscorlib_ni+0x001f8277
0x792b8190: mscorlib_ni+0x001f8190
0x792b8040: mscorlib_ni+0x001f8040
0x792b7ff2: mscorlib_ni+0x001f7ff2
0x677e48f3: System_Runtime_Remoting_ni+0x000748f3
0x677e44be: System_Runtime_Remoting_ni+0x000744be
0x677e46ec: System_Runtime_Remoting_ni+0x000746ec
0x677e8408: System_Runtime_Remoting_ni+0x00078408
0x7926eb8d: mscorlib_ni+0x001aeb8d

Now what does that tell me?

Plum answered 21/4, 2011 at 6:18 Comment(13)
Does it continue growing? I.e. is it truly a leak or just the runtime starting up?Salisbarry
It continues to grow up to several million handles until it eventually crashes.Plum
Could it be an external application creating the handles (such as anti-spyware or antivirus?)Salisbarry
Is that even possible? How can one process affect the handles of another process? It runs Avira Antivir but when disabling it the same issue is still present, even when I restart the application.Plum
Hard to believe this is accurate. .NET has no use for process handles beyond the Process class. The handle returned by GetCurrentProcess() Windows API is a pseudo handle with the value -1. Debug your code to narrow down the call that increments the handle count, you've got good feedback.Iodoform
@Hans: There is also a lot of MFC, C++ code in it. It is only happening on one machine all others are fine where the app is running. That machine only has release DLLs and can only run xcopy-deployed tools.Plum
Well, that's an environmental problem. A debugger can show you what kind of crapware gets loaded into your process. Greasy fingers while you hold the machine out of a 4th story window is another solution.Iodoform
I have updated my question with some more information. Any clues? It seems that .NET infact DOES have use for process handles since all three stacktraces are purley CLR realted.Plum
If you look at your process in Process Explorer you can get a list of handles and their values. Maybe if you identify what the handles represent you will get an idea what might be leaking them.Stagecoach
What about the managed code callstacks? Try to use the !clrstack (available in the SOS debugger extension) and see if they give you a clue about here these handles are being created. EDIT: I don't know you'll be able to get the managed callstack directly from the handles but you could nevertheless put for example breakpoints in the kernel32!CreateThread or kernel32!CreateProcessEx functions and get the managed stack from thereAmphibolite
@bitbonk: Have you tried setting a breakpoint at OpenProcess? Does it ever get hit?Bullpup
When the app finally crashes, do you have an exception handler or a message in the event log? That might give you a little more infoSeften
@Amphibolite I suppose those callstacks don't show any of my code because !htrace always shows the unmanaged callstack only, leaving out the managed part? So the callstack is actually much longer?Plum
M
5

The call stacks look wrong. Did you setup the symbol server correctly? .symfix should do the trick in Windbg. Afterwards you should get a better stacktrace.

It looks like part of the code that has this problem is managed so it would make sense to break on DuplicateHandle and OpenProcess and dump the managed call stack there. These two methods are the only ones which could produce a real process handle.

You can declare a breakpoint like this and execute commands when the breakpoint is hit. In this case the managed stack is printed and then the execution does continue.

bp kernel32!OpenProcess "!ClrStack;g"
Madeline answered 8/5, 2011 at 20:30 Comment(1)
The number after the method is very high. No method is longer than a few hundred bytes. If you see offsets in the thousands or more it is a sure sign that you have got wrong or missing symbols. The debugger uses as fall back then the nearest exported method of the module to display at least something.Madeline
V
1

Had same issues with a webservice calling COM objects through interop.

I solved this by explicitely calling Marshal.ReleaseComObject against the interop objects I created. No issues after that moment for me.

Hope it helps.

Vinous answered 7/5, 2011 at 14:17 Comment(0)
B
0

So... are you doing performance counters explicitely (if so, try disabling them to narrow down on the source of the leaks).

Bedspring answered 7/5, 2011 at 14:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.