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

11

У меня есть простая программа (на 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);
    ...
}
... 

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

спасибо, беги через это сегодня! Dio
Спасибо за вопрос и за ответ. Я прыгал туда-сюда между вариантами _popen (...) (которые хорошо работают в моей среде Code :: Blocks-GCC, но не включаются в моей рабочей среде) и используемыми вами методами CreateProcess / CreatePipe. Ваша реализация отлично работает. Благодарю. ryyker

Ваш Ответ

3   ответа
6

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

На самом деле, я не могу дождаться завершения дочернего процесса до завершения цикла. Кроме того, я решил проблему сам: я не закрывал должным образом дескриптор записи канала, так что синхронныйReadFile не смог сообщить мне об окончании дочернего процесса. В любом случае, спасибо ArtoAle
@ Реми, ты уверен? Я никогда не слышал, чтобы удержание открытых дескрипторов процесса не позволяло Windows закрывать дескрипторы, принадлежащие этому процессу, когда он завершается.
У меня та же проблема и то же решение - я подозреваю, что это потому, что, если вы не закроете дескриптор, родительский процесс может записать в канал, а затем прочитать из того же самого канала. Следовательно, ReadFile должен ждать / канал должен оставаться открытым, поскольку вышеупомянутый (глупый) случай все еще может произойти. Но если никаких дескрипторов больше не существует, то ничто не сможет снова написать в канал.
13

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

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

Спасибо за этот ответ. Собственный пример кода Microsoft [1] для этого не работает, но это решило проблему для меня. [1]:msdn.microsoft.com/en-us/library/windows/desktop/…
Некоторые полезные документы по этому вопросу:msdn.microsoft.com/en-gb/library/windows/desktop/…
0

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

Похожие вопросы