c++ - ERROR_BROKEN_PIPE 无法读取进程终止前产生的进程输出

标签 c++ winapi

我在 Win32 中有一个简单的进程重定向例程。这里的问题是,如果我在从子进程 stdout 的读取之间放置一个 Sleep,只要进程在我 sleep 时终止,我就会错过输出 ERROR_BROKEN_PIPE 的管道中的最后一个字节。看起来,一旦子进程终止,它的管道和关联的句柄就会关闭,任何未决的东西都会被丢弃。唯一的解决方案似乎是尽可能快地从管道中读取文件,但由于软件的设计,这对我来说不仅仅是一个问题。

int _tmain(int argc, _TCHAR* argv[])
{
    BOOL bSuccess;
    WCHAR szCmdLine[MAX_PATH];
    char chBuf[BUFSIZE];
    DWORD dwRead;
    HANDLE g_hChildStd_OUT_Rd2 = NULL;
    HANDLE g_hChildStd_OUT_Wr2 = NULL;
    SECURITY_ATTRIBUTES saAttr2; 
    STARTUPINFO si2;
    PROCESS_INFORMATION pi2;

    ZeroMemory( &si2, sizeof(si2) );
    si2.cb = sizeof(si2);
    ZeroMemory( &pi2, sizeof(pi2) );
    //create pipe
    saAttr2.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr2.bInheritHandle = TRUE; 
    saAttr2.lpSecurityDescriptor = NULL; 
    assert(CreatePipe(&g_hChildStd_OUT_Rd2, &g_hChildStd_OUT_Wr2, &saAttr2, 0));
    //create child process
    bSuccess = FALSE;
    memset(szCmdLine, 0, MAX_PATH);
    wsprintf(szCmdLine, L"c:\\myprocess.exe");
    ZeroMemory( &pi2, sizeof(PROCESS_INFORMATION) );
    ZeroMemory( &si2, sizeof(STARTUPINFO) );
    si2.cb = sizeof(STARTUPINFO); 
    si2.hStdOutput = g_hChildStd_OUT_Wr2;
    si2.hStdError = g_hChildStd_OUT_Wr2; // also add the pipe as stderr!
    si2.dwFlags |= STARTF_USESTDHANDLES;
    assert(CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si2, &pi2));
    //read from pipe
    CloseHandle(g_hChildStd_OUT_Wr2);
    memset(chBuf, 0, BUFSIZE);
    for (;;) 
    { 
        DWORD dwRead = 0;
        DWORD bytes = 0;
        if (!PeekNamedPipe(g_hChildStd_OUT_Rd2,NULL,NULL,NULL,&bytes,NULL)) {
            //printf("Peek named pipe failed!");
            break;
        }

        if (bytes != 0) {
            if (!ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE, &dwRead, NULL)) 
            {
                printf("EOF!!\n");
                break;

            }
            else {
                chBuf[dwRead] = 0;
                printf("%s", chBuf);
            }

        } else {
            Sleep(5000);
        }

    }
    while(1) {
    Sleep(1000);
    printf("Lopp!\n");
    }
    return 0;
}

有什么提示吗?有没有办法像在 POSIX 中那样,让进程保持暂停状态,直到它的管道被读取?

谢谢!

最佳答案

我觉得问题不在那里。

您的代码中确实存在一些问题。许多都是未成年人:你初始化了两次 si2 和 pi2(无害),你有一个无限循环所以你的程序永远不会结束(我假设你是 Ctrl-C ...),你正在混合 _tmain 和 WCHAR (应该是 wmainWCHAR_tmainTCHAR)但是如果你做一个 unicode build 就没问题.

一个更严重:chBuf 的大小为 BUFSIZE,您最多读取其中的 BUFSIZE 个字符(到这里为止还不错)。但是如果你确实读取 BUFSIZE 字符,dwReadBUFSIZE 并且在下一行你有缓冲区溢出

chBuf[dwRead] = 0; // buffer overflow if BUFSIZE chars have been read !

我只用 :

解决了这个问题
if (!ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE - 1, &dwRead, NULL))

程序运行正常。

顺便说一句:子进程为系统所知(即使已终止),直到它的所有句柄都已关闭......并且您在 pi2.hProcess 中有一个句柄。

当然我不能使用 c:\\myprocess.exe 并使用 cmd/c dir 进行测试。因此,如果上述修复还不够,请尝试使用与我相同的子项,因为问题可能来自以 NULL hStdInput 开头的 myprocess.exe

关于c++ - ERROR_BROKEN_PIPE 无法读取进程终止前产生的进程输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28170391/

相关文章:

c - Winapi win32编程-选项卡控件不显示

c++ - 无法让 Windows 覆盖图标在 TListView 中工作

c++ - char、unsigned char 和signed char 的 C/C++ 底层表示

c++ - boost::circular_buffer 是否确认自动弹出操作

java - C++ 或 Java 中的类型转换和类型转换有什么区别?

c++ - 有没有办法限制进程的输出文件数量?

c++ - 使 GNU gettext 为 MFC 应用程序工作

c++ - C++11标准中 `top-level cv-qualifiers`的定义在哪里?

delphi - Delphi中如何查找并关闭弹出菜单?

c++ - 设置当前驱动器?时间:2019-03-17 标签:c++win32