mosh-server: Fix bug where spins forever if process dies while disconnected
This commit is contained in:
@@ -532,7 +532,8 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network
|
|||||||
|
|
||||||
const int timeout_if_no_client = 60000;
|
const int timeout_if_no_client = 60000;
|
||||||
int timeout = min( network.wait_time(), terminal.wait_time( now ) );
|
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 );
|
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 */
|
assert( fd_list.size() == 1 ); /* servers don't hop */
|
||||||
int network_fd = fd_list.back();
|
int network_fd = fd_list.back();
|
||||||
sel.add_fd( network_fd );
|
sel.add_fd( network_fd );
|
||||||
|
if ( !network.shutdown_in_progress() ) {
|
||||||
sel.add_fd( host_fd );
|
sel.add_fd( host_fd );
|
||||||
|
}
|
||||||
|
|
||||||
int active_fds = sel.select( timeout );
|
int active_fds = sel.select( timeout );
|
||||||
if ( active_fds < 0 ) {
|
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 */
|
/* input from the host needs to be fed to the terminal */
|
||||||
const int buf_size = 16384;
|
const int buf_size = 16384;
|
||||||
char buf[ buf_size ];
|
char buf[ buf_size ];
|
||||||
@@ -630,25 +633,19 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network
|
|||||||
EIO (see #264). So we treat errors on read() like EOF. */
|
EIO (see #264). So we treat errors on read() like EOF. */
|
||||||
if ( bytes_read <= 0 ) {
|
if ( bytes_read <= 0 ) {
|
||||||
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 */
|
/* update client with new state of terminal */
|
||||||
if ( !network.shutdown_in_progress() ) {
|
|
||||||
network.set_current_state( terminal );
|
network.set_current_state( terminal );
|
||||||
}
|
|
||||||
|
|
||||||
/* write any writeback octets back to the host */
|
/* write any writeback octets back to the host */
|
||||||
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( sel.any_signal() ) {
|
if ( sel.any_signal() ) {
|
||||||
/* shutdown signal */
|
/* shutdown signal */
|
||||||
@@ -664,13 +661,9 @@ void serve( int host_fd, Terminal::Complete &terminal, ServerConnection &network
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sel.error( host_fd ) ) {
|
if ( (!network.shutdown_in_progress()) && sel.error( host_fd ) ) {
|
||||||
/* host problem */
|
/* host problem */
|
||||||
if ( network.has_remote_addr() ) {
|
|
||||||
network.start_shutdown();
|
network.start_shutdown();
|
||||||
} else {
|
|
||||||
spin(); /* let 60-second timer take care of this */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* quit if our shutdown has been acknowledged */
|
/* quit if our shutdown has been acknowledged */
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ TransportSender<MyState>::TransportSender( Connection *s_connection, MyState &in
|
|||||||
verbose( false ),
|
verbose( false ),
|
||||||
shutdown_in_progress( false ),
|
shutdown_in_progress( false ),
|
||||||
shutdown_tries( 0 ),
|
shutdown_tries( 0 ),
|
||||||
|
shutdown_start( -1 ),
|
||||||
ack_num( 0 ),
|
ack_num( 0 ),
|
||||||
pending_data_ack( false ),
|
pending_data_ack( false ),
|
||||||
SEND_MINDELAY( 8 ),
|
SEND_MINDELAY( 8 ),
|
||||||
@@ -357,7 +358,15 @@ void TransportSender<MyState>::process_acknowledgment_through( uint64_t ack_num
|
|||||||
template <class MyState>
|
template <class MyState>
|
||||||
bool TransportSender<MyState>::shutdown_ack_timed_out( void ) const
|
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 */
|
/* Executed upon entry to new receiver state */
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ namespace Network {
|
|||||||
bool verbose;
|
bool verbose;
|
||||||
bool shutdown_in_progress;
|
bool shutdown_in_progress;
|
||||||
int shutdown_tries;
|
int shutdown_tries;
|
||||||
|
uint64_t shutdown_start;
|
||||||
|
|
||||||
/* information about receiver state */
|
/* information about receiver state */
|
||||||
uint64_t ack_num;
|
uint64_t ack_num;
|
||||||
@@ -132,7 +133,7 @@ namespace Network {
|
|||||||
void remote_heard( uint64_t ts ) { last_heard = ts; }
|
void remote_heard( uint64_t ts ) { last_heard = ts; }
|
||||||
|
|
||||||
/* Starts shutdown sequence */
|
/* 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 */
|
/* Misc. getters and setters */
|
||||||
/* Cannot modify current_state while shutdown in progress */
|
/* Cannot modify current_state while shutdown in progress */
|
||||||
|
|||||||
Reference in New Issue
Block a user