diff --git a/networktransport.hpp b/networktransport.hpp index 4805b04..c11ae09 100644 --- a/networktransport.hpp +++ b/networktransport.hpp @@ -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 */ diff --git a/stmclient.cpp b/stmclient.cpp index 354fe8e..c30f280 100644 --- a/stmclient.cpp +++ b/stmclient.cpp @@ -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 */ - network->start_shutdown(); + 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; diff --git a/transportsender.cpp b/transportsender.cpp index 47785e8..cc19f5a 100644 --- a/transportsender.cpp +++ b/transportsender.cpp @@ -14,6 +14,7 @@ TransportSender::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::process_acknowledgment_through( uint64_t ack_num assert( !sent_states.empty() ); } +/* give up on getting acknowledgement for shutdown after 5 RTTs */ +template +bool TransportSender::shutdown_ack_timed_out( void ) +{ + if ( !shutdown_in_progress ) { + return false; + } + + if ( timestamp() - shutdown_timestamp > 5 * connection->get_SRTT() ) { + return true; + } + + return false; +} diff --git a/transportsender.hpp b/transportsender.hpp index 4ad4bd0..940bd9d 100644 --- a/transportsender.hpp +++ b/transportsender.hpp @@ -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 );