use of select() on FIFO after it has closed - Unix

This is a discussion on use of select() on FIFO after it has closed - Unix ; Set up a fifo like this from bash: mkfifo /tmp/testfifo inside a program open it, which gets an fd, set that fd nonblocking (because of other stuff going on on other fd's which are not shown in this example) then ...

+ Reply to Thread
Results 1 to 6 of 6

Thread: use of select() on FIFO after it has closed

  1. use of select() on FIFO after it has closed

    Set up a fifo like this from bash:

    mkfifo /tmp/testfifo

    inside a program open it, which gets an fd, set that fd nonblocking
    (because of other stuff going on on other fd's which are not shown in
    this example) then enter a program which has a loop containing
    (simplified from the original):

    FD_CLEAR(&read_set);
    FD_SET(fd, &read_set);
    select(fd+1,&read_set,NULL,NULL,NULL);
    if(FD_ISSET(fd,&read_set)){
    ret = read(fd, addr, n);
    if(ret>0){
    (void) fprintf(stdout,"Read %s\n",addr);
    }
    else if(ret < 0){
    (void) fprintf(stdout,"Error %d\n",errno);
    }
    else {
    (void) fprintf(stdout,"File closed\n");
    }
    }


    Here is where it gets strange. At first this works as expected, it
    gets to the select() and waits for input on the FIFO. If from another
    shell one then does:

    echo "word" >/tmp/testfifo

    Select sees that data is available and returns, FD_ISSET is true,
    read() gets the data, and finally fprintf emits

    Read word

    So far so good. However, then things go south. Because the echo
    "closed" the fifo, select() sees it in End of File (which is an event)
    and comes back immediately, FD_ISSET is true, and read returns 0 (== end
    of file). So the program begins to spew

    File closed
    File closed
    ....

    as fast as it can. If while this is going on from another shell
    one does:

    echo "another word" >/tmp/testfifo

    the output will look like this

    ....
    File closed
    Read another word
    File closed
    File closed
    ....

    In this case EOF does not indicate the end of input, that is
    triggered by a particular "End of Stream" string sent to the fifo.

    The question is, what is the most portable way to make the select() stop
    coming back immediately? If the application closes and reopens the FIFO
    it will go back to the original state where it will wait at the
    select(). Is there a better way, perhaps using fcntl()?

    Thanks,

    David Mathog

  2. Re: use of select() on FIFO after it has closed

    "David Mathog" wrote in message
    news:fppq52$ob4$1@naig.caltech.edu...
    [snip]
    > In this case EOF does not indicate the end of input, that is
    > triggered by a particular "End of Stream" string sent to the fifo.
    >
    > The question is, what is the most portable way to make the select() stop
    > coming back immediately? If the application closes and reopens the FIFO
    > it will go back to the original state where it will wait at the select().
    > Is there a better way, perhaps using fcntl()?


    The potential problem with closing and reopening the FIFO is that there is a
    window between read() == 0 and close() where data written will be thrown
    away.

    An alternative is to open the FIFO for writing immediately after opening it
    for reading, and leave both descriptors open (opening it O_RDWR may work;
    the behaviour is unspecified by POSIX). This means you will never see EOF
    (useful in some cases).

    Alex



  3. Re: use of select() on FIFO after it has closed

    Alex Fraser wrote:

    > An alternative is to open the FIFO for writing immediately after opening it
    > for reading, and leave both descriptors open (opening it O_RDWR may work;
    > the behaviour is unspecified by POSIX). This means you will never see EOF
    > (useful in some cases).


    I went this route. Now it opens the file, checks the fd with fstat() to
    see if it is a FIFO, and if it is, it opens the same file for write.

    Unfortunately it (still) locks on the first open() of the FIFO unless
    there is already data waiting there. I do not think there is a way
    around that, since the program cannot set read nonblocking until it has
    a read fd, and it cannot get a read fd until the file is opened. The
    program could use stat() first to see if it is a FIFO before opening it
    for read, and do the open for write first, then push a byte or two into
    the FIFO so the open for read won't block. But that isn't safe, since
    the program has no way of knowing if there is data in the FIFO at that
    point. Better to live with the block on open for read I guess.

    Thanks,

    David Mathog

  4. Re: use of select() on FIFO after it has closed

    In article ,
    David Mathog wrote:

    > Alex Fraser wrote:
    >
    > > An alternative is to open the FIFO for writing immediately after opening it
    > > for reading, and leave both descriptors open (opening it O_RDWR may work;
    > > the behaviour is unspecified by POSIX). This means you will never see EOF
    > > (useful in some cases).

    >
    > I went this route. Now it opens the file, checks the fd with fstat() to
    > see if it is a FIFO, and if it is, it opens the same file for write.
    >
    > Unfortunately it (still) locks on the first open() of the FIFO unless
    > there is already data waiting there. I do not think there is a way
    > around that, since the program cannot set read nonblocking until it has
    > a read fd, and it cannot get a read fd until the file is opened. The
    > program could use stat() first to see if it is a FIFO before opening it
    > for read, and do the open for write first, then push a byte or two into
    > the FIFO so the open for read won't block. But that isn't safe, since
    > the program has no way of knowing if there is data in the FIFO at that
    > point. Better to live with the block on open for read I guess.


    Does the O_NONBLOCK option to open(2) help?

    --
    Barry Margolin, barmar@alum.mit.edu
    Arlington, MA
    *** PLEASE post questions in newsgroups, not directly to me ***
    *** PLEASE don't copy me on replies, I'll read them in the group ***

  5. Re: use of select() on FIFO after it has closed

    Barry Margolin wrote:
    >
    > Does the O_NONBLOCK option to open(2) help?


    (Sheepishly) Yes, that did it.

    Thanks,

    David Mathog

  6. Re: use of select() on FIFO after it has closed

    "David Mathog" wrote in message
    news:fq1gl6$11o$1@naig.caltech.edu...
    > Barry Margolin wrote:
    >>
    >> Does the O_NONBLOCK option to open(2) help?

    >
    > (Sheepishly) Yes, that did it.


    Ignoring O_RDWR (undefined by POSIX for a FIFO), open(fifo, O_RDONLY |
    O_NONBLOCK) then open(fifo, O_WRONLY) is the only way because open(fifo,
    O_WRONLY) blocks until the FIFO is open for reading and open(fifo, O_WRONLY
    | O_NONBLOCK) returns an error (ENXIO) if the FIFO is not open for reading.

    Alex



+ Reply to Thread