diff options
Diffstat (limited to 'src/p2p')
| -rw-r--r-- | src/p2p/net_node.inl | 94 |
1 files changed, 49 insertions, 45 deletions
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 943061814..9bfe83eed 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -318,7 +318,7 @@ namespace nodetool } for (const auto &c: conns) - zone.second.m_net_server.get_config_object().close(c); + zone.second.m_net_server.get_config_object().close(c, false); conns.clear(); } @@ -374,7 +374,7 @@ namespace nodetool return true; }); for (const auto &c: conns) - zone.second.m_net_server.get_config_object().close(c); + zone.second.m_net_server.get_config_object().close(c, false); for (int i = 0; i < 2; ++i) zone.second.m_peerlist.filter(i == 0, [&subnet](const peerlist_entry &pe){ @@ -796,8 +796,14 @@ namespace nodetool // TODO: at some point add IPv6 support, but that won't be relevant // for some time yet. - std::vector<std::vector<std::string>> dns_results; - dns_results.resize(m_seed_nodes_list.size()); + struct frame_t + { + std::vector<std::vector<std::string>> dns_results; + boost::mutex sync; + }; + + const auto frame = std::make_shared<frame_t>(); + frame->dns_results.resize(m_seed_nodes_list.size()); // some libc implementation provide only a very small stack // for threads, e.g. musl only gives +- 80kb, which is not @@ -808,32 +814,22 @@ namespace nodetool std::list<boost::thread> dns_threads; uint64_t result_index = 0; + const std::weak_ptr<frame_t> frame_weak{frame}; for (const std::string& addr_str : m_seed_nodes_list) { - boost::thread th = boost::thread(thread_attributes, [=, &dns_results, &addr_str] + boost::thread th = boost::thread(thread_attributes, [frame_weak, addr_str, result_index] { MDEBUG("dns_threads[" << result_index << "] created for: " << addr_str); // TODO: care about dnssec avail/valid bool avail, valid; - std::vector<std::string> addr_list; - - try - { - addr_list = tools::DNSResolver::instance().get_ipv4(addr_str, avail, valid); - MDEBUG("dns_threads[" << result_index << "] DNS resolve done"); - boost::this_thread::interruption_point(); - } - catch(const boost::thread_interrupted&) + std::vector<std::string> addr_list = tools::DNSResolver::instance().get_ipv4(addr_str, avail, valid); + MINFO("dns_threads[" << result_index << "] addr_str: " << addr_str << " number of results: " << addr_list.size()); + const auto frame = frame_weak.lock(); + if (frame) { - // thread interruption request - // even if we now have results, finish thread without setting - // result variables, which are now out of scope in main thread - MWARNING("dns_threads[" << result_index << "] interrupted"); - return; + const boost::lock_guard<boost::mutex> lock{frame->sync}; + frame->dns_results.at(result_index) = std::move(addr_list); } - - MINFO("dns_threads[" << result_index << "] addr_str: " << addr_str << " number of results: " << addr_list.size()); - dns_results[result_index] = addr_list; }); dns_threads.push_back(std::move(th)); @@ -847,14 +843,15 @@ namespace nodetool { if (! th.try_join_until(deadline)) { - MWARNING("dns_threads[" << i << "] timed out, sending interrupt"); - th.interrupt(); + MWARNING("dns_threads[" << i << "] timed out"); + th.detach(); } ++i; } i = 0; - for (const auto& result : dns_results) + const boost::lock_guard<boost::mutex> lock{frame->sync}; + for (const auto& result : frame->dns_results) { MDEBUG("DNS lookup for " << m_seed_nodes_list[i] << ": " << result.size() << " results"); // if no results for node, thread's lookup likely timed out @@ -1154,19 +1151,26 @@ namespace nodetool { MDEBUG("[node] sending stop signal"); for (auto& zone : m_network_zones) - zone.second.m_net_server.send_stop_signal(); - MDEBUG("[node] Stop signal sent"); - - for (auto& zone : m_network_zones) { - std::list<boost::uuids::uuid> connection_ids; - zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - connection_ids.push_back(cntxt.m_connection_id); - return true; - }); - for (const auto &connection_id: connection_ids) - zone.second.m_net_server.get_config_object().close(connection_id); + const auto close_all_connections = [&, this]() + { + std::list<boost::uuids::uuid> connection_ids; + zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { + connection_ids.push_back(cntxt.m_connection_id); + return true; + }); + for (const auto &connection_id: connection_ids) + { + MDEBUG("Closing connection " << connection_id); + // We need to wait for every connection's shutdown sequence to complete before stopping the io_context. + zone.second.m_net_server.get_config_object().close(connection_id, true/*wait_for_shutdown*/); + MDEBUG("Closed connection " << connection_id); + } + }; + + zone.second.m_net_server.send_stop_signal(close_all_connections); } + MDEBUG("[node] Stop signal sent"); m_payload_handler.stop(); return true; } @@ -1253,7 +1257,7 @@ namespace nodetool { LOG_WARNING_CC(context_, "COMMAND_HANDSHAKE Failed"); if (!timeout) - zone.m_net_server.get_config_object().close(context_.m_connection_id); + zone.m_net_server.get_config_object().close(context_.m_connection_id, false); } else if (!just_take_peerlist) { @@ -1287,14 +1291,14 @@ namespace nodetool if(!handle_remote_peerlist(rsp.local_peerlist_new, context)) { LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection."); - m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id ); + m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id, false); add_host_fail(context.m_remote_address); } if(!context.m_is_income) m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_address, context.m_pruning_seed, context.m_rpc_port, context.m_rpc_credits_per_hash); if (!m_payload_handler.process_payload_sync_data(rsp.payload_data, context, false)) { - m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id ); + m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id, false); } }); @@ -1451,7 +1455,7 @@ namespace nodetool if(just_take_peerlist) { - zone.m_net_server.get_config_object().close(con->m_connection_id); + zone.m_net_server.get_config_object().close(con->m_connection_id, false); LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED."); return true; } @@ -1513,7 +1517,7 @@ namespace nodetool return false; } - zone.m_net_server.get_config_object().close(con->m_connection_id); + zone.m_net_server.get_config_object().close(con->m_connection_id, false); LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED."); @@ -2444,7 +2448,7 @@ namespace nodetool template<class t_payload_net_handler> bool node_server<t_payload_net_handler>::drop_connection(const epee::net_utils::connection_context_base& context) { - m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id); + m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id, false); return true; } //----------------------------------------------------------------------------------- @@ -2527,17 +2531,17 @@ namespace nodetool if(rsp.status != PING_OK_RESPONSE_STATUS_TEXT || pr != rsp.peer_id) { LOG_WARNING_CC(ping_context, "back ping invoke wrong response \"" << rsp.status << "\" from" << address.str() << ", hsh_peer_id=" << pr_ << ", rsp.peer_id=" << peerid_to_string(rsp.peer_id)); - zone.m_net_server.get_config_object().close(ping_context.m_connection_id); + zone.m_net_server.get_config_object().close(ping_context.m_connection_id, false); return; } - zone.m_net_server.get_config_object().close(ping_context.m_connection_id); + zone.m_net_server.get_config_object().close(ping_context.m_connection_id, false); cb(); }); if(!inv_call_res) { LOG_WARNING_CC(ping_context, "back ping invoke failed to " << address.str()); - zone.m_net_server.get_config_object().close(ping_context.m_connection_id); + zone.m_net_server.get_config_object().close(ping_context.m_connection_id, false); return false; } return true; |
