Re-reading from a named pipe when writers come and go

I have a problem when I have to read from a named pipe. I have to handle the situation when the authors of the named pipe come and go, but I need the same pipe to open in all my applications.

I have summarized this in the following code.

int main( int c, char *v[] )
{
    int rfd;
    if ( (rfd = open( PIPENAME, O_RDONLY | O_NONBLOCK )) < 0 )
    {
        perror( "open" );
        return 1;
    }

    char buffer[ 1024000 ];

    // used to give select an upper bound on number of fds
    int nfd = rfd + 1;

    fd_set rfds;
    FD_ZERO( &rfds );
    FD_SET( rfd, &rfds );

    while( true )
    {
        int nr = select( nfd, &rfds, NULL, NULL, NULL );

        if ( nr < 0 )
        {
            perror( "select" );
            break;
        }

        if ( FD_ISSET( rfd, &rfds ) )
        {
            //std::cout << "RFD SET" << std::endl;
            // Ok, we have data we can read
            int nread = read( rfd, buffer, sizeof( buffer ) );
            if ( nread < 0 )
            {
                perror( "read" );
                break;
            }
            else if ( nread == 0 )
            {
                std::cout << "read 0" << std::endl;
            }
            else
            {
                std::cout << "read " << nread << " bytes" << std::endl;

            }

        }
    }

    close( rfd );

    return 0;
}

The problem is that after the first process writes to the named pipe and disables (closes) its end, my program does not block the selection. It effectively has the rfd set, and reading returns zero bytes read in a narrow loop.

I need rfd to be in NON_BLOCKING mode, or open will block until a record appears.

I tried to use fcntl to set to BLOCKING mode, but this does not work either.

, EOF , . , .

:) .

+3
3

, , . ", ", .

.....
else if ( nread == 0 )   
{   
    std::cout << "read 0" << std::endl;   

    FD_ZERO( &rfds );
    close( rfd );
    if ( (rfd = open( PIPENAME, O_RDONLY | O_NONBLOCK )) < 0 )
    {
        perror( "re-open" );
        break;
    }
    FD_SET( rfd, &rfds );
    nfd = std::max( wfd, rfd ) + 1;
}   
else
.....

, .

- .

+4

:

if ( (rfd = open( PIPENAME, O_RDWR | O_NONBLOCK )) < 0 )

. RDWR RDONLY, , ...

+1

fds , read() EWOULDBLOCK/EAGAIN, clearerr() fd?

-1

Source: https://habr.com/ru/post/1729047/


All Articles