Permalink
Browse files

mosh-server: Fix bug where spins forever if process dies while discon…

…nected
  • Loading branch information...
keithw committed Nov 26, 2012
1 parent 6a16eec commit 486325e76bbdf2c658f86f382f7f7b5bd8758e39
Showing with 28 additions and 25 deletions.
  1. +16 −23 src/frontend/mosh-server.cc
  2. +10 −1 src/network/transportsender.cc
  3. +2 −1 src/network/transportsender.h
@@ -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();
- }
- }
-
- string terminal_to_host = terminal.act( string( buf, bytes_read ) );
+ network.start_shutdown();
+ } else {
+ 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 */
@@ -56,6 +56,7 @@ TransportSender<MyState>::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<MyState>::process_acknowledgment_through( uint64_t ack_num
template <class MyState>
bool TransportSender<MyState>::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 */
@@ -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 */

0 comments on commit 486325e

Please sign in to comment.