Я написал программу a.exe
, которая запускает другую написанную мной программу, b.exe
, используя функцию CreateProcess .Вызывающая сторона создает два канала и передает концы записи обоих каналов в CreateProcess как дескриптор stdout / stderr для использования в дочернем процессе.Это практически то же самое, что и образец Создание дочернего процесса с перенаправленным вводом и выводом на MSDN.
Поскольку, похоже, он не может использовать один вызов синхронизации, который ожидаетчтобы процесс мог выйти из или данных на stdout или stderr (функция WaitForMultipleObjects не работает на каналах), у вызывающей стороны есть два работающих потока, которые оба выполняют (блокирование) ReadFile вызывает конец чтения каналов stdout / stderr;вот точный код «процедуры чтения потока», которая используется для stdout / stderr (я сам не писал этот код, я полагаю, что это сделал какой-то коллега):
DWORD __stdcall ReadDataProc( void *handle )
{
char buf[ 1024 ];
DWORD nread;
while ( ReadFile( (HANDLE)handle, buf, sizeof( buf ), &nread, NULL ) &&
GetLastError() != ERROR_BROKEN_PIPE ) {
if ( nread > 0 ) {
fwrite( buf, nread, 1, stdout );
}
}
fflush( stdout );
return 0;
}
a.exe
затем используетпростой вызов WaitForSingleObject для ожидания завершения b.exe
.Как только этот вызов возвращается, два потока чтения завершаются (потому что каналы разорваны), и концы чтения обоих каналов закрываются с помощью CloseHandle .
Теперь проблема, с которой я столкнулся, заключается в следующем:b.exe
может (в зависимости от ввода пользователя) запускать внешние процессы, которые живут дольше самого b.exe
, в основном процессы демона.В этом случае происходит то, что концы записи каналов stdout / stderr наследуются этому процессу демона, поэтому канал никогда не прерывается.Это означает, что вызов WaitForSingleObject в a.exe
возвращает (потому что b.exe
завершен), но вызов CloseHandle для любого из блоков каналов, потому что оба потока чтения все еще находятся в своем (блокирующем!) Вызове ReadFile.
Как решить эту проблему, не прерывая обе темы чтения с помощью грубой силы ( TerminateThread ) после возврата b.exe
?Если возможно, я бы хотел избежать любых решений, которые включают опрос труб и / или процесс тоже.
ОБНОВЛЕНИЕ: Вот что я попробовал до сих пор:
- Не имеющий
b.exe
наследования a.exe
;это не работаетMSDN, в частности, говорит, что дескрипторы, передаваемые в CreateProcess, должны быть наследуемыми. - Очистка наследуемого флага в stdout / stderr внутри
b.exe
: похоже, не имеет никакого эффекта (меня это удивило бы, если бы это произошло). - Имея процедуру
ReadDataProc
(которая читает на обоих каналах), проверьте, действительно ли работает b.exe
в дополнение к проверке ERROR_BROKEN_PIPE
.Конечно, это не сработало (но я понял это позже), потому что поток заблокирован в вызове ReadFile.