读取封闭的匿名管道时,VC ++ ReadFile意外阻塞

时间:2011-10-13 12:41:28

标签: winapi stdout stderr readfile io-redirection

我正在尝试创建一个运行任何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()在读取匿名管道时会阻塞?

1 个答案:

答案 0 :(得分:4)

forgot to close the pipe handles in the parent process,所以管道尚未完全关闭。