If ServerAliveInterval should work even if the client keeps trying to
send data, then please consider this patch.
diff --git a/clientloop.c b/clientloop.c
index da396c7..358b526 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -162,6 +162,7 @@ static int connection_out; /* Connection to server
(output). */
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
static int session_closed; /* In SSH2: login session closed. */
static u_int x11_refuse_time; /* If >0, refuse x11 opens after this
time. */
+static time_t server_alive_time; /* Time to do server_alive_check */
static void client_init_dispatch(struct ssh *ssh);
int session_ident = -1;
@@ -495,7 +496,7 @@ client_wait_until_can_do_something(struct ssh *ssh,
{
struct timeval tv, *tvp;
int timeout_secs;
- time_t minwait_secs = 0, server_alive_time = 0, now = monotime();
+ time_t minwait_secs = 0, now = monotime();
int r, ret;
/* Add any selections by the channel mechanism. */
@@ -525,8 +526,9 @@ client_wait_until_can_do_something(struct ssh *ssh,
timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
if (options.server_alive_interval > 0) {
- timeout_secs = options.server_alive_interval;
- server_alive_time = now + options.server_alive_interval;
+ timeout_secs = server_alive_time - now;
+ if (timeout_secs < 0)
+ timeout_secs = 0;
}
if (options.rekey_interval > 0 && !rekeying)
timeout_secs = MINIMUM(timeout_secs,
@@ -565,13 +567,14 @@ client_wait_until_can_do_something(struct ssh *ssh,
"select: %s\r\n", strerror(errno))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
quit_pending = 1;
- } else if (ret == 0) {
- /*
- * Timeout. Could have been either keepalive or rekeying.
- * Keepalive we check here, rekeying is checked in clientloop.
- */
- if (server_alive_time != 0 && server_alive_time <= monotime())
+ } else {
+ /* See if keepalive check needs to be done */
+ if (options.server_alive_interval > 0
+ && ! FD_ISSET(connection_in, *readsetp)
+ && (now = monotime()) >= server_alive_time ) {
+ server_alive_time = now + options.server_alive_interval;
server_alive_check(ssh);
+ }
}
}
@@ -613,6 +616,8 @@ client_process_net_input(struct ssh *ssh, fd_set
*readset)
* the packet subsystem.
*/
if (FD_ISSET(connection_in, readset)) {
+ if (options.server_alive_interval > 0)
+ server_alive_time = monotime() + options.server_alive_interval;
/* Read as much as possible. */
len = read(connection_in, buf, sizeof(buf));
if (len == 0) {
@@ -1314,6 +1319,9 @@ client_loop(struct ssh *ssh, int have_pty, int
escape_char_arg,
client_channel_closed, 0);
}
+ if (options.server_alive_interval > 0)
+ server_alive_time = monotime() + options.server_alive_interval;
+
/* Main loop of the client for the interactive session mode. */
while (!quit_pending) {
On 5/23/20 4:36 PM, J Raynor wrote:
The ServerAliveInterval option is supposed to check the connection "if
no data has been received from the server" during the interval.
However, if the client side keeps trying to write data, the check is
never performed.
For example, run this command:
while true; do date ; sleep 3; done | ssh -o ServerAliveInterval=10 -o
ServerAliveCountMax=2 YourSshServer cat
Once the connection is established, break the communication between
the client and server. For example, add a bad route to the client on
YourSshServer, or take down the server's network interface, or pause
the server if it is a VM.
Once the communication is broken, given the options listed above, the
connection should time out in about 20 seconds. But it won't. It
appears to stay alive until a tcp timeout occurs.
Is the ServerAliveInterval option only supposed to work if the client
is idle? Or, at least, only if the client tries to transmit data less
often than the interval?
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev