kern/94772: FIFOs (named pipes) + select() == broken
Bruce Evans
bde at zeta.org.au
Sat Mar 25 05:10:27 UTC 2006
The following reply was made to PR kern/94772; it has been noted by GNATS.
From: Bruce Evans <bde at zeta.org.au>
To: Oliver Fromme <olli at lurza.secnetix.de>
Cc: bug-followup at freebsd.org
Subject: Re: kern/94772: FIFOs (named pipes) + select() == broken
Date: Sat, 25 Mar 2006 16:00:30 +1100 (EST)
On Thu, 23 Mar 2006, Oliver Fromme wrote:
> 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).
It's fairly subtle even for a native speaker. (I think it would look
like a larger difference for a non-native speaker, but you know
English too well :-). It's not quite precise enough for a standard
since the literal English meaning would cover all past disconnections
(unless we consider a fifo to be a virtual device whose life began
on the previous "first" open by a reader or a writer).
> So I agree with you that FreeBSD should behave the same as
> Linux in that regard.
> 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.
I'm not sure that SBS_EOFNOHUP is needed. SBS_CANTRCVMORE might
be sufficient. It is cleared when someone opens the FIFO for
writing. Also, the O_NONBLOCK open for read() shouldn't be very
different, since in addition to previously discussed reasons the
SBS flags are per-socket so they can't be used to give different
behaviour for a mix of nonblocking and blocking reads.
> 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?
Good. I'll reply to the mail that has the patch.
Bruce
More information about the freebsd-bugs
mailing list