12

我有一个简单的程序(在 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);
    ...
}
... 

最后一次调用(子进程退出后)阻塞。为什么的想法(如果没有,如何调试)?

4

3 回答 3

14

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

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

于 2012-06-02T13:53:55.547 回答
7

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

于 2012-06-01T21:06:25.677 回答
0

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

于 2016-06-23T14:38:31.050 回答