From 486325e76bbdf2c658f86f382f7f7b5bd8758e39 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 26 Nov 2012 01:45:07 -0500 Subject: [PATCH] mosh-server: Fix bug where spins forever if process dies while disconnected --- src/frontend/mosh-server.cc | 39 ++++++++++++++-------------------- src/network/transportsender.cc | 11 +++++++++- src/network/transportsender.h | 3 ++- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc index 4f7a5eb..e6900ae 100644 --- a/src/frontend/mosh-server.cc +++ b/src/frontend/mosh-server.cc @@ -532,7 +532,8 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network const int timeout_if_no_client = 60000; int timeout = min( network.wait_time(), terminal.wait_time( now ) ); - if ( !network.get_remote_state_num() ) { + if ( (!network.get_remote_state_num()) + || network.shutdown_in_progress() ) { timeout = min( timeout, timeout_if_no_client ); } @@ -542,7 +543,9 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network assert( fd_list.size() == 1 ); /* servers don't hop */ int network_fd = fd_list.back(); sel.add_fd( network_fd ); - sel.add_fd( host_fd ); + if ( !network.shutdown_in_progress() ) { + sel.add_fd( host_fd ); + } int active_fds = sel.select( timeout ); if ( active_fds < 0 ) { @@ -618,7 +621,7 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network } } - if ( sel.read( host_fd ) ) { + if ( (!network.shutdown_in_progress()) && sel.read( host_fd ) ) { /* input from the host needs to be fed to the terminal */ const int buf_size = 16384; char buf[ buf_size ]; @@ -630,23 +633,17 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network EIO (see #264). So we treat errors on read() like EOF. */ if ( bytes_read <= 0 ) { bytes_read = 0; - if ( !network.has_remote_addr() ) { - spin(); /* let 60-second timer take care of this */ - } else if ( !network.shutdown_in_progress() ) { - network.start_shutdown(); - } - } + network.start_shutdown(); + } else { + string terminal_to_host = terminal.act( string( buf, bytes_read ) ); - string terminal_to_host = terminal.act( string( buf, bytes_read ) ); - - /* update client with new state of terminal */ - if ( !network.shutdown_in_progress() ) { + /* update client with new state of terminal */ network.set_current_state( terminal ); - } - /* write any writeback octets back to the host */ - if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) { - break; + /* write any writeback octets back to the host */ + if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) { + break; + } } } @@ -664,13 +661,9 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network break; } - if ( sel.error( host_fd ) ) { + if ( (!network.shutdown_in_progress()) && sel.error( host_fd ) ) { /* host problem */ - if ( network.has_remote_addr() ) { - network.start_shutdown(); - } else { - spin(); /* let 60-second timer take care of this */ - } + network.start_shutdown(); } /* quit if our shutdown has been acknowledged */ diff --git a/src/network/transportsender.cc b/src/network/transportsender.cc index 497d9ea..e641655 100644 --- a/src/network/transportsender.cc +++ b/src/network/transportsender.cc @@ -56,6 +56,7 @@ TransportSender::TransportSender( Connection *s_connection, MyState &in verbose( false ), shutdown_in_progress( false ), shutdown_tries( 0 ), + shutdown_start( -1 ), ack_num( 0 ), pending_data_ack( false ), SEND_MINDELAY( 8 ), @@ -357,7 +358,15 @@ void TransportSender::process_acknowledgment_through( uint64_t ack_num template bool TransportSender::shutdown_ack_timed_out( void ) const { - return shutdown_tries >= SHUTDOWN_RETRIES; + if ( shutdown_in_progress ) { + if ( shutdown_tries >= SHUTDOWN_RETRIES ) { + return true; + } else if ( timestamp() - shutdown_start >= uint64_t( ACTIVE_RETRY_TIMEOUT ) ) { + return true; + } + } + + return false; } /* Executed upon entry to new receiver state */ diff --git a/src/network/transportsender.h b/src/network/transportsender.h index 0a205e1..572c47f 100644 --- a/src/network/transportsender.h +++ b/src/network/transportsender.h @@ -94,6 +94,7 @@ namespace Network { bool verbose; bool shutdown_in_progress; int shutdown_tries; + uint64_t shutdown_start; /* information about receiver state */ uint64_t ack_num; @@ -132,7 +133,7 @@ namespace Network { void remote_heard( uint64_t ts ) { last_heard = ts; } /* Starts shutdown sequence */ - void start_shutdown( void ) { shutdown_in_progress = true; } + void start_shutdown( void ) { if ( !shutdown_in_progress ) { shutdown_start = timestamp(); shutdown_in_progress = true; } } /* Misc. getters and setters */ /* Cannot modify current_state while shutdown in progress */