Как читать стандартный вывод из подпроцесса, когда последний не очищает свой стандартный вывод?

0

Перед нижеследующим кодом я делаю:

  • создать 1 трубу для чтения вывода из разветвленного процесса

  • вилка()

  • execv() скрипт python

Затем в родительском процессе я делаю:

//set pipes to non-Blocking
File * cout_f = fdopen(cout_pipe[0], "r");
int flags = fcntl(cout_pipe[0], F_GETFL, 0);
fcntl(cout_pipe[0], F_SETFL, flags|O_NONBLOCK);

// read from pipe and send it up through a callback method
int stat;
size_t size = 0;
char buffer [ 1000 ];
do
{
    while((size = fread(buffer, sizeof(char), sizeof(char)*1000, cout_f))!=0)
    {
        call_back_function(buffer, size);
    }
}while(waitpid(child_pid, &stat, WNOHANG) != -1)

//Do 1 extra read
while((size = fread(buffer, sizeof(char), sizeof(char)*1000, cout_f))!=0)
{
    call_back_function(buffer, size);
}

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

Вот мои вопросы:

  • Является ли приведенный выше код безопасным/правильным или его можно улучшить?
  • Есть ли способ прочитать всю трубу в последний момент, когда подпроцесс умирает, даже если он не очищает его stdout?
  • 3
    Пока данные не сброшены, они не записаны, поэтому никак!
  • 0
    Согласовано! Но как только подпроцесс python умирает, не должны ли каналы очищаться автоматически?
Показать ещё 8 комментариев
Теги:
stdout
pipe
fork

1 ответ

2
Лучший ответ

Вам не нужно ждать. Просто отправьте все, как вы его читаете. Это то, что уже делает ваш код. Избавиться от неблокирующего режима; избавиться от условия while (wait (...)); избавиться от окончательного чтения; и просто выполните первый цикл чтения до конца потока. Затем вызовите wait(), чтобы получить код выхода.

Если процесс также создается на stderr, вам нужно будет прочитать это в другом потоке, иначе при буфере stderr он будет блокироваться.

  • 0
    Оу, вы правы, и я действительно читаю stderr. Так может ли моя проблема быть исправлена с помощью вышеуказанной реализации?
  • 1
    Или, если вам не нужен второй поток, вы можете использовать системный вызов select, чтобы подождать, пока данные не будут доступны по любому каналу.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню