From 0662f2b7193693ba1129690ac004af7f866470bb Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 7 Mar 2025 16:22:50 +0100 Subject: [PATCH] In a coroutine, re-throw everything ex. std::exception (and inheritors) not just boost::coroutines::detail::forced_unwind. This is needed because as of Boost 1.87, boost::asio::spawn() uses Fiber, not Coroutine v1. https://github.com/boostorg/asio/commit/df973a85ed69f021 This is safe because every actual exception shall inherit from std::exception. Except forced_unwind and its Fiber equivalent, so that `catch(const std::exception&)` doesn't catch them and only them. --- lib/base/io-engine.hpp | 13 ++++++---- lib/icingadb/redisconnection.cpp | 41 ++++---------------------------- lib/icingadb/redisconnection.hpp | 8 ++----- 3 files changed, 14 insertions(+), 48 deletions(-) diff --git a/lib/base/io-engine.hpp b/lib/base/io-engine.hpp index 0350d45b8..55a06fb6a 100644 --- a/lib/base/io-engine.hpp +++ b/lib/base/io-engine.hpp @@ -106,14 +106,17 @@ public: try { f(yc); - } catch (const boost::coroutines::detail::forced_unwind &) { - // Required for proper stack unwinding when coroutines are destroyed. - // https://github.com/boostorg/coroutine/issues/39 - throw; } catch (const std::exception& ex) { Log(LogCritical, "IoEngine") << "Exception in coroutine: " << DiagnosticInformation(ex); } catch (...) { - Log(LogCritical, "IoEngine", "Exception in coroutine!"); + try { + Log(LogCritical, "IoEngine", "Exception in coroutine!"); + } catch (...) { + } + + // Required for proper stack unwinding when coroutines are destroyed. + // https://github.com/boostorg/coroutine/issues/39 + throw; } }, boost::coroutines::attributes(GetCoroutineStackSize()) // Set a pre-defined stack size. diff --git a/lib/icingadb/redisconnection.cpp b/lib/icingadb/redisconnection.cpp index a6b82187d..c1f73f5a0 100644 --- a/lib/icingadb/redisconnection.cpp +++ b/lib/icingadb/redisconnection.cpp @@ -377,8 +377,6 @@ void RedisConnection::Connect(asio::yield_context& yc) } break; - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; } catch (const std::exception& ex) { Log(LogCritical, "IcingaDB") << "Cannot connect to " << m_Host << ":" << m_Port << ": " << ex.what(); @@ -408,17 +406,10 @@ void RedisConnection::ReadLoop(asio::yield_context& yc) for (auto i (item.Amount); i; --i) { ReadOne(yc); } - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; } catch (const std::exception& ex) { Log(LogCritical, "IcingaDB") << "Error during receiving the response to a query which has been fired and forgotten: " << ex.what(); - continue; - } catch (...) { - Log(LogCritical, "IcingaDB") - << "Error during receiving the response to a query which has been fired and forgotten"; - continue; } @@ -432,9 +423,7 @@ void RedisConnection::ReadLoop(asio::yield_context& yc) try { reply = ReadOne(yc); - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; - } catch (...) { + } catch (const std::exception&) { promise.set_exception(std::current_exception()); continue; @@ -455,9 +444,7 @@ void RedisConnection::ReadLoop(asio::yield_context& yc) for (auto i (item.Amount); i; --i) { try { replies.emplace_back(ReadOne(yc)); - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; - } catch (...) { + } catch (const std::exception&) { promise.set_exception(std::current_exception()); break; } @@ -551,19 +538,11 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection: try { WriteOne(item, yc); - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; } catch (const std::exception& ex) { Log msg (LogCritical, "IcingaDB", "Error during sending query"); LogQuery(item, msg); msg << " which has been fired and forgotten: " << ex.what(); - return; - } catch (...) { - Log msg (LogCritical, "IcingaDB", "Error during sending query"); - LogQuery(item, msg); - msg << " which has been fired and forgotten"; - return; } @@ -587,19 +566,11 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection: WriteOne(query, yc); ++i; } - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; } catch (const std::exception& ex) { Log msg (LogCritical, "IcingaDB", "Error during sending query"); LogQuery(item[i], msg); msg << " which has been fired and forgotten: " << ex.what(); - return; - } catch (...) { - Log msg (LogCritical, "IcingaDB", "Error during sending query"); - LogQuery(item[i], msg); - msg << " which has been fired and forgotten"; - return; } @@ -618,9 +589,7 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection: try { WriteOne(item.first, yc); - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; - } catch (...) { + } catch (const std::exception&) { item.second.set_exception(std::current_exception()); return; @@ -645,9 +614,7 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection: for (auto& query : item.first) { WriteOne(query, yc); } - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; - } catch (...) { + } catch (const std::exception&) { item.second.set_exception(std::current_exception()); return; diff --git a/lib/icingadb/redisconnection.hpp b/lib/icingadb/redisconnection.hpp index 3f963f3d3..acc6e4381 100644 --- a/lib/icingadb/redisconnection.hpp +++ b/lib/icingadb/redisconnection.hpp @@ -389,9 +389,7 @@ RedisConnection::Reply RedisConnection::ReadOne(StreamPtr& stream, boost::asio:: try { return ReadRESP(*strm, yc); - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; - } catch (...) { + } catch (const std::exception&) { if (m_Connecting.exchange(false)) { m_Connected.store(false); stream = nullptr; @@ -427,9 +425,7 @@ void RedisConnection::WriteOne(StreamPtr& stream, RedisConnection::Query& query, try { WriteRESP(*strm, query, yc); strm->async_flush(yc); - } catch (const boost::coroutines::detail::forced_unwind&) { - throw; - } catch (...) { + } catch (const std::exception&) { if (m_Connecting.exchange(false)) { m_Connected.store(false); stream = nullptr;