02 июн. 2012 г., 16:02 отArtoAle

Win32, ReadFile из конвейера даже после завершения дочернего процесса

У меня есть простая программа (на C), которая создает два дочерних процесса, ждет на унаследованном канале и помещает вывод в файл.

Все работает хорошо, за исключением того, что после некоторого цикла записи / чтения в двух каналах, когда дочерний процесс завершается, вызывается блок ReadFile, ожидающий данные в канале. Я использую следующий шаблон:

...
//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);
    ...
}
... 

Последний блок вызова (после выхода дочернего процесса). Идея почему (и, если нет, как отладить это)?

Ответы на вопрос(3)

01 июн. 2012 г., 23:06 отRemy Lebeau

ReadFile() в синхронном режиме. Пока труба открыта,ReadFile() заблокирует ожидание большего количества данных. Если вы оставите открытым процесс и обработайте нить,CreateProcess() возвращается к вам, что не позволит полностью завершить дочерний процесс, поэтому канал может не закрыться на дочернем конце. Прежде чем войти в цикл чтения, закройте ручки, которыеCreateProcess() возвращает, позволяя правильно закрыть канал после полного завершения дочернего процесса, а затемReadFile() может сообщить вам об ошибке, когда она больше не может читать из канала. В качестве альтернативы, переключитесь на перекрывающийся ввод / вывод на конвейере, чтобы вы могли контролировать дочерний процесс с помощьюWaitForSingleObject() или жеGetExitCodeProcess() во время выполнения цикла вы можете определить, когда дочерний процесс завершается независимо от состояния канала.

02 июн. 2012 г., 15:53 отArtoAle

Я не закрывал родительский дескриптор записи канала должным образом (hWrite), поэтому синхронный файл ReadFile не смог сообщить мне о завершении дочернего процесса.

Если у кого-то возникла такая же проблема, убедитесь, что вы закрыли наследуемый дескриптор канала перед запуском операции ввода-вывода на этом канале (как сообщает MSDN, найти не удалось).

23 июн. 2016 г., 16:38 отkellogs

у вас был доступ к обоим процессам на канале. Однако, если вы этого не сделали или просто хотели прерватьReadFile позвони, тогдаCancelSynchronousIo твой друг:https://msdn.microsoft.com/en-us/library/windows/desktop/aa363789(v=vs.85).aspx

ВАШ ОТВЕТ НА ВОПРОС