VC ++ ReadFile неожиданно блокирует при чтении закрытого анонимного канала - PullRequest
0 голосов
/ 13 октября 2011

Я пытаюсь создать дочерний процесс, выполняющий любую команду exe, и перенаправить все его stdio и stderr на мой родительский процесс через анонимный канал.Но когда мой родительский процесс пытается выполнить ReadFile () в конце READ анонимного канала после завершения дочернего процесса, он просто блокирует, а не возвращает ошибку.

Вот код:

#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 записи анонимного канала.Мой родительский процесс читает из РУЧКИ чтения той же трубы.

Они напечатаны my _tmain (), показывая, что канал может связываться через родительско-дочерние процессы.Это то, что мы ожидаем увидеть, если мы введем cl.exe в командной строке без каких-либо аргументов.Обратите внимание на своеобразное поведение cl.exe: первые две строки взяты из stderr cl.exe, а последняя - из 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);

в блоках _tmain () после завершения дочернего процесса cl.exe.Но я ожидаю, что вызов ReadFile () вернется с ошибкой ERROR_BROKEN_PIPE и выйдет из родительского цикла вместо блокировки вызова ReadFile ().

Почему блоки ReadFile () блокируются при чтении анонимного канала?

1 Ответ

4 голосов
/ 13 октября 2011

Вы забыли закрыть дескрипторы канала в родительском процессе , поэтому канал еще не полностью закрыт.

...