Improve client shutdown robustness
This commit is contained in:
@@ -55,6 +55,7 @@ namespace Network {
|
||||
void start_shutdown( void ) { sender.start_shutdown(); }
|
||||
bool shutdown_in_progress( void ) { return sender.get_shutdown_in_progress(); }
|
||||
bool shutdown_acknowledged( void ) { return sender.get_shutdown_acknowledged(); }
|
||||
bool shutdown_ack_timed_out( void ) { return sender.shutdown_ack_timed_out(); }
|
||||
bool attached( void ) { return connection.get_attached(); }
|
||||
|
||||
/* Other side has requested shutdown and we have sent one ACK */
|
||||
|
||||
+19
-1
@@ -227,7 +227,16 @@ void STMClient::main( void )
|
||||
|
||||
if ( pollfds[ 3 ].revents & POLLIN ) {
|
||||
/* shutdown signal */
|
||||
if ( network->attached() ) {
|
||||
struct signalfd_siginfo the_siginfo;
|
||||
ssize_t bytes_read = read( pollfds[ 3 ].fd, &the_siginfo, sizeof( the_siginfo ) );
|
||||
if ( bytes_read == 0 ) {
|
||||
break;
|
||||
} else if ( bytes_read < 0 ) {
|
||||
perror( "read" );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( network->attached() && (!network->shutdown_in_progress()) ) {
|
||||
network->start_shutdown();
|
||||
} else {
|
||||
break;
|
||||
@@ -243,7 +252,11 @@ void STMClient::main( void )
|
||||
if ( (pollfds[ 1 ].revents)
|
||||
& (POLLERR | POLLHUP | POLLNVAL) ) {
|
||||
/* user problem */
|
||||
if ( network->attached() && (!network->shutdown_in_progress()) ) {
|
||||
network->start_shutdown();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* quit if our shutdown has been acknowledged */
|
||||
@@ -251,6 +264,11 @@ void STMClient::main( void )
|
||||
break;
|
||||
}
|
||||
|
||||
/* quit after shutdown acknowledgement timeout */
|
||||
if ( network->shutdown_in_progress() && network->shutdown_ack_timed_out() ) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* quit if we received and acknowledged a shutdown request */
|
||||
if ( network->counterparty_shutdown_ack_sent() ) {
|
||||
break;
|
||||
|
||||
@@ -14,6 +14,7 @@ TransportSender<MyState>::TransportSender( Connection *s_connection, MyState &in
|
||||
next_send_time( timestamp() ),
|
||||
verbose( false ),
|
||||
shutdown_in_progress( false ),
|
||||
shutdown_timestamp( -1 ),
|
||||
ack_num( 0 ),
|
||||
pending_data_ack( false )
|
||||
{
|
||||
@@ -279,3 +280,17 @@ void TransportSender<MyState>::process_acknowledgment_through( uint64_t ack_num
|
||||
assert( !sent_states.empty() );
|
||||
}
|
||||
|
||||
/* give up on getting acknowledgement for shutdown after 5 RTTs */
|
||||
template <class MyState>
|
||||
bool TransportSender<MyState>::shutdown_ack_timed_out( void )
|
||||
{
|
||||
if ( !shutdown_in_progress ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( timestamp() - shutdown_timestamp > 5 * connection->get_SRTT() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+3
-1
@@ -55,6 +55,7 @@ namespace Network {
|
||||
|
||||
bool verbose;
|
||||
bool shutdown_in_progress;
|
||||
uint64_t shutdown_timestamp;
|
||||
|
||||
/* information about receiver state */
|
||||
uint64_t ack_num;
|
||||
@@ -80,7 +81,7 @@ namespace Network {
|
||||
void set_data_ack( void ) { pending_data_ack = true; }
|
||||
|
||||
/* Starts shutdown sequence */
|
||||
void start_shutdown( void ) { shutdown_in_progress = true; }
|
||||
void start_shutdown( void ) { shutdown_in_progress = true; shutdown_timestamp = timestamp(); }
|
||||
|
||||
/* Misc. getters and setters */
|
||||
/* Cannot modify current_state while shutdown in progress */
|
||||
@@ -91,6 +92,7 @@ namespace Network {
|
||||
bool get_shutdown_in_progress( void ) { return shutdown_in_progress; }
|
||||
bool get_shutdown_acknowledged( void ) { return sent_states.front().num == uint64_t(-1); }
|
||||
bool get_counterparty_shutdown_acknowledged( void ) { return fragmenter.last_ack_sent() == uint64_t(-1); }
|
||||
bool shutdown_ack_timed_out( void );
|
||||
|
||||
/* nonexistent methods to satisfy -Weffc++ */
|
||||
TransportSender( const TransportSender &x );
|
||||
|
||||
Reference in New Issue
Block a user