如何在CreateProcess之后防止stdout和stdin死锁

时间:2014-05-25 12:31:49

标签: c++ winapi

我对ReadFile的呼吁是僵局,我认为这是此处描述的问题:http://blogs.msdn.com/b/oldnewthing/archive/2011/07/07/10183884.aspx

不幸的是,我仍然无法使我的代码工作。我实际上并没有尝试向stdin写任何东西,但我想我必须以某种方式我没有意识到。我已经尝试创建第二个线程,但是我无法弄清楚该线程中应该进行哪些操作。

我将在下面提供我的代码。我很抱歉这里有很多,但我已经尝试将其剥离到最低限度,而且我只包含了我的流程创建代码。

我试过移动各个部分的订单,但我不能让它以任何顺序工作。该代码似乎适用于小输出,但不适用于大输出,但我需要大输出。

class STDOUT_WORK_ITEM
{
public:
    HANDLE g_hChildStd_OUT_Rd;
    std::wstringstream& ss;

    STDOUT_WORK_ITEM(HANDLE _g_hChildStd_OUT_Rd, std::wstringstream& _ss) : g_hChildStd_OUT_Rd (_g_hChildStd_OUT_Rd), ss(_ss) { };
};

unsigned int _stdcall InternalCreateProcessStdOutHelperThread (void* param)
{
    DWORD dwRead;
    char chBuf[4096] = { 0 };
    BOOL bSuccess = FALSE;

    for (;;)
    {
        bSuccess = ReadFile(reinterpret_cast<STDOUT_WORK_ITEM*>(param)->g_hChildStd_OUT_Rd, chBuf, 4096, &dwRead, NULL);
        if(!bSuccess || dwRead == 0)
            break;
        std::string temp = chBuf;
        reinterpret_cast<STDOUT_WORK_ITEM*>(param)->ss << std::wstring(temp.begin(), temp.end());
        if (dwRead < 4096)
            break;
        ZeroMemory(chBuf, dwRead);
    }
    _endthreadex(ERROR_SUCCESS);
    return ERROR_SUCCESS;
}

bool function(...)
{
    bool _return = true;

    HANDLE g_hChildStd_OUT_Rd = NULL;
    HANDLE g_hChildStd_OUT_Wr = NULL;

    STARTUPINFO         siStartupInfo;
    PROCESS_INFORMATION piProcessInfo;

    memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    memset(&piProcessInfo, 0, sizeof(piProcessInfo));

    siStartupInfo.cb = sizeof(siStartupInfo);

    LPWSTR szCmdline = _wcsdup(ExpandEnvironmentVariables(path).c_str());
    LPWSTR szParameters = _wcsdup(args.c_str());


    SECURITY_ATTRIBUTES saAttr;
    memset(&saAttr, 0, sizeof(saAttr));

    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;

    if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, NULL))
        _return = false;

    if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, NULL))
        _return = false;

    if (!_return)
    {
        CloseHandle(g_hChildStd_OUT_Rd);
        CloseHandle(g_hChildStd_OUT_Wr);
        free(szParameters);
        free(szCmdline);
        return false;
    }

    siStartupInfo.hStdError  = g_hChildStd_OUT_Wr;
    siStartupInfo.hStdOutput = g_hChildStd_OUT_Wr;
    siStartupInfo.dwFlags   |= STARTF_USESTDHANDLES;



    if(CreateProcess(szCmdline, szParameters, NULL, NULL, stdOUT != NULL ? TRUE : FALSE, CREATE_NO_WINDOW, NULL, NULL, &siStartupInfo, &piProcessInfo) == FALSE)
    {
        // Fail
    }


    WaitForSingleObject(piProcessInfo.hProcess, INFINITE);
    GetExitCodeProcess(piProcessInfo.hProcess, exit_code);


    std::wstringstream ss;

    HANDLE hStdOutWorkMutex = CreateMutex(NULL, FALSE, NULL);
    HANDLE hStdOutThread = (HANDLE)_beginthreadex(NULL, NULL, InternalCreateProcessStdOutHelperThread, &STDOUT_WORK_ITEM(g_hChildStd_OUT_Rd, ss), NULL, NULL);
    WaitForSingleObject(hStdOutThread, INFINITE);

    // Collect output from ss.str();

    CloseHandle(g_hChildStd_OUT_Rd);
    CloseHandle(g_hChildStd_OUT_Wr);

    CloseHandle(piProcessInfo.hProcess);
    CloseHandle(piProcessInfo.hThread);
    free(szParameters);
    free(szCmdline);

    return _return;
}

不幸的是,ReadFile仍然死锁。非常感谢您提供的任何帮助。

0 个答案:

没有答案