> Back in imapd.c, cmd_idle() only reads from the client socket if
> IDLE_INPUT is flagged. Which it's not after a select timeout, so if
> tcp_keepalive has detected a connection dropout, cyrus still doesn't
> know about it.
So tcp_keepalive and select() timeout are unrelated. It appears the
point of a select() timeout is just a "defensive" measure, as the
comment that sets up the timeout notes:
/* maximum possible timeout before we double-check anyway */
timeout.tv_sec = idle_timeout;
timeout.tv_usec = 0;
So if the timeout is hit, we fall out of imap_idle(), do an index check
and alert check, and if nothing has changed, go back into imap_idle().
In theory, this timeout shouldn't actually be needed really.
But that's unreleated to tcp_keepalive. In the tcp_keepalive case, if
the connection has been "cut", then eventually the keepalive will detect
that, and mark the socket as EOF. In that case, select() will return
with "read available on client fd" case, because:
Those listed in readfds will be watched to see if characters become
available for reading (more precisely, to see if a read will not
block; in particular, a file descriptor is also ready on end-of-file)
Which will go into this path:
if (r > 0 && otherfd >= 0 && FD_ISSET(otherfd, &rfds))
flags |= IDLE_INPUT;
So it should return IDLE_INPUT flags, which should catch the EOF
condition up a layer.
So I'm not sure how an IDLE connection doesn't eventually hang up if
tcp_keepalive has been enabled.