Re: [Patch][RFC] epoll and half closed TCP connections

Jamie Lokier (jamie@shareable.org)
Sun, 13 Jul 2003 20:15:59 +0100


Davide Libenzi wrote:
> > However, if a program is waiting on POLLRDHUP, you don't want the
> > program to have to say "if this fd is a TCP socket then listen for
> > POLLRDHUP else if this fd is another kind of socket call read to
> > detect EOF else listen for POLLHUP". Programs have enough
> > version-specific special cases as it is.
> >
> > - Everywhere that POLLHUP is currently set in a driver, socket etc.
> > it should set POLLRDHUP|POLLHUP - unless it specifically knows
> > about POLLRDHUP as in TCP (and presumably UDP, SCTP etc).
>
> Returning POLLHUP to a caller waiting for POLLIN might break existing code
> IMHO.

Oh, agreed. I was(*) suggesting to add POLL_RDHUP to the set of
events reported by e.g. AF_UNIX sockets which are half-closed. Not to
add POLLHUP to anything! (Particularly as POLLHUP can't be ignored).

> After ppl reporting the O_RDONLY|O_TRUNC case I'm inclined to expect
> everything from existing apps ;) POLLHUP should be returned to apps
> waiting for POLLOUT while POLLRDHUP to ones for POLLIN.

Not sure exactly how you're thinking with that last sentence.

At present, it's impossible for socket code to return POLLHUP only to
apps which are waiting on POLLOUT - because POLLHUP is not maskable in
sys_poll's API. Therefore sockets return POLLHUP only if they are
closed in both directions.

There is no way for a socket to return a HUP condition for someone who
is waiting only to write, but fortunately that doesn't matter :)

Back to the (*), (see above):

(*) There aren't that many places which set POLLHUP; they divide into:
sockets, ttys, SCSI-generic and PPP. The latter two are not important
as they don't do half-close.

__The critical thing with POLL_RDHUP is that it is set if read() would
return EOF after returning data.__

If this condition isn't met, than an app which is using POLL_RDHUP to
optimise performance using epoll will hang occasionally.

Sockets are important: TCP is not the only thing to support
half-closing. If an app is waiting for POLLRDHUP, and it doesn't know
what kind of socket it has been given (e.g. AF_UNIX), the network
stack had better return POLL_RDHUP when there's an EOF pending.

So we'd better add POLLRDHUP to all the socket types which do
half-closing. For the rest, no change is required as POLLHUP is
non-maskable :) (So apps should always say "if (events &
(POLLHUP|POLLRDHUP)) check_for_eof()").

And ttys? They are problematic, because ttys can return EOF _after_
returning data without closing (and without being hung-up). An epoll
loop which is reading a tty (and isn't programmed specially for a tty)
_must_ receive POLLRDHUP when the EOF is pending, else it may hang.

In other words, POLLRDHUP is the wrong name: the correct name is
POLLRDEOF.

-- Jamie
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/