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