Handle leaks and CreateProcess

I finally nailed down an annoying little bug tonight. In a certain app, I’ve been calling CreateProcess() to periodically spawn a process, do some work, and shut down. Unfortunately after running several hours, the app would fail with an exception saying: insufficient quota to complete the requested service. After a fair bit of monitoring the app’s activity, I notice that the handle count of the main process, slowly and surely, kept going up. After a bit of trial-and-error, disabling modules systematically, I finally noticed that this was occurring when I spawned off the child process I mentioned.

Reading the MSDN docs for CreateProcess(), I finally got to the root of the issue; the handles returned in the PROCESS_INFORMATION struct must be closed via. CloseHandle() or the handles are kept open, even though the child process has terminated.

If the function succeeds, be sure to call the CloseHandle function to close the hProcess and hThread handles when you are finished with them. Otherwise, when the child process exits, the system cannot clean up the process structures for the child process because the parent process still has open handles to the child process.

This oversight was probably due to the fact that I was working in C# (I was P/Invoking this stuff) and lulled into a false sense of safety, thinking the garbage collector would take care of stuff like this, but from working with files, various streams, sockets, etc. I realized that C# doesn’t really close handles automatically. Now that has me thinking, why not? Wouldn’t handle management be very similar to memory management?

1 Comment

  1. Bruce Zikmund

    I wanted to thank you for helping me identify a super annoying memory leak. I recently ran into a problem where I was spawning thousands of processes using CreateProcess (one at a time) and eventually the OS would run out of kernel memory due to a handle leak. The problem was I had closed hProcess but neglected to close the hThread in the returned ProcessInformation structure. Why in the world would Microsoft bury that important detail inside the ProcessingInformation structure in MSDN documentation and not also include a WARNING it in CreateProcess()??? I checked some other utilities I had written years ago and they too had the bug. That one little documentation omission has probably resulted in numerous instances of memory leaks in Windows over the years. If it weren’t for your blog, I might have spent days trying to isolate this issue. Thanks again for taking the time to share this!