我有一个简单的程序(在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);
...
}
...
最后一次调用(子进程退出后)阻止。 想法为什么(如果不是,如何调试)?
答案 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