Date: Thu, 23 Mar 2006 22:10:25 GMT From: Oliver Fromme <olli@lurza.secnetix.de> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/94772: FIFOs (named pipes) + select() == broken Message-ID: <200603232210.k2NMAP95032679@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: Oliver Fromme <olli@lurza.secnetix.de> To: bde@zeta.org.au (Bruce Evans) Cc: bug-followup@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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603232210.k2NMAP95032679>