NAB - Re: kern/76525: select() hangs on EOF from named pipe (FIFO)

Dorr H. Clark dclark at applmath.scu.edu
Sat Apr 9 13:50:34 PDT 2005


The following reply was made to PR kern/76525; it has been noted by GNATS.

From: "Dorr H. Clark" <dclark at applmath.scu.edu>
To: freebsd-gnats-submit at FreeBSD.org, defuller at lbl.gov
Cc:  
Subject: NAB - Re: kern/76525: select() hangs on EOF from named pipe (FIFO)
Date: Sat, 09 Apr 2005 13:49:10 -0700

 We believe that the behavior of select() on fifo
 in the absence of a writer is the desired behavior of FreeBSD5.3
 and is therefore not a bug.
 
 We propose the following fix to the bug author's source code fifo.c
 
 --- fifo_orig.c Sun Mar 13 08:54:14 2005
 +++ fifo.c      Sun Mar 13 09:45:30 2005
 @@ -4,26 +4,21 @@
   #include <sys/time.h>
   #include <unistd.h>
   #include <fcntl.h>
 +#include <sys/poll.h>
 
   const char      FIFO[] = "/tmp/fifo";
 
   void
   look(int fd)
   {
 -        fd_set  readfds, excepfds;
 +        struct pollfd poll_list[1];
 
 -        FD_ZERO(&readfds);
 -        FD_ZERO(&excepfds);
 -        FD_SET(fd, &readfds);
 -        FD_SET(fd, &excepfds);
 -        if (select(fd+1, &readfds, NULL, &excepfds, NULL) < 0) {
 -                perror("select");
 +        poll_list[0].fd = fd;
 +        poll_list[0].events = POLLIN|POLLINIGNEOF;
 +        if (poll(poll_list , 1, -1) < 0) {
 +                perror("poll");
                   exit(1);
           }
 -        if (FD_ISSET(fd, &excepfds))
 -                puts("Exception on FIFO");
 -        if (FD_ISSET(fd, &readfds))
 -                puts("FIFO available for read");
   }
 
 In FreeBSD4.x, select() on fifo always returned when there was no
 writer.  In FreeBSD5.x, select() on fifo was changed to block
 in the absence of a writer.
 
 Historically, some users have desired select() to block waiting for a
 writer to appear.  They want fifo to behave as a data source without
 worrying about connections coming and going, but there are also
 users who want select() to return in the absence of a writer.
 
 This disagreement has played out in CVS, specifically
 /usr/src/sys/fs/fifofs/fifo_vnops.c has experienced
 a series of changes, alternating between blocking
 and non-blocking behavior for select().
 
 The following CVS revisions are relevant:
 In 1.40, select() on fifo with no writer did not block.
 In 1.56 it was restored to blocking.  In revision 1.62,
 the fixes of 1.40 were restored but select() on fifo was
 made to block waiting for a writer to appear.
 
 Also, a new event bitmask, POLLINIGNEOF for poll() has been
 implemented.  If the users want non-blocking behavior
 when there is no writer, they can call poll() instead,
 setting the event bitmask POLLINIGNEOF.  To illustrate,
 we have implemented this change in the bug author's test program.
 
 We also believe that the current 5.x behavior is consistent
 with the POSIX.1 standard as well as the overall intent
 of select(), but we are aware that this interpretation
 is not universally shared.
 
 If the current behavior of select() on fifo,
 is not desirable, the following patch can be applied to
 filo_poll() in fifo_vnops.c, which reverses the select()
 behavior for fifo by reverting it to non-blocking.Users
 need to set the event bitmask POLLINIGNEOF to get blocking
 behavior.
 
 While offering the change, we would like to reiterate
 that we believe the change is inappropriate (inconsistent
 with POSIX.1) and should not be captured into CVS.
 
 --- fifo_vnops_orig.c   Wed Mar 16 16:13:24 2005
 +++ fifo_vnops.c        Wed Mar 16 16:25:12 2005
 @@ -531,7 +531,7 @@
                   * set POLLINIGNEOF to get non-blocking behavior.
                   */
                  if (events & (POLLIN | POLLRDNORM) &&
 -                   !(events & POLLINIGNEOF)) {
 +                   (events & POLLINIGNEOF)) {
                          events &= ~(POLLIN | POLLRDNORM);
                          events |= POLLINIGNEOF;
                  }
 @@ -544,7 +544,7 @@
 
                  /* Reverse the above conversion. */
                  if ((revents & POLLINIGNEOF) &&
 -                   !(ap->a_events & POLLINIGNEOF)) {
 +                   (ap->a_events & POLLINIGNEOF)) {
                          revents |= (ap->a_events & (POLLIN | POLLRDNORM));
                          revents &= ~POLLINIGNEOF;
                  }
 
 
 
 Shikha Shrivastava, engineer
 Dorr H. Clark, advisor
 COEN 284 - Operating Systems Case Study
 Santa Clara University,
 Santa Clara CA.


More information about the freebsd-bugs mailing list