Есть задача запускать из своей программы другую и отлавливать, что она делает.
Другое приложение - это FFmpeg (но это не важно).
Проблема в том, что моя программа почему-то не всегда видит последнюю выведенную ей строку.
Я создаю pipe, потом выполняю fork и exec.
В процессе работы периодически читаю функцией fgets из своего конца трубы то, что FFmpeg туда пишет.
И эта функция либо не отдает последнюю строчку, которую ffmpeg ей написала, либо зависает, ожидая, что ffmpeg туда что-то напишет, а ffmpeg уже давно закончила работу и ждет в виде зомби (ffmpeg [<defunct>]), когда же ее соберут функцией waitpid().
Код под спойлером
#define response_length 450
char response[response_length+1];
int fds[2];
if (pipe(fds)) {
//обработка ошибки
return 1;
}
pid_t pid;
pid = fork();
if (pid < 0) {
// обработка ошибки
return 1;
}else if (pid == 0) { //child
close(fds[0]);
close(STDERR_FILENO);
dup2(fds[1], STDERR_FILENO );
execv(ffmpeg_command, ffmpeg_params2);
_exit(0);
}
time_t fork_start_time,cur_time;
fork_start_time=cur_time=time(NULL);
if((run_fp = fdopen(fds[0], "r"))==NULL){
// не получилось открыть трубу на чтение, обработка ошибки, выход
return 1;
}
int wp_res=0;
pid_t wp_ret;
int feof_res=0;
int time_res=0;
cur_time=time(NULL);
while((feof_res=!feof(run_fp)) &&
!is_exiting() &&
(wp_res=((wp_ret=waitpid((*pid),&ffmpeg_status,WNOHANG))==(pid_t)0)) &&
(time_res=(cur_time - fork_start_time < (time_t)max_run_time))){
cur_time=time(NULL);
if(fgets(response,response_length,run_fp)!=NULL){
//обработка того, что написала FFmpeg
}
}
wp_ret=waitpid((*pid), &ffmpeg_status, 0);
if (WIFEXITED ( ffmpeg_status )) {
int exit_code = WEXITSTATUS ( ffmpeg_status );
if (exit_code == 0) {
/// прочая обработка кода возврата и response
}
}
Пробовал перед чтением опрашивать дескриптор pselect-ом - эта функция возвращает, что данных нет.
Пробовал после цикла еще раз читать что-то из трубы - то же самое, либо fgets подвисает в ожидании данных, либо pselect возвращает нули, (т.е. нечего читать).
Пользователь решил продолжить мысль 22 Июля 2009, 08:21:00:
Агаа!
fgets читает из потока до тех пор, пока не встретит eof или \n.
EOF там точно нет, и \n FFmpeg туда не пишет - вероятно поэтому fgets и виснет.