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