kern/94772: FIFOs (named pipes) + select() == broken
Oliver Fromme
olli at lurza.secnetix.de
Thu Mar 23 22:10:31 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 23:05:17 +0100 (CET)
OK, here are new patches. I wrote and tested them on
RELENG_6, but they should apply to HEAD as well, AFAICT.
With these patches, all of the test programs pass with
success (no output), i.e. the select test and the poll
test. My own test program from the beginning of this
PR passes without problems, too.
Best regards
Oliver
--- ./fs/fifofs/fifo_vnops.c.orig Tue Mar 21 09:42:32 2006
+++ ./fs/fifofs/fifo_vnops.c Thu Mar 23 19:57:21 2006
@@ -231,6 +231,12 @@
wakeup(&fip->fi_writers);
sowwakeup(fip->fi_writesock);
}
+ else if (ap->a_mode & O_NONBLOCK) {
+ SOCKBUF_LOCK(&fip->fi_readsock->so_rcv);
+ fip->fi_readsock->so_rcv.sb_state |=
+ SBS_EOFNOHUP;
+ SOCKBUF_UNLOCK(&fip->fi_readsock->so_rcv);
+ }
}
}
if (ap->a_mode & FWRITE) {
@@ -241,7 +247,8 @@
fip->fi_writers++;
if (fip->fi_writers == 1) {
SOCKBUF_LOCK(&fip->fi_readsock->so_rcv);
- fip->fi_readsock->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
+ fip->fi_readsock->so_rcv.sb_state &=
+ ~(SBS_CANTRCVMORE | SBS_EOFNOHUP);
SOCKBUF_UNLOCK(&fip->fi_readsock->so_rcv);
if (fip->fi_readers > 0) {
wakeup(&fip->fi_readers);
@@ -661,37 +668,23 @@
int levents, revents = 0;
fip = fp->f_data;
- levents = events &
- (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND);
+ levents = events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND);
if ((fp->f_flag & FREAD) && levents) {
- /*
- * If POLLIN or POLLRDNORM is requested and POLLINIGNEOF is
- * not, then convert the first two to the last one. This
- * tells the socket poll function to ignore EOF so that we
- * block if there is no writer (and no data). Callers can
- * set POLLINIGNEOF to get non-blocking behavior.
- */
- if (levents & (POLLIN | POLLRDNORM) &&
- !(levents & POLLINIGNEOF)) {
- levents &= ~(POLLIN | POLLRDNORM);
- levents |= POLLINIGNEOF;
- }
-
filetmp.f_data = fip->fi_readsock;
filetmp.f_cred = cred;
revents |= soo_poll(&filetmp, levents, cred, td);
-
- /* Reverse the above conversion. */
- if ((revents & POLLINIGNEOF) && !(events & POLLINIGNEOF)) {
- revents |= (events & (POLLIN | POLLRDNORM));
- revents &= ~POLLINIGNEOF;
- }
}
levents = events & (POLLOUT | POLLWRNORM | POLLWRBAND);
if ((fp->f_flag & FWRITE) && levents) {
filetmp.f_data = fip->fi_writesock;
filetmp.f_cred = cred;
revents |= soo_poll(&filetmp, levents, cred, td);
+ }
+ if (revents & POLLHUP) {
+ SOCKBUF_LOCK(&fip->fi_readsock->so_rcv);
+ if (fip->fi_readsock->so_rcv.sb_state & SBS_EOFNOHUP)
+ revents = (revents & ~POLLHUP) | POLLHUPIGNEOF;
+ SOCKBUF_UNLOCK(&fip->fi_readsock->so_rcv);
}
return (revents);
}
--- ./kern/uipc_socket.c.orig Wed Dec 28 19:05:13 2005
+++ ./kern/uipc_socket.c Thu Mar 23 22:50:33 2006
@@ -2033,16 +2033,15 @@
SOCKBUF_LOCK(&so->so_snd);
SOCKBUF_LOCK(&so->so_rcv);
if (events & (POLLIN | POLLRDNORM))
- if (soreadable(so))
- revents |= events & (POLLIN | POLLRDNORM);
-
- if (events & POLLINIGNEOF)
if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat ||
!TAILQ_EMPTY(&so->so_comp) || so->so_error)
- revents |= POLLINIGNEOF;
+ revents |= events & (POLLIN | POLLRDNORM);
- if (events & (POLLOUT | POLLWRNORM))
- if (sowriteable(so))
+ if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) ||
+ (so->so_snd.sb_state & SBS_CANTSENDMORE))
+ revents |= POLLHUP;
+ else
+ if (events & (POLLOUT | POLLWRNORM) && sowriteable(so))
revents |= events & (POLLOUT | POLLWRNORM);
if (events & (POLLPRI | POLLRDBAND))
@@ -2050,9 +2049,7 @@
revents |= events & (POLLPRI | POLLRDBAND);
if (revents == 0) {
- if (events &
- (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM |
- POLLRDBAND)) {
+ if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
selrecord(td, &so->so_rcv.sb_sel);
so->so_rcv.sb_flags |= SB_SEL;
}
--- ./kern/sys_generic.c.orig Thu Jul 7 20:17:55 2005
+++ ./kern/sys_generic.c Thu Mar 23 19:58:03 2006
@@ -1027,7 +1027,7 @@
* POLLERR if appropriate.
*/
fds->revents = fo_poll(fp, fds->events,
- td->td_ucred, td);
+ td->td_ucred, td) & ~POLLHUPIGNEOF;
if (fds->revents != 0)
n++;
}
--- ./sys/poll.h.orig Wed Jul 10 06:47:25 2002
+++ ./sys/poll.h Thu Mar 23 19:56:58 2006
@@ -66,9 +66,8 @@
#define POLLRDBAND 0x0080 /* OOB/Urgent readable data */
#define POLLWRBAND 0x0100 /* OOB/Urgent data can be written */
-#if __BSD_VISIBLE
-/* General FreeBSD extension (currently only supported for sockets): */
-#define POLLINIGNEOF 0x2000 /* like POLLIN, except ignore EOF */
+#ifdef _KERNEL
+#define POLLHUPIGNEOF 0x2000
#endif
/*
--- ./sys/socketvar.h.orig Sat Jul 9 14:24:40 2005
+++ ./sys/socketvar.h Thu Mar 23 19:20:25 2006
@@ -215,6 +215,7 @@
#define SBS_CANTSENDMORE 0x0010 /* can't send more data to peer */
#define SBS_CANTRCVMORE 0x0020 /* can't receive more data from peer */
#define SBS_RCVATMARK 0x0040 /* at mark on input */
+#define SBS_EOFNOHUP 0x0080 /* no initial writer */
/*
* Socket state bits stored in so_qstate.
--
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.
More information about the freebsd-bugs
mailing list