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