kern/94772: FIFOs (named pipes) + select() == broken

Oliver Fromme olli at lurza.secnetix.de
Thu Mar 23 16:30:22 UTC 2006


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

From: Oliver Fromme <olli at lurza.secnetix.de>
To: bde at zeta.org.au (Bruce Evans)
Cc: bug-followup at freebsd.org
Subject: Re: kern/94772: FIFOs (named pipes) + select() == broken
Date: Thu, 23 Mar 2006 17:25:45 +0100 (CET)

 Hi,
 
 I have to correct myself slightly, and I have a few more
 insights ...
 
 Oliver Fromme wrote:
  > Bruce Evans wrote:
  > > select() on a named pipe:
  > > % selectp: state 0: expected set; got clear
  > > [...]
  > > Now there is an extra failure for state 0.  Some complications will be
  > > required to fix this without breaking poll() on named pipe.  State 0 is
  > > when the read descriptor is open with O_NONBLOCK and there has "never"
  > > been a writer.  In this state, select() on the read descriptor must
  > > succeed to conform to POSIX, but poll() on the read descriptor must
  > > block to conform to Linux.  I think the Linux behaviour is what happens
  > > naturally -- the socket isn't hung up so sopoll() won't set POLLHUP,
  > 
  > Now that might be debatable.  SUSv3 says that POLLHUP means
  > that the device is disconnected.  That doesn't sound like
  > it should make a difference if there was a previous writer
  > or not.
 
 SUSv3 says about POLLHUP:  "The device has been disconnected".
 I suppose that "has been disconnected" is different from "is
 disconnected".  I'm sorry, English is not my native language,
 so I didn't notice that slight difference when I read that
 page first.
 
 Thinking about it again, the Linux implementation seems to be
 reasonable, and it's probably conformant with the standard
 (even though the standard is somewhat fuzzy).
 
 So I agree with you that FreeBSD should behave the same as
 Linux in that regard.
 
  > Yes, if we want to be Linux-compliant.  That'll make the
  > code a lot more complicated.  *sigh*
 
 Just to make it clear:  This case happens only if the FIFO
 is opened with O_RDONLY | O_NONBLOCK and there is currently
 no process who has opened the FIFO for writing.
 
 Because "hung up" and "EOF" are different things, a new
 flag is required for the case when no previous writer
 exists (which means "EOF", but not "hung up").  select()
 is only interested in the EOF case, while poll() is only
 interested in the "hung up" case.
 
 I propose a new SBS_* flag for the so_rcv.sb_state mask.
 Lets call it SBS_EOFNOHUP for now (I'm sure someone can
 come up with a better name).  It will be set in fifo_open()
 in the case O_RDONLY | O_NONBLOCK and no writers.  It will
 be cleared in fifo_open() when someone opens the FIFO for
 writing.  In fifo_poll_f(), POLLHUP will be replaced by
 POLLIGNEOF in the result of soo_poll() if SBS_EOFNOHUP is
 set.
 
 selscan() does not need to be changed.  It will handle
 POLLIGNEOF just like POLLHUP, so select() won't block.
 
 pollscan() needs a slight change in order to remove
 POLLIGNEOF from the result of the fo_poll() call.
 I think POLLIGNEOF should not be exposed to userland.
 Its sole purpose is to communicate the abovementioned
 case from fifo_poll_f() to selscan(), and only those
 two functions should use that flag.
 
 That should fix both select() and poll(), if I didn't
 miss anything.
 
 What do you think?
 
 Best regards
    Oliver
 
 -- 
 Oliver Fromme,  secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing
 Dienstleistungen mit Schwerpunkt FreeBSD: http://www.secnetix.de/bsd
 Any opinions expressed in this message may be personal to the author
 and may not necessarily reflect the opinions of secnetix in any way.
 
 $ dd if=/dev/urandom of=test.pl count=1
 $ file test.pl
 test.pl: perl script text executable


More information about the freebsd-bugs mailing list