From 53a1f95cd2cc8453230b65cf41ee300d258f510f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Mon, 25 Mar 2024 10:27:13 +0100 Subject: [PATCH] GRACEFUL SHUTDOWN --- nano/lib/stats_enums.hpp | 1 + nano/node/transport/tcp_listener.cpp | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/nano/lib/stats_enums.hpp b/nano/lib/stats_enums.hpp index ff095f9a38..2106f69cb2 100644 --- a/nano/lib/stats_enums.hpp +++ b/nano/lib/stats_enums.hpp @@ -240,6 +240,7 @@ enum class detail : uint8_t accept_error, accept_failure, accept_limits_exceeded, + close_error, max_per_ip, max_per_subnetwork, excluded, diff --git a/nano/node/transport/tcp_listener.cpp b/nano/node/transport/tcp_listener.cpp index 8f8702a001..0e4c83aeda 100644 --- a/nano/node/transport/tcp_listener.cpp +++ b/nano/node/transport/tcp_listener.cpp @@ -183,7 +183,7 @@ void nano::transport::tcp_listener::run () lock.lock (); // Sleep for a while to prevent busy loop with additional cooldown if an error occurred - condition.wait_for (lock, cooldown ? 1s : 10ms, [this] () { return stopped.load (); }); + condition.wait_for (lock, cooldown ? 100ms : 10ms, [this] () { return stopped.load (); }); } if (!stopped) { @@ -194,22 +194,34 @@ void nano::transport::tcp_listener::run () auto nano::transport::tcp_listener::accept_one () -> accept_result { - auto boost_socket = acceptor.accept (); - auto const remote_endpoint = boost_socket.remote_endpoint (); - auto const local_endpoint = boost_socket.local_endpoint (); + auto raw_socket = acceptor.accept (); + auto const remote_endpoint = raw_socket.remote_endpoint (); + auto const local_endpoint = raw_socket.local_endpoint (); if (auto result = check_limits (remote_endpoint.address ()); result != accept_result::accepted) { stats.inc (nano::stat::type::tcp_listener, nano::stat::detail::accept_limits_exceeded, nano::stat::dir::in); // Refusal reason should be logged earlier + try + { + // Best effor attempt to gracefully close the socket, shutdown before closing to avoid zombie sockets + raw_socket.shutdown (boost::asio::ip::tcp::socket::shutdown_both); + raw_socket.close (); + } + catch (boost::system::system_error const & ex) + { + logger.debug (nano::log::type::tcp_listener, "Error while closing socket after refusing connection: {}", ex.what ()); + stats.inc (nano::stat::type::tcp_listener, nano::stat::detail::close_error, nano::stat::dir::in); + } + return result; } stats.inc (nano::stat::type::tcp_listener, nano::stat::detail::accept_success, nano::stat::dir::in); logger.debug (nano::log::type::tcp_listener, "Accepted incoming connection from: {}", fmt::streamed (remote_endpoint)); - auto socket = std::make_shared (std::move (boost_socket), remote_endpoint, local_endpoint, node, socket_endpoint::server); + auto socket = std::make_shared (std::move (raw_socket), remote_endpoint, local_endpoint, node, socket_endpoint::server); auto server = std::make_shared (socket, node.shared (), true); {