Как обнаружить сломанную трубу на входе?

У меня есть программа, которая подает данные на стандартный ввод через канал; someapp | myprogram

Я надеялся, что read возвращает отрицательное значение на сломанной трубе; кажется, это не так. Основной цикл выглядит примерно так:

    int rdsum = 0;
    int rdsize = 0;

    do
    {
        rdsize = read(STDIN_FILENO, buf, BUFSIZE);
        if(rdsize > 0)
        {
            //[operations on the buffer]
            rdsum += rdsize;
        }
        else if(rdsize == 0)
        {
            usleep(100000);
        }
        else return 0;
    }
    while(rdsum < blocksize);

на return 0;, программа направляется прямо к выходу. Или, по крайней мере, если бы это случилось...

Если someapp в someapp | myprogram заканчивается или убит, myprog еще жив, появляется в ps список. Как правильно определить, что приложение для кормления умерло / закончилось / было убито, и выйти из него в таком случае?

1 ответ

Решение

От man 2 read:

В случае успеха возвращается число прочитанных байтов (ноль указывает на конец файла)

Таким образом, правильное поведение для вас будет возвращаться на rdsize == 0,

Возвращаемое значение -1 для ошибок (или errno == EAGAIN только если дескриптор файла установлен на неблокирование) и когда это произойдет, вам следует

perror("read"); // print an error message
abort(); // abort the process or do other error handling

Как это:

int rdsum = 0;
int rdsize = 0;

do
{
    rdsize = read(STDIN_FILENO, buf, BUFSIZE);
    if(rdsize > 0)
    {
        //[operations on the buffer]
        rdsum += rdsize;
    }
    else if(rdsize == 0)
    {
        return 0;
    }
    else if (errno == EAGAIN  || errno == EWOULDBLOCK) { // #include <errno.h>
        usleep(100000);
    } else {
        perror("read"); // print an error message
        abort();        // exit and core dump
    }
}
while(rdsum < blocksize);
Другие вопросы по тегам