p2p: fix frequent weak_ptr exception on connection

When a handshake fails, it can fail due to timeout or destroyed
connection, in which case the connection will be, or already is,
closed, and we don't want to do it twice.
Additionally, when closing a connection directly from the top
level code, ensure the connection is gone from the m_connects
list so it won't be used again.

AFAICT this is now clean in netstat, /proc/PID/fd and print_cn.

This fixes a noisy (but harmless) exception.
This commit is contained in:
moneromooo-monero 2019-12-30 17:24:42 +00:00
parent 6c7d928f19
commit 21fe6a289b
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3
2 changed files with 12 additions and 5 deletions

View File

@ -949,7 +949,12 @@ bool async_protocol_handler_config<t_connection_context>::close(boost::uuids::uu
{ {
CRITICAL_REGION_LOCAL(m_connects_lock); CRITICAL_REGION_LOCAL(m_connects_lock);
async_protocol_handler<t_connection_context>* aph = find_connection(connection_id); async_protocol_handler<t_connection_context>* aph = find_connection(connection_id);
return 0 != aph ? aph->close() : false; if (!aph)
return false;
if (!aph->close())
return false;
m_connects.erase(connection_id);
return true;
} }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
template<class t_connection_context> template<class t_connection_context>

View File

@ -1013,15 +1013,18 @@ namespace nodetool
epee::simple_event ev; epee::simple_event ev;
std::atomic<bool> hsh_result(false); std::atomic<bool> hsh_result(false);
bool timeout = false;
bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_, COMMAND_HANDSHAKE::ID, arg, zone.m_net_server.get_config_object(), bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_, COMMAND_HANDSHAKE::ID, arg, zone.m_net_server.get_config_object(),
[this, &pi, &ev, &hsh_result, &just_take_peerlist, &context_](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context) [this, &pi, &ev, &hsh_result, &just_take_peerlist, &context_, &timeout](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context)
{ {
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ev.raise();}); epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ev.raise();});
if(code < 0) if(code < 0)
{ {
LOG_WARNING_CC(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")"); LOG_WARNING_CC(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")");
if (code == LEVIN_ERROR_CONNECTION_TIMEDOUT || code == LEVIN_ERROR_CONNECTION_DESTROYED)
timeout = true;
return; return;
} }
@ -1079,7 +1082,8 @@ namespace nodetool
if(!hsh_result) if(!hsh_result)
{ {
LOG_WARNING_CC(context_, "COMMAND_HANDSHAKE Failed"); LOG_WARNING_CC(context_, "COMMAND_HANDSHAKE Failed");
m_network_zones.at(context_.m_remote_address.get_zone()).m_net_server.get_config_object().close(context_.m_connection_id); if (!timeout)
zone.m_net_server.get_config_object().close(context_.m_connection_id);
} }
else if (!just_take_peerlist) else if (!just_take_peerlist)
{ {
@ -1266,7 +1270,6 @@ namespace nodetool
LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer " LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer "
<< na.str() << na.str()
/*<< ", try " << try_count*/); /*<< ", try " << try_count*/);
zone.m_net_server.get_config_object().close(con->m_connection_id);
record_addr_failed(na); record_addr_failed(na);
return false; return false;
} }
@ -1330,7 +1333,6 @@ namespace nodetool
bool is_priority = is_priority_node(na); bool is_priority = is_priority_node(na);
LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer " << na.str()); LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer " << na.str());
zone.m_net_server.get_config_object().close(con->m_connection_id);
record_addr_failed(na); record_addr_failed(na);
return false; return false;
} }