Search code examples
c++windowshandlecreateprocessresource-leak

Why do I leak exactly two handles when calling CreateProcess multiple times or just once?


According to GetProcessHandleCount I'm losing two handles when calling CreateProcess. Please look at the following minimal example, which will create one child-process. Before creating the child-process, the number of handles are examined. Then the child-process handles returned in the PROCESS_INFORMATION structure are closed, and then the handles are counted again. I get a difference of 2 handles - has anyone an idea why?

Also interesting: If I create multiple child-processes within the for-loop in the sample below, I also "leak" exactly two handles.

Edit: Please note that in the StartupInformation Structure no handles are returned, so there is nothing to close there.

Can someone explain to me this difference of two handles?

#include <windows.h>
#include <tchar.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
    std::wstring commandLine = L"C:\\windows\\system32\\cmd.exe";

    BOOL closedHT = FALSE;
    BOOL closedHP = FALSE;
    BOOL createdProcess = FALSE;

    // Count handles before creating child processes:
    HANDLE hCurrent = GetCurrentProcess();
    DWORD hCountBefore = 0;
    ::GetProcessHandleCount(hCurrent, &hCountBefore);

    // Create one child-processes:
    for (size_t i = 0; i < 1; i++)
    {
        STARTUPINFO startupInfo;
        ::ZeroMemory(&startupInfo, sizeof(startupInfo));

        PROCESS_INFORMATION procInfo;
        ::ZeroMemory(&procInfo, sizeof(procInfo));

        createdProcess = ::CreateProcess(NULL, (LPWSTR)commandLine.c_str(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, &procInfo);
        closedHP = ::CloseHandle(procInfo.hProcess);
        closedHT = ::CloseHandle(procInfo.hThread);
    }

    // And calculate the difference of handles:
    DWORD hCountAfter = 0;
    ::GetProcessHandleCount(hCurrent, &hCountAfter);
    DWORD diff = hCountAfter - hCountBefore;

    if (createdProcess && closedHP && closedHT && diff != 0)
    {
        std::wcout << L"lost handles??: " << diff << std::endl;
    }
    else
    {
        std::wcout << L"Nothing got lost" << std::endl;
    }

    return 0;
}

Solution

  • UKMonkey is right, it will load apphelp.dll which will open two handles:

    See the following two screenshots, showing the dlls and handles loaded / opened:

    DDLs and handles before calling CreateProcess

    DLLS and handles after calling CreateProcess

    Loading the dll itself by calling LoadLibrary will open the handle to the SESSION MANAGER, calling CreateProcess the first time will open the handle to Custom Locale.