kern/94772: FIFOs (named pipes) + select() == broken
Bruce Evans
bde at zeta.org.au
Fri Mar 24 13:20:26 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 00:19:33 +1100 (EST)
On Thu, 23 Mar 2006, Oliver Fromme wrote:
> Bruce Evans wrote:
> > I thought that the signal() was portable.
>
> Unfortunately, it's not. SysV (e.g. Solaris) has different
> semantics: When the signal handler is executed, the signal's
> disposition is set to SIG_DFL. That means that the handler
Oops, I forgot that SysV signal handling is broken.
> On Linux, the situation is even more complex: When using
> libc4 or libc5, signal() has SysV semantics, and when using
> glibc2, it has BSD semantics. However, when using glibc2
> with -D_XOPEN_SOURCE=500, it's again SysV, and in this
> latter case sigset() is defined in the header file (not
> in the other cases).
I forgot that too. I now remember being surprised when Linux
defaulted to the SySV signal() brokenness and other SysV mistakes
(like termio.h instead of POSIX termios.h). I stopped keeping
track of Linux userland at much the same time that it started
switching to BSD signal(). Of course, switching made the mess
larger.
> > Under FreeBSD, <stdlib.h>
> > of all things is the only missing include.
>
> FreeBSD generally seems to require less includes than the
> standard says. I had to add <sys/types.h>, <stdlib.h>,
> <string.h> and <stdio.h> (although the latter two probably
> only because of my err() and warnx() replacements).
<sys/types.h> used to be standard (required by POSIX.1-1990),
but this was fixed in POSIX.1-2001 or earlier, and FreeBSD
(mainly mike@, who seems to have departed :() cleaned up the
most important headers so that they don't need <sys/types.h>.
> > ..
> > but not for poll(). From POSIX.1-2001-draft7.txt for pselect():
> I've got SUSv3 a.k.a. IEEE Std 1003.1-2001 ("POSIX"). You
> can download it from The Open Group's website (you have to
> register with them, but it's free). However, I don't know
> how much it differs from the draft that you have.
I'm already registered and sometimes look at the web site, but
grepping draft7 mostly works better.
> > Other parts of POSIX make it clear that O_NONBLOCK reads must never block,
>
> That's right, but it does not matter for select()/poll().
>
> > so if O_NONBLOCK is set then pselect() for read must never block either.
>
> No, I think that's not right. The standard clearly says
> that select() should always behave as if O_NONBLOCK was not
> set: "A descriptor shall be considered ready for reading
> when a call to an input function with O_NONBLOCK clear
> would not block".
Oops. So select() must not block when there are no writers because that
state is special for read() -- read() doesn't block waiting for writers.
BTW, in private (?) followup to one of the #76xxx PRs mentioned in this
thread, it was pointed out that this is a problem -- at least if poll()
does the same, there is no good way to wait for a writer. I said that
a blocking open could be used (while keeping the original fd open), but
the original poster pointed out the problem with that -- it requires a
separate thread for each fd being waited on. This is the best argument
that I know of for having Linux's poll() behaviour. I think it would be
better for a writer appearing to be an exceptional event for select()
and a POLLWRITER event for poll().
> > This might be clearer with SBS_CANTSENDMORE checked first.
> > SBS_CANTSENDMORE set implies !sowriteable() so the behaviour is the same,
> > and I think it is clearer to not even look at the output bits in
> > `events' in the hangup case.
>
> So you mean in the SBS_CANTSENDMORE case, POLLHUP should be
> set without checking if the caller has requested POLLOUT in
> the events mask? That sounds reasonable, because POLLOUT
> certainly can't be returned in that case. It makes the
> code more complex, though.
Yes. POLLHUP Is also needed for making poll() return for poll()
waiting for input only. I think it would make the code slightly
less complex.
> Bruce Evans wrote:
> > Bruce Evans wrote:
> > > I intened to check the behaviour for this in my test programs but don't
> > > seem to have done it. I intended to follow Linux's behaviour even if this
> > > is nonstandard. Linux used to have some special cases including a gripe
> > > in a comment about having to have them to match Sun's behaviour, but I
> > > couldn't find these when I last checked. Perhaps the difference is
> > > precisely between select() and poll(), to follow the standard for select()
> > > and exploit the fuzziness for poll().
> >
> > I added the check.
>
> I'll try that later today. (At least I hope to have enough
> time for it.)
I'm interested in what non-Linux non-FreeBSD systems do. I won't have time
to look at your patches today :-).
> > 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. In fact, when I open a FIFO which doesn't have a
> writer currently, there's no way to know if there was a
> writer previously (before I opened the FIFO) who "hung it
> up".
>
> Personally I think that Linux is in error. POLLHUP should
> be set when "the device is disconnected" (SUSv3), i.e. when
> there is no writer, period.
I tend to agree, but trying to keep the semantics as simple as
that is half of what caused this bug suite (the other half is
not implementing POLLHUP).
> However, I see your point that it might be more beneficial
> to be Linux-compliant instead of standard-compliant.
Hmm, the regression test needs to be even more delicate to test
the timing of previous hangups. FreeBSD clears the hangup flag
on transition from 0 to 1 readers, so history of connections
is handled reasonably well.
Bruce
More information about the freebsd-bugs
mailing list