svn commit: r196460 - head/sys/kern

Jilles Tjoelker jilles at stack.nl
Tue Aug 25 21:08:17 UTC 2009


On Tue, Aug 25, 2009 at 04:07:11AM +1000, Bruce Evans wrote:
> On Sun, 23 Aug 2009, Jilles Tjoelker wrote:

> > I think poll on fifos should instead be fixed by closing the
> > half-connection corresponding to writing from fi_readsock to
> > fi_writesock. I have tried this out, see attached patch. With the patch,
> > pipepoll only gives "expected POLLHUP; got POLLIN | POLLHUP" errors and
> > an error in fifo case 6b caused by our distinction between new and old
> > readers.

> This sort of worked for me, but has several problems:

> % Index: sys/fs/fifofs/fifo_vnops.c
> % ===================================================================
> % --- sys/fs/fifofs/fifo_vnops.c	(revision 196459)
> % +++ sys/fs/fifofs/fifo_vnops.c	(working copy)
> % @@ -193,6 +193,10 @@
> %  			goto fail2;
> %  		fip->fi_writesock = wso;
> %  		error = soconnect2(wso, rso);
> % +		if (error == 0)
> % +			error = soshutdown(rso, SHUT_WR);
> % +		if (error == 0)
> % +			error = soshutdown(wso, SHUT_RD);
> %  		if (error) {
> %  			(void)soclose(wso);
> %  fail2:

> The second soshutdown() is only harmful.  I see the following state changes
> - the first soshutdown() sets SBS_CANTRCVMORE on rso like you would expect,
>    and also sets SBS_CANTSENDMORE on wso.  This gives the desired state.
> - the second soshutdown() then clears SBS_CANTRCVMORE on rso (without
>    the first soshutdown() it leaves both flags clear in both directions).
>    This clobbers the desired state.  The failure shows in just one of my
>    uncommitted regression tests (when there is a writer and there was
>    a reader, poll() returns POLLOUT for the writer, but should return
>    POLLHUP; the missing SBS_CANTRCVMORE on rso prevents it ever returning
>    POLLHUP for writers).

> After removing the second soshutdown() and fixing a spurious POLLIN (see
> below), all my tests pass.

I have removed the second shutdown, it is not necessary.

> Elsewhere, fifo_vnops.c hacks on SBS_CANT*MORE directly.  Perhaps it should
> call soshutdown(), or if the direct access there is safe then it is probably
> safe above.

That's for a later commit to fix.

> % Index: sys/kern/uipc_socket.c
> % ===================================================================
> % --- sys/kern/uipc_socket.c	(revision 196469)
> % +++ sys/kern/uipc_socket.c	(working copy)
> % @@ -2898,11 +2898,13 @@
> %  		if (so->so_oobmark || (so->so_rcv.sb_state & SBS_RCVATMARK))
> %  			revents |= events & (POLLPRI | POLLRDBAND);
> % 
> % -	if ((events & POLLINIGNEOF) == 0)
> % -		if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
> % -			revents |= POLLHUP;
> % -	if (so->so_snd.sb_state & SBS_CANTSENDMORE)
> % -		revents |= POLLHUP;
> % +	if ((events & POLLINIGNEOF) == 0) {

> Old problems become larger:

> I don't like POLLINIGNEOF (for input) affecting POLLHUP for output.  This
> seems to cause no problems for fifos, at least when the kernel sets
> POLLINIGNEOF, but it is hard to understand even why it doesn't cause
> problems, and kib@ wants POLLINIGNEOF to remain user-settable, so the
> complications might remain exported to userland for for fifos and
> sockets, where they are harder to document and understand.

I do not like userland POLLINIGNEOF either. I think programs can do fine
with the standard functionality (closing and reopening a fifo to reset
the POLLHUP state).

> % +			revents |= events & (POLLIN | POLLRDNORM);

> This gives spurious POLLINs when POLLHUP is also returned, and thus defeats
> the point of soreadable_data() being different from soreadable().  Tests
> 6a-6d show the spurious POLLIN.  I don't understand how tests 6a and 6c-6d
> passed for you.

Same problem here. I think kib@ wants to keep this in 8.x for the sake
of buggy programs that do not check for POLLHUP. I suppose we can do it
properly in 9.x.

> % +			if (so->so_snd.sb_state & SBS_CANTSENDMORE)
> % +				revents |= POLLHUP;

> Tests 6a-6d pass with the above 3 lines changed to:

>  			if (so->so_snd.sb_state & SBS_CANTSENDMORE)
>  				revents |= POLLHUP;
>  			else
>  				revents |= events & (POLLIN | POLLRDNORM);

> Returning POLLIN will cause poll() to not block on input descriptors, but
> this seems to be as correct as possible since there really is a read-EOF.
> Applications just can't see this EOF as POLLHUP -- they will see POLLIN
> and have to try to read(), and then interpret read() returning 0 as meaning
> EOF.  Device-independent applications must do precisely this anyway since
> the input descriptor might be a regular file and there is no POLLHUP for
> regular files.

Yes. Even more, any program must handle it because it is also possible
that an EOF happens between poll() and read().

-- 
Jilles Tjoelker


More information about the svn-src-all mailing list