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.
This commit is contained in:
Alexander A. Klimov 2025-03-07 16:22:50 +01:00 committed by Julian Brost
parent 011c67964e
commit 0662f2b719
3 changed files with 14 additions and 48 deletions

View File

@ -106,14 +106,17 @@ public:
try { try {
f(yc); 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) { } catch (const std::exception& ex) {
Log(LogCritical, "IoEngine") << "Exception in coroutine: " << DiagnosticInformation(ex); Log(LogCritical, "IoEngine") << "Exception in coroutine: " << DiagnosticInformation(ex);
} catch (...) { } catch (...) {
try {
Log(LogCritical, "IoEngine", "Exception in coroutine!"); 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. boost::coroutines::attributes(GetCoroutineStackSize()) // Set a pre-defined stack size.

View File

@ -377,8 +377,6 @@ void RedisConnection::Connect(asio::yield_context& yc)
} }
break; break;
} catch (const boost::coroutines::detail::forced_unwind&) {
throw;
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
Log(LogCritical, "IcingaDB") Log(LogCritical, "IcingaDB")
<< "Cannot connect to " << m_Host << ":" << m_Port << ": " << ex.what(); << "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) { for (auto i (item.Amount); i; --i) {
ReadOne(yc); ReadOne(yc);
} }
} catch (const boost::coroutines::detail::forced_unwind&) {
throw;
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
Log(LogCritical, "IcingaDB") Log(LogCritical, "IcingaDB")
<< "Error during receiving the response to a query which has been fired and forgotten: " << ex.what(); << "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; continue;
} }
@ -432,9 +423,7 @@ void RedisConnection::ReadLoop(asio::yield_context& yc)
try { try {
reply = ReadOne(yc); reply = ReadOne(yc);
} catch (const boost::coroutines::detail::forced_unwind&) { } catch (const std::exception&) {
throw;
} catch (...) {
promise.set_exception(std::current_exception()); promise.set_exception(std::current_exception());
continue; continue;
@ -455,9 +444,7 @@ void RedisConnection::ReadLoop(asio::yield_context& yc)
for (auto i (item.Amount); i; --i) { for (auto i (item.Amount); i; --i) {
try { try {
replies.emplace_back(ReadOne(yc)); replies.emplace_back(ReadOne(yc));
} catch (const boost::coroutines::detail::forced_unwind&) { } catch (const std::exception&) {
throw;
} catch (...) {
promise.set_exception(std::current_exception()); promise.set_exception(std::current_exception());
break; break;
} }
@ -551,19 +538,11 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection:
try { try {
WriteOne(item, yc); WriteOne(item, yc);
} catch (const boost::coroutines::detail::forced_unwind&) {
throw;
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
Log msg (LogCritical, "IcingaDB", "Error during sending query"); Log msg (LogCritical, "IcingaDB", "Error during sending query");
LogQuery(item, msg); LogQuery(item, msg);
msg << " which has been fired and forgotten: " << ex.what(); 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; return;
} }
@ -587,19 +566,11 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection:
WriteOne(query, yc); WriteOne(query, yc);
++i; ++i;
} }
} catch (const boost::coroutines::detail::forced_unwind&) {
throw;
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
Log msg (LogCritical, "IcingaDB", "Error during sending query"); Log msg (LogCritical, "IcingaDB", "Error during sending query");
LogQuery(item[i], msg); LogQuery(item[i], msg);
msg << " which has been fired and forgotten: " << ex.what(); 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; return;
} }
@ -618,9 +589,7 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection:
try { try {
WriteOne(item.first, yc); WriteOne(item.first, yc);
} catch (const boost::coroutines::detail::forced_unwind&) { } catch (const std::exception&) {
throw;
} catch (...) {
item.second.set_exception(std::current_exception()); item.second.set_exception(std::current_exception());
return; return;
@ -645,9 +614,7 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection:
for (auto& query : item.first) { for (auto& query : item.first) {
WriteOne(query, yc); WriteOne(query, yc);
} }
} catch (const boost::coroutines::detail::forced_unwind&) { } catch (const std::exception&) {
throw;
} catch (...) {
item.second.set_exception(std::current_exception()); item.second.set_exception(std::current_exception());
return; return;

View File

@ -389,9 +389,7 @@ RedisConnection::Reply RedisConnection::ReadOne(StreamPtr& stream, boost::asio::
try { try {
return ReadRESP(*strm, yc); return ReadRESP(*strm, yc);
} catch (const boost::coroutines::detail::forced_unwind&) { } catch (const std::exception&) {
throw;
} catch (...) {
if (m_Connecting.exchange(false)) { if (m_Connecting.exchange(false)) {
m_Connected.store(false); m_Connected.store(false);
stream = nullptr; stream = nullptr;
@ -427,9 +425,7 @@ void RedisConnection::WriteOne(StreamPtr& stream, RedisConnection::Query& query,
try { try {
WriteRESP(*strm, query, yc); WriteRESP(*strm, query, yc);
strm->async_flush(yc); strm->async_flush(yc);
} catch (const boost::coroutines::detail::forced_unwind&) { } catch (const std::exception&) {
throw;
} catch (...) {
if (m_Connecting.exchange(false)) { if (m_Connecting.exchange(false)) {
m_Connected.store(false); m_Connected.store(false);
stream = nullptr; stream = nullptr;