net: Make select() not spurious
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 19 Dec 2017 23:12:48 +0000 (18:12 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 20 Dec 2017 18:37:08 +0000 (13:37 -0500)
commitd9b8448e5351433ab9cd5bb874fc013887bc0e0b
tree21626d2403512d70615a95b65d8bde2cad645376
parent0965931a0a80aef1fe60339d7c070ad2d3ebff0f
net: Make select() not spurious

Our old select() was spurious - in the event there was some race, or even
some potential race, we'd say that all of the FDs had some action.  For
instance, when we first added an FD to the epoll set, we could have missed
an event: say it happened!  Or if we might have had another thread consume
our event: say it happened!

This was OK for a while, but it break with non-blocking connect().  Calls
like read() and write() are often in a loop, so a spurious event isn't a
big deal.  But with connect(), once the app is told the connect is done,
they expect either completion or failure.

Originally, we never polled the FDs with fstat.  Over time, it turns out
that we needed to, such as for apps that call select() even though they
didn't drain them to empty (which would trigger an edge event later).  Now
that we have that polling method (fstat + appropriate support for
readable/writable bits) we can redo select such that we do not return
spurious events.

This might be broken, especially for FDs on devices that don't support the
necessary stat bits.  So far, it's been working with sshd and port
forwarding (which uses non-blocking connects).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/iplib/select.c