From 21fe6a289b934bd96bf83d5d23ece14ec850df27 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 30 Dec 2019 17:24:42 +0000 Subject: [PATCH] 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. --- .../epee/include/net/levin_protocol_handler_async.h | 7 ++++++- src/p2p/net_node.inl | 10 ++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index 5774c0ba7..1341a4ae6 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -949,7 +949,12 @@ bool async_protocol_handler_config::close(boost::uuids::uu { CRITICAL_REGION_LOCAL(m_connects_lock); async_protocol_handler* 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 diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 9b6358dee..dcd16e5c1 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1013,15 +1013,18 @@ namespace nodetool epee::simple_event ev; std::atomic hsh_result(false); + bool timeout = false; bool r = epee::net_utils::async_invoke_remote_command2(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();}); if(code < 0) { 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; } @@ -1079,7 +1082,8 @@ namespace nodetool if(!hsh_result) { 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) { @@ -1266,7 +1270,6 @@ namespace nodetool LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer " << na.str() /*<< ", try " << try_count*/); - zone.m_net_server.get_config_object().close(con->m_connection_id); record_addr_failed(na); return false; } @@ -1330,7 +1333,6 @@ namespace nodetool bool is_priority = is_priority_node(na); 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); return false; }