I'm creating a C-program under Linux, and I want to catch FFMpeg's output-data and forward it. To do so, I'm calling FFMpeg via (an implementation of) popen2. It all is working fine: I'm able to get FFMpeg's data out of the pipe via read(). Things start to get awkward if FFMpeg stops working. read() seems to be blocking, which is the expected behaviour, but it never exits when the pipe is closed.
I learned that, for read() to break and detect an EOF, the pipe should be closed on both ends, so when I detect that FFMpeg is crashed or killed, I close the reading-end of my pipe. I'm assuming that, since FFMpeg is closed, it disconnects its end of the pipe.
My assumption seems to be wrong: when I close the reading-end of the pipe by using close(), the program still seems to be hanging in read().
Would somebody be able to explain me what's wrong with my assumption and point me in the right direction so that I can properly detect when the program that I'm piping to or from (in this case FFMpeg) has stopped sending data?
The relevant code:
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "helper.h"
#define READ 0
#define WRITE 1
FILE *sink_stream;
int ffmpeg_sink;
pid_t popen2_2(const char **command, int *infp, int *outfp);
void* pthread_sink_ffmpeg(void *arg);
pid_t popen2_2(const char **command, int *infp, int *outfp)
{
    int p_stdin[2], p_stdout[2];
    pid_t pid;
    
    int devNull = open("/dev/null", O_WRONLY);
    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return -1;
    pid = fork();
    if (pid < 0)
        return pid;
    else if (pid == 0) //first fork
    {
        close(p_stdin[WRITE]);
        dup2(p_stdin[READ], READ); 
        
        close(p_stdout[READ]);
        dup2(p_stdout[WRITE], WRITE);
        
        //dup2(devNull,2); //pipes stderr to /dev/null....
        execvp(*command, command);
        _exit(1);
    }
    if (infp == NULL)
    {
        close(p_stdin[WRITE]);
        close(p_stdin[READ]);
    }
    else
    {
        *infp = p_stdin[WRITE];
    }
    
    if (outfp == NULL)
    {
        close(p_stdout[WRITE]);
        close(p_stdout[READ]);
    }
    else
    {
        *outfp = p_stdout[READ];
    }
    
    return pid;
}
void* pthread_sink_ffmpeg(void *arg)
{
    char *pbuffer;
    int length, res;
    
    pbuffer = malloc(4096);
    while(1)
    {
        /* Wait for input */    
        dbgfprintf("Waiting for input...");
                
        while( (length = read(ffmpeg_sink, pbuffer, 1024)) )
        {
            fprintf(stderr, "Read [ %d ]...\r", length);
        }
        /* RIP */
        dbgfprintf("Done for now..");
        
    }
    free(pbuffer);
}
int main( void )
{
    int wstatus;
    pid_t child_pid, w;
    pthread_t t_ffmpeg_source;
        
    const char *command_ffmpeg[] = {"ffmpeg", 
        "-hide_banner",
        "-re",
        "-i", "http://relay.ah.fm/192k",
        "-c:a", "libfdk_aac",
        "-profile:a", "aac_he_v2",
        "-b:a", "128k",
        "-f", "adts",
        "pipe:1",
        NULL};
        
    child_pid = popen2_2(command_ffmpeg, NULL, &ffmpeg_sink);
    dbgfprintf("Started ffmpeg with pid [ %d ]...", child_pid);
    
    pthread_create(&t_ffmpeg_source, NULL, pthread_sink_ffmpeg, NULL);
    
    do {
       w = waitpid(child_pid, &wstatus, WUNTRACED | WCONTINUED);
    } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus)); 
    
    dbgfprintf("ffmpeg terminated...");
    close(ffmpeg_sink);
    
    pthread_join(t_ffmpeg_source, NULL);
}
This code is able to start the program, receive it's data, detect the execvp'd program crash/kill, but it never gets out of read() when the execvp'd program is killed.
I've also tried to read the pipe as a filestream;
    sink_stream = fdopen(ffmpeg_sink, "r");
    while( !feof(sink_stream) )
    {
        length = fread(pbuffer, 1, 4096, sink_stream);
            
        fprintf(stderr, "Read [ %d ]...\r", length);
    }
..which gives the same result: it reads the data but it doesn't get out of fread().
Any help would be highly appreciated!
Thanks in advance!
