Я примерно создал следующий код для вызова дочернего процесса:
// pipe meanings
const int READ = 0;
const int WRITE = 1;
int fd[2];
// Create pipes
if (pipe(fd))
{
throw ...
}
p_pid = fork();
if (p_pid == 0) // in the child
{
close(fd[READ]);
if (dup2(fd[WRITE], fileno(stdout)) == -1)
{
throw ...
}
close(fd[WRITE]);
// Call exec
execv(argv[0], const_cast<char*const*>(&argv[0]));
_exit(-1);
}
else if (p_pid < 0) // fork has failed
{
throw
}
else // in th parent
{
close(fd[WRITE]);
p_stdout = new std::ifstream(fd[READ]));
}
Теперь, если подпроцесс не слишком много пишет в стандартный вывод, я могу дождаться его завершения, а затем прочитать стандартный вывод из p_stdout
. Если он пишет слишком много, запись блокируется, и родитель ждет ее вечно. Чтобы исправить это, я попытался подождать с WNOHANG
в родительском элементе, если он не закончен, прочитать весь доступный вывод из p_stdout с помощью readsome
, немного поспать и повторить попытку. К сожалению, readsome
никогда ничего не читает:
while (true)
{
if (waitid(P_PID, p_pid, &info, WEXITED | WNOHANG) != 0)
throw ...;
else if (info.si_pid != 0) // waiting has succeeded
break;
char tmp[1024];
size_t sizeRead;
sizeRead = p_stdout->readsome(tmp, 1024);
if (sizeRead > 0)
s_stdout.write(tmp, sizeRead);
sleep(1);
}
Вопрос: Почему это не работает и как это исправить?
edit: Если есть только дочерний процесс, простое использование read
вместо readsome
, вероятно, сработает, но процесс имеет несколько дочерних процессов и должен реагировать, как только один из них завершается.