I have a set of TCP sockets with keep-alive (interval 1 min), controlled by a select(2)
loop (selecting for read).
select(2)
return an error if keep-alive timeout has happened for one of the sockets in the set?read(2)
return?select()
itself does not return an error if an error is signalled for one of the sockets it is selecting for. [Indeed, the API can't indicate per-socket errors this way, because two different sockets could each acquire a pending error during a single call of select()
. Which one would select()
return?]select()
loop, you instead use the FD_ISSET macro to attempt a read()
on each socket marked readable.select()
returns, allowing you to pick up timed-out errors due to keep-alive immediately. Note that select marking a socket for read does not indicate that there is data to read, only that an attempt to read will not block. If the socket has a pending error to retrieve, reading will not block. Both read(2)
and write(2)
first retrieve any pending error on the socket before even attempting to handle any data.
A descriptor shall be considered ready for reading when a call to an input function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully. (The function might return data, an end-of-file indication, or an error other than one indicating that it is blocked, and in each of these cases the descriptor shall be considered ready for reading.) [POSIX:select()]
ETIMEDOUT
if the other end vanishes totally. If a packet delivery error occurs, you'll get that through instead (so if the keep-alive packet gets an ICMP error reply, like "host unreachable", you'll have EHOSTUNREACH
delivered). [For more details on these cases, see Stevens, "Unix Network Programming, vol 1".]If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With