我正在尝试创建一个运行任何exe命令的子进程,并通过匿名管道将其所有stdio和stderr重定向到我的父进程。但是当我的父进程在子进程终止后尝试在匿名管道的READ端执行ReadFile()时,它只是阻塞而不是返回错误。
以下是代码:
#include "windows.h"
//==================================================
void createChildPipes(PHANDLE phRead, PHANDLE phWrite){
SECURITY_ATTRIBUTES sa={sizeof(SECURITY_ATTRIBUTES) ,NULL,TRUE};
if ( !CreatePipe(phRead, phWrite, &sa, 2048) ) { //... }
}
//==================================================
void setupStartupInfo(LPSTARTUPINFO lpsi, HANDLE hStdOutput, HANDLE hStdError) {
lpsi->cb = sizeof(STARTUPINFO);
lpsi->lpReserved=NULL;
lpsi->lpDesktop=NULL;
lpsi->lpTitle=NULL;
lpsi->dwX=0;
lpsi->dwY=0;
lpsi->dwXSize=200;
lpsi->dwYSize=500;
lpsi->dwFlags=STARTF_USESTDHANDLES;
lpsi->cbReserved2=0;
lpsi->lpReserved2=NULL;
lpsi->hStdInput=GetStdHandle(STD_INPUT_HANDLE);
lpsi->hStdError= hStdError;
lpsi->hStdOutput=hStdOutput;
}
//==================================================
void createChildProcess(PHANDLE phOutRead, PHANDLE phOutWrite, PHANDLE phErrRead, PHANDLE phErrWrite) {
TCHAR name[]=_T("cl.exe");
createChildPipes(phOutRead, phOutWrite);
STARTUPINFO si;
setupStartupInfo(&si, *phOutWrite, *phOutWrite);
PROCESS_INFORMATION pi;
if (!CreateProcess(NULL, name, NULL, NULL, true, 0, NULL, NULL, &si, &pi)) { //...}
}
//==================================================
void _tmain(int argc, _TCHAR* argv[]){
HANDLE hOutRead, hOutWrite, hErrRead, hErrWrite;
createChildProcess(&hOutRead, &hOutWrite, &hErrRead, &hErrWrite) ;
char buf[10];
BOOL readState;
for (;;) {
DWORD dwBytesRead;
memset(buf, '\0', sizeof(buf));
readState=ReadFile(hOutRead, buf, sizeof(buf)-2 , &dwBytesRead, NULL);
printf("%s", buf);
if (!readState)
break;
}
}
这是我的代码正在做的事情。我的_tmain()创建了一个子进程(我使用VC ++ cl.exe命令作为测试)并将其stdio和stderr重定向到匿名管道的写HANDLE。我的父进程从同一管道的读HANDLE读取。
这些是由我的_tmain()打印出来的,表明管道可以通过父子进程进行通信。如果我们在没有任何参数的命令行中键入cl.exe,我们期望看到这些。请注意cl.exe的特殊行为,前两行来自cl.exe的stderr,最后一行来自stdout。
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
现在关于这个问题,行:
readState=ReadFile(hOutRead, buf, sizeof(buf)-2 , &dwBytesRead, NULL);
在子cl.exe进程终止后,在_tmain()块中。但是,我希望ReadFile()调用以ERROR_BROKEN_PIPE错误状态返回并退出父循环而不是阻止ReadFile()调用。
为什么ReadFile()在读取匿名管道时会阻塞?