问题
I have a simple program (in C) that create two child process, wait on an inherited pipe each, and put the output in a file.
Everything works well, except that after some write/read cycle on the two pipe, when the child ends, the call to ReadFile block, waiting for data on the pipe. I use the following pattern:
...
//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);
...
}
...
The last call (after child process exit) block. Idea of why (and, if not, how to debug this)?
回答1:
I found out the solution myself (wich actually was a coding error).
I wasn't closing the parent's write handle of the pipe properly (hWrite
), so, the synchronous ReadFile wasn't able to report me back the child process termination.
If somebody has the same problem, make sure you close the inheritable handle of the pipe before starting the I/O operation on that pipe (as MSDN reports, cannot find again were).
回答2:
You are calling ReadFile()
in synchronous mode. As long as the pipe is open, ReadFile()
will block waiting for more data. If you leave open the process and thread handles that CreateProcess()
returns to you, that will prevent the child process from fully exiting, so the pipe may not get closed on the child end. Before entering your reading loop, close the handles that CreateProcess()
returns, allowing the pipe to close properly when the child process fully terminates, and then ReadFile()
can report an error back to you when it can't read from the pipe anymore. Alterntively, switch to overlapped I/O on the pipe so you can monitor the child process with WaitForSingleObject()
or GetExitCodeProcess()
while the loop is running so you can detect when the child process terminates regardless of the pipe state.
回答3:
In your case all good, you had access to both processes on the pipe. If however you did not, or just wanted to interrupt the ReadFile
call, then CancelSynchronousIo
is your friend: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363789(v=vs.85).aspx
来源:https://stackoverflow.com/questions/10841840/win32-readfile-from-pipe-block-even-after-child-terminated