Win32的ReadFile的从管道读取时挂起(Win32 ReadFile hangs when

2019-07-04 23:01发布

我创建一个子进程,并读取其输出。 当子进程创建输出(我的代码工作正常, cmd /c echo Hello World ),但是ReadFile的将挂起,如果过程不产生输出( cmd /c echo Hello World > output.txt )。 进程终止后我只读书。

我做什么可怕的错误? 反正是有与同步模式要做到这一点,或者我必须使用异步模式? 所有这一切是发生在一个单独的线程,所以我不认为异步模式将提供任何好处给我,除非是为了得到这个工作的唯一途径。 非常感谢!

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

CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0);
SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0);

memset(&piProcInfo, 0, sizeof(PROCESS_INFORMATION));
memset(&siStartInfo, 0, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO); 
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess(NULL, commandWideString, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);

while(1)
{
    GetExitCodeProcess(piProcInfo.hProcess, &processExitCode);
    if(processExitCode != STILL_ACTIVE)
        break;
    else
        Sleep(1);
}

*output = (char *)calloc(32, sizeof(char));
processOutputSize = 0;
while(1)
{
    bSuccess = ReadFile( g_hChildStd_OUT_Rd, processOutputTemp, 32, &dwRead, NULL);
    if(!bSuccess || !dwRead)
        break;
    memcpy(*output + processOutputSize, processOutputTemp, dwRead);
    processOutputSize += dwRead;
    if(dwRead == 32)
        *output = (char *)realloc(*output, processOutputSize + 32);
    else
    {
        memset(*output + processOutputSize, 0, 1);
        break;
    }
}
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
CloseHandle(g_hChildStd_OUT_Rd);
CloseHandle(g_hChildStd_OUT_Wr);

Answer 1:

您在此过程的输出重定向到一个管道,启动过程,等到它退出,然后读取输出。

问题是,窗口的缓冲区只是有限的数据量。 所以,你必须阅读管道,而进程仍在运行,否则程序将被阻止,因为它没有任何更多的数据写入到管道。



Answer 2:

你应该关闭输出管道的写入结束你从中读取之前,作为@Marcus在意见建议。

CloseHandle(g_hChildStd_OUT_Wr);

对我来说,这是真正的答案。



Answer 3:

你可以使用PeekNamedPipe在这样的循环:

for (;;)
{
    DWORD bytesAvail = 0;
    if (!PeekNamedPipe(stdoutPipeRead, NULL, 0, NULL, &bytesAvail, NULL)) {
        std::cout << "Failed to call PeekNamedPipe" << std::endl;
    }
    if (bytesAvail) {
        CHAR buf[BUFSIZE];
        DWORD n;
        BOOL success = ReadFile(stdoutPipeRead, buf, BUFSIZE, &n, NULL);
        if (!success || n == 0) {
            std::cout << "Failed to call ReadFile" << std::endl;
        }
        std::cout << std::string(buf, buf + n);
    }
}


文章来源: Win32 ReadFile hangs when reading from pipe