Date: Fri, 24 Mar 2006 13:20:25 GMT From: Bruce Evans <bde@zeta.org.au> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/94772: FIFOs (named pipes) + select() == broken Message-ID: <200603241320.k2ODKPXd087861@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/94772; it has been noted by GNATS. From: Bruce Evans <bde@zeta.org.au> To: Oliver Fromme <olli@lurza.secnetix.de> Cc: bug-followup@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603241320.k2ODKPXd087861>