More robust shutdown sequence with warning on unclean shutdown.
This commit is contained in:
@@ -87,6 +87,10 @@ void STMClient::init( void )
|
|||||||
if ( !getenv( "MOSH_TITLE_NOPREFIX" ) ) {
|
if ( !getenv( "MOSH_TITLE_NOPREFIX" ) ) {
|
||||||
overlays.set_title_prefix( wstring( L"[mosh] " ) );
|
overlays.set_title_prefix( wstring( L"[mosh] " ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wchar_t tmp[ 128 ];
|
||||||
|
swprintf( tmp, 128, L"Nothing received from server on UDP port %d.", port );
|
||||||
|
connecting_notification = wstring( tmp );
|
||||||
}
|
}
|
||||||
|
|
||||||
void STMClient::shutdown( void )
|
void STMClient::shutdown( void )
|
||||||
@@ -109,6 +113,10 @@ void STMClient::shutdown( void )
|
|||||||
fprintf( stderr, "mosh did not make a successful connection to %s:%d.\n", ip.c_str(), port );
|
fprintf( stderr, "mosh did not make a successful connection to %s:%d.\n", ip.c_str(), port );
|
||||||
fprintf( stderr, "Please verify that UDP port %d is not firewalled and can reach the server.\n\n", port );
|
fprintf( stderr, "Please verify that UDP port %d is not firewalled and can reach the server.\n\n", port );
|
||||||
fprintf( stderr, "(By default, mosh uses a UDP port between 60000 and 61000. The -p option\nselects a specific UDP port number.)\n" );
|
fprintf( stderr, "(By default, mosh uses a UDP port between 60000 and 61000. The -p option\nselects a specific UDP port number.)\n" );
|
||||||
|
} else if ( network ) {
|
||||||
|
if ( !clean_shutdown ) {
|
||||||
|
fprintf( stderr, "\n\nmosh did not shut down cleanly. Please note that the\nmosh-server process may still be running on the server.\n" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +231,7 @@ bool STMClient::process_user_input( int fd )
|
|||||||
if ( quit_sequence_started ) {
|
if ( quit_sequence_started ) {
|
||||||
if ( the_byte == '.' ) { /* Quit sequence is Ctrl-^ . */
|
if ( the_byte == '.' ) { /* Quit sequence is Ctrl-^ . */
|
||||||
if ( network->has_remote_addr() && (!network->shutdown_in_progress()) ) {
|
if ( network->has_remote_addr() && (!network->shutdown_in_progress()) ) {
|
||||||
overlays.get_notification_engine().set_notification_string( wstring( L"Exiting on user request..." ) );
|
overlays.get_notification_engine().set_notification_string( wstring( L"Exiting on user request..." ), true );
|
||||||
network->start_shutdown();
|
network->start_shutdown();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -328,7 +336,7 @@ void STMClient::main( void )
|
|||||||
if ( !network->has_remote_addr() ) {
|
if ( !network->has_remote_addr() ) {
|
||||||
break;
|
break;
|
||||||
} else if ( !network->shutdown_in_progress() ) {
|
} else if ( !network->shutdown_in_progress() ) {
|
||||||
overlays.get_notification_engine().set_notification_string( wstring( L"Exiting..." ) );
|
overlays.get_notification_engine().set_notification_string( wstring( L"Exiting..." ), true );
|
||||||
network->start_shutdown();
|
network->start_shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,7 +354,7 @@ void STMClient::main( void )
|
|||||||
if ( !network->has_remote_addr() ) {
|
if ( !network->has_remote_addr() ) {
|
||||||
break;
|
break;
|
||||||
} else if ( !network->shutdown_in_progress() ) {
|
} else if ( !network->shutdown_in_progress() ) {
|
||||||
overlays.get_notification_engine().set_notification_string( wstring( L"Signal received, shutting down..." ) );
|
overlays.get_notification_engine().set_notification_string( wstring( L"Signal received, shutting down..." ), true );
|
||||||
network->start_shutdown();
|
network->start_shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,13 +372,14 @@ void STMClient::main( void )
|
|||||||
if ( !network->has_remote_addr() ) {
|
if ( !network->has_remote_addr() ) {
|
||||||
break;
|
break;
|
||||||
} else if ( !network->shutdown_in_progress() ) {
|
} else if ( !network->shutdown_in_progress() ) {
|
||||||
overlays.get_notification_engine().set_notification_string( wstring( L"Exiting..." ) );
|
overlays.get_notification_engine().set_notification_string( wstring( L"Exiting..." ), true );
|
||||||
network->start_shutdown();
|
network->start_shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* quit if our shutdown has been acknowledged */
|
/* quit if our shutdown has been acknowledged */
|
||||||
if ( network->shutdown_in_progress() && network->shutdown_acknowledged() ) {
|
if ( network->shutdown_in_progress() && network->shutdown_acknowledged() ) {
|
||||||
|
clean_shutdown = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,14 +390,11 @@ void STMClient::main( void )
|
|||||||
|
|
||||||
/* 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() ) {
|
||||||
|
clean_shutdown = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write diagnostic message if can't reach server */
|
/* write diagnostic message if can't reach server */
|
||||||
wchar_t tmp[ 128 ];
|
|
||||||
swprintf( tmp, 128, L"Nothing received from server on UDP port %d.", port );
|
|
||||||
wstring connecting_notification( tmp );
|
|
||||||
|
|
||||||
if ( still_connecting()
|
if ( still_connecting()
|
||||||
&& (!network->shutdown_in_progress())
|
&& (!network->shutdown_in_progress())
|
||||||
&& (timestamp() - network->get_latest_remote_state().timestamp > 250) ) {
|
&& (timestamp() - network->get_latest_remote_state().timestamp > 250) ) {
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ private:
|
|||||||
Network::Transport< Network::UserStream, Terminal::Complete > *network;
|
Network::Transport< Network::UserStream, Terminal::Complete > *network;
|
||||||
Terminal::Display display;
|
Terminal::Display display;
|
||||||
|
|
||||||
|
std::wstring connecting_notification;
|
||||||
bool repaint_requested, quit_sequence_started;
|
bool repaint_requested, quit_sequence_started;
|
||||||
|
bool clean_shutdown;
|
||||||
|
|
||||||
void main_init( void );
|
void main_init( void );
|
||||||
bool process_network_input( void );
|
bool process_network_input( void );
|
||||||
@@ -70,8 +72,10 @@ public:
|
|||||||
overlays(),
|
overlays(),
|
||||||
network( NULL ),
|
network( NULL ),
|
||||||
display( true ), /* use TERM environment var to initialize display */
|
display( true ), /* use TERM environment var to initialize display */
|
||||||
|
connecting_notification(),
|
||||||
repaint_requested( false ),
|
repaint_requested( false ),
|
||||||
quit_sequence_started( false )
|
quit_sequence_started( false ),
|
||||||
|
clean_shutdown( false )
|
||||||
{
|
{
|
||||||
if ( predict_mode ) {
|
if ( predict_mode ) {
|
||||||
if ( !strcmp( predict_mode, "always" ) ) {
|
if ( !strcmp( predict_mode, "always" ) ) {
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ namespace Overlay {
|
|||||||
bool need_countup( uint64_t ts ) const { return ts - last_word_from_server > 6500; }
|
bool need_countup( uint64_t ts ) const { return ts - last_word_from_server > 6500; }
|
||||||
void adjust_message( void );
|
void adjust_message( void );
|
||||||
void apply( Framebuffer &fb ) const;
|
void apply( Framebuffer &fb ) const;
|
||||||
void set_notification_string( const wstring s_message ) { message = s_message; message_expiration = timestamp() + 1000; }
|
void set_notification_string( const wstring &s_message, bool permanent = false ) { message = s_message; if ( permanent ) { message_expiration = -1; } else { message_expiration = timestamp() + 1000; } }
|
||||||
const wstring &get_notification_string( void ) const { return message; }
|
const wstring &get_notification_string( void ) const { return message; }
|
||||||
void server_heard( uint64_t s_last_word ) { last_word_from_server = s_last_word; }
|
void server_heard( uint64_t s_last_word ) { last_word_from_server = s_last_word; }
|
||||||
uint64_t get_message_expiration( void ) const { return message_expiration; }
|
uint64_t get_message_expiration( void ) const { return message_expiration; }
|
||||||
|
|||||||
@@ -159,7 +159,9 @@ void TransportSender<MyState>::tick( void )
|
|||||||
template <class MyState>
|
template <class MyState>
|
||||||
void TransportSender<MyState>::send_empty_ack( void )
|
void TransportSender<MyState>::send_empty_ack( void )
|
||||||
{
|
{
|
||||||
assert ( timestamp() >= next_ack_time );
|
uint64_t now = timestamp();
|
||||||
|
|
||||||
|
assert( now >= next_ack_time );
|
||||||
|
|
||||||
uint64_t new_num = sent_states.back().num + 1;
|
uint64_t new_num = sent_states.back().num + 1;
|
||||||
|
|
||||||
@@ -169,10 +171,10 @@ void TransportSender<MyState>::send_empty_ack( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sent_states.push_back( TimestampedState<MyState>( sent_states.back().timestamp, new_num, current_state ) );
|
// sent_states.push_back( TimestampedState<MyState>( sent_states.back().timestamp, new_num, current_state ) );
|
||||||
add_sent_state( sent_states.back().timestamp, new_num, current_state );
|
add_sent_state( now, new_num, current_state );
|
||||||
send_in_fragments( "", new_num );
|
send_in_fragments( "", new_num );
|
||||||
|
|
||||||
next_ack_time = timestamp() + ACK_INTERVAL;
|
next_ack_time = now + ACK_INTERVAL;
|
||||||
next_send_time = uint64_t(-1);
|
next_send_time = uint64_t(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Network {
|
|||||||
static const int SEND_INTERVAL_MAX = 250; /* ms between frames */
|
static const int SEND_INTERVAL_MAX = 250; /* ms between frames */
|
||||||
static const int ACK_INTERVAL = 3000; /* ms between empty acks */
|
static const int ACK_INTERVAL = 3000; /* ms between empty acks */
|
||||||
static const int ACK_DELAY = 100; /* ms before delayed ack */
|
static const int ACK_DELAY = 100; /* ms before delayed ack */
|
||||||
static const int SHUTDOWN_RETRIES = 3; /* number of shutdown packets to send before giving up */
|
static const int SHUTDOWN_RETRIES = 16; /* number of shutdown packets to send before giving up */
|
||||||
static const int ACTIVE_RETRY_TIMEOUT = 10000; /* attempt to resend at frame rate */
|
static const int ACTIVE_RETRY_TIMEOUT = 10000; /* attempt to resend at frame rate */
|
||||||
|
|
||||||
/* helper methods for tick() */
|
/* helper methods for tick() */
|
||||||
|
|||||||
Reference in New Issue
Block a user