diff --git a/include/fc/rpc/json_connection.hpp b/include/fc/rpc/json_connection.hpp index dd8aba3..a0b36b8 100644 --- a/include/fc/rpc/json_connection.hpp +++ b/include/fc/rpc/json_connection.hpp @@ -32,6 +32,8 @@ namespace fc { namespace rpc { logger get_logger()const; void set_logger( const logger& l ); + void set_close_callback(std::function callback); + /** * @name server interface * diff --git a/src/rpc/json_connection.cpp b/src/rpc/json_connection.cpp index 77a3918..402d07d 100644 --- a/src/rpc/json_connection.cpp +++ b/src/rpc/json_connection.cpp @@ -16,6 +16,14 @@ namespace fc { namespace rpc { public: json_connection_impl( fc::buffered_istream_ptr&& in, fc::buffered_ostream_ptr&& out ) :_in(fc::move(in)),_out(fc::move(out)),_eof(false),_next_id(0),_logger("json_connection"){} + ~json_connection_impl() { + _done.cancel_and_wait(__FUNCTION__); + _out->close(); + _handle_message_future.cancel_and_wait(__FUNCTION__); + //Work around crash because _done.cancel_and_wait didn't work, and read_loop() is going to resume + //and crash us in just a moment if we allow ourselves to destroy now. + fc::usleep(fc::milliseconds(100)); + } fc::buffered_istream_ptr _in; fc::buffered_ostream_ptr _out; @@ -30,7 +38,7 @@ namespace fc { namespace rpc { boost::unordered_map _named_param_methods; fc::mutex _write_mutex; - //std::function _on_close; + std::function _on_close; logger _logger; @@ -225,6 +233,9 @@ namespace fc { namespace rpc { void close( fc::exception_ptr e ) { + e = fc::exception_ptr(new FC_EXCEPTION( unhandled_exception, "json connection closed" )); + if( _on_close ) + _on_close(e); wlog( "close ${reason}", ("reason", e->to_detail_string() ) ); for( auto itr = _awaiting.begin(); itr != _awaiting.end(); ++itr ) { @@ -240,24 +251,6 @@ namespace fc { namespace rpc { json_connection::~json_connection() { - try - { - if( my->_handle_message_future.valid() && !my->_handle_message_future.ready() ) - my->_handle_message_future.cancel_and_wait(__FUNCTION__); - if( my->_done.valid() && !my->_done.ready() ) - { - my->_done.cancel("json_connection is destructing"); - my->_out->close(); - my->_done.wait(); - } - } - catch ( fc::canceled_exception& ){} // expected exception - catch ( fc::eof_exception& ){} // expected exception - catch ( fc::exception& e ) - { - // unhandled, unexpected exception cannot throw from destructor, so log it. - wlog( "${exception}", ("exception",e.to_detail_string()) ); - } } fc::future json_connection::exec() @@ -698,4 +691,9 @@ namespace fc { namespace rpc { my->_logger = l; } + void json_connection::set_close_callback(std::function callback) + { + my->_on_close = callback; + } + }}