From 186a9e95f77f76be29abe955ddf2b8fb726f71b1 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 5 Feb 2020 17:17:41 +0100 Subject: [PATCH 1/2] Generalize I/O timeout emulation --- lib/base/io-engine.cpp | 8 +++++++ lib/base/io-engine.hpp | 52 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/lib/base/io-engine.cpp b/lib/base/io-engine.cpp index 5dd3ee59c..d3197790e 100644 --- a/lib/base/io-engine.cpp +++ b/lib/base/io-engine.cpp @@ -144,3 +144,11 @@ void AsioConditionVariable::Wait(boost::asio::yield_context yc) boost::system::error_code ec; m_Timer.async_wait(yc[ec]); } + +void Timeout::Cancel() +{ + m_Cancelled.store(true); + + boost::system::error_code ec; + m_Timer.cancel(ec); +} diff --git a/lib/base/io-engine.hpp b/lib/base/io-engine.hpp index a9ea030e9..d8b3bf041 100644 --- a/lib/base/io-engine.hpp +++ b/lib/base/io-engine.hpp @@ -6,10 +6,12 @@ #include "base/exception.hpp" #include "base/lazy-init.hpp" #include "base/logger.hpp" +#include "base/shared-object.hpp" #include #include #include #include +#include #include #include #include @@ -175,6 +177,56 @@ private: boost::asio::deadline_timer m_Timer; }; +/** + * I/O timeout emulator + * + * @ingroup base + */ +class Timeout : public SharedObject +{ +public: + DECLARE_PTR_TYPEDEFS(Timeout); + + template + Timeout(boost::asio::io_context& io, Executor& executor, TimeoutFromNow timeoutFromNow, OnTimeout onTimeout) + : m_Timer(io) + { + Ptr keepAlive (this); + + m_Cancelled.store(false); + m_Timer.expires_from_now(std::move(timeoutFromNow)); + + IoEngine::SpawnCoroutine(executor, [this, keepAlive, onTimeout](boost::asio::yield_context yc) { + if (m_Cancelled.load()) { + return; + } + + { + boost::system::error_code ec; + + m_Timer.async_wait(yc[ec]); + + if (ec) { + return; + } + } + + if (m_Cancelled.load()) { + return; + } + + auto f (onTimeout); + f(std::move(yc)); + }); + } + + void Cancel(); + +private: + boost::asio::deadline_timer m_Timer; + std::atomic m_Cancelled; +}; + } #endif /* IO_ENGINE_H */ From b24f438daa75e99bc3fb743628048ad18d538200 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 27 Feb 2020 13:24:57 +0100 Subject: [PATCH 2/2] Add timeout for boost::asio::ssl::stream#async_shutdown() refs #7203 --- lib/remote/jsonrpcconnection.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/remote/jsonrpcconnection.cpp b/lib/remote/jsonrpcconnection.cpp index 479fdea05..7fd8775a7 100644 --- a/lib/remote/jsonrpcconnection.cpp +++ b/lib/remote/jsonrpcconnection.cpp @@ -235,8 +235,20 @@ void JsonRpcConnection::Disconnect() m_Stream->lowest_layer().cancel(ec); + Timeout::Ptr shutdownTimeout (new Timeout( + m_IoStrand.context(), + m_IoStrand, + boost::posix_time::seconds(10), + [this, keepAlive](asio::yield_context yc) { + boost::system::error_code ec; + m_Stream->lowest_layer().cancel(ec); + } + )); + m_Stream->next_layer().async_shutdown(yc[ec]); + shutdownTimeout->Cancel(); + m_Stream->lowest_layer().shutdown(m_Stream->lowest_layer().shutdown_both, ec); } });