即使在孩子终止后,Win32,来自管道块的ReadFile

时间:2012-05-31 21:55:57

标签: c pipe win32-process

我有一个简单的程序(在C中),它创建两个子进程,每次等待一个继承的管道,并将输出放在一个文件中。

一切正常,除了在两个管道上的一些写/读周期之后,当孩子结束时,调用ReadFile块,等待管道上的数据。我使用以下模式:

...
//create pipe1
CreatePipe(&hReadDup,&hWrite,&saAttr,0);
DuplicateHandle(GetCurrentProcess(),hReadDup,GetCurrentProcess(),&hRead,0,FALSE,DUPLICATE_SAME_ACCESS);
CloseHandle(hReadDup);


si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hWrite;   

CreateProcess(  NULL,
        const_cast<LPWSTR>(cmd2.c_str()), //the command to execute
        NULL,
        NULL,
        TRUE,
        0,
        NULL,
        NULL,
        &si, //si.
        &pi
    );

...
CloseHandle(hWrite); // EDIT: this was the operation not properly done!

while(cont){
    ...
    cont = ReadFile(hRead,buf,50, &actual,NULL);
    ...
}
... 

最后一次调用(子进程退出后)阻止。 想法为什么(如果不是,如何调试)?

3 个答案:

答案 0 :(得分:13)

我自己找到了解决方案(实际上是编码错误)。 我没有正确关闭父管道的管道写入句柄(hWrite),因此,同步ReadFile无法向我报告子进程终止。

如果有人遇到同样的问题,请确保在启动该管道上的I / O操作之前关闭管道的可继承句柄(如MSDN报告,再也找不到)。

答案 1 :(得分:7)

您正在以同步模式呼叫ReadFile()。只要管道打开,ReadFile()将阻止等待更多数据。如果您打开CreateProcess()返回给您的进程和线程句柄,这将阻止子进程完全退出,因此管道可能无法在子端关闭。在进入读取循环之前,关闭CreateProcess()返回的句柄,允许管道在子进程完全终止时正确关闭,然后ReadFile()可以在无法读取时向您报告错误从管道了。或者,切换到管道上的重叠I / O,这样您就可以在循环运行时使用WaitForSingleObject()GetExitCodeProcess()监视子进程,这样您就可以检测子进程何时终止,而不管管道状态如何。

答案 2 :(得分:0)

在您的情况下一切都很好,您可以访问管道上的两个进程。如果您没有,或者只是想打断ReadFile来电,那么CancelSynchronousIo就是您的朋友:https://msdn.microsoft.com/en-us/library/windows/desktop/aa363789(v=vs.85).aspx