From 57c00a20c5b156e0a86e451ea4d80c8c18fa64e2 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Tue, 30 Jun 2026 21:47:58 +0200 Subject: [PATCH] libutil: make exception wrapping accessible outside of TRY_AWAIT this will be useful for rpc cases, and it reduces macro code expasions. Change-Id: I47c837fb5efab8eb408fcf9617055ea1562fc422 --- lix/libutil/async.hh | 71 +++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/lix/libutil/async.hh b/lix/libutil/async.hh index a78b241da..b346e7e98 100644 --- a/lix/libutil/async.hh +++ b/lix/libutil/async.hh @@ -4,6 +4,7 @@ #include "lix/libutil/error.hh" #include "lix/libutil/result.hh" #include "lix/libutil/signals.hh" +#include #include #include #include @@ -109,30 +110,58 @@ T runAsyncUnwrap(Result t) { return std::move(t).value(); } + +[[noreturn]] +inline void rethrow_async_exception_as_lix( + std::optional context, std::source_location loc = std::source_location::current() +) +{ + try { + throw; // NOLINT(lix-foreign-exceptions) + } catch (BaseException & e) { + e.addAsyncTrace(loc, context); + throw; + } catch (kj::Exception & e) { // NOLINT(lix-foreign-exceptions) + Error fe{e.getDescription().cStr()}; + fe.addAsyncTrace(loc, context); + throw fe; + } catch (...) { + auto fe = ForeignException::wrapCurrent(); + fe.addAsyncTrace(loc, context); + throw fe; + } +} + +inline ErrorInfo wrap_exception_as_lix( + std::exception_ptr ex, + std::optional context = std::nullopt, + std::source_location loc = std::source_location::current() +) +{ + try { + std::rethrow_exception(ex); + } catch (BaseError & e) { + return e.info(); + } catch (std::exception & e) { // NOLINT(lix-foreign-exceptions) + return {lvlError, HintFmt("%s", Uncolored(e.what()))}; + } catch (...) { + return {lvlError, HintFmt("unknown exception")}; + } +} } } -#define LIX_TRY_AWAIT_CONTEXT_MAP(_l_ctx, _l_map, ...) \ - ({ \ - auto _lix_awaited = (_l_map) (co_await (__VA_ARGS__)); \ - if (_lix_awaited.has_error()) { \ - try { \ - _lix_awaited.value(); \ - } catch (::nix::BaseException & e) { \ - e.addAsyncTrace(::std::source_location::current(), _l_ctx()); \ - throw; \ - /* NOLINTNEXTLINE(lix-foreign-exceptions) */ \ - } catch (::kj::Exception & e) { \ - ::nix::Error fe{e.getDescription().cStr()}; \ - fe.addAsyncTrace(::std::source_location::current(), _l_ctx()); \ - throw fe; \ - } catch (...) { \ - auto fe = ::nix::ForeignException::wrapCurrent(); \ - fe.addAsyncTrace(::std::source_location::current(), _l_ctx()); \ - throw fe; \ - } \ - } \ - ::nix::detail::materializeResult(std::move(_lix_awaited)); \ +#define LIX_TRY_AWAIT_CONTEXT_MAP(_l_ctx, _l_map, ...) \ + ({ \ + auto _lix_awaited = (_l_map) (co_await (__VA_ARGS__)); \ + if (_lix_awaited.has_error()) { \ + try { \ + _lix_awaited.value(); \ + } catch (...) { \ + ::nix::detail::rethrow_async_exception_as_lix(_l_ctx()); \ + } \ + } \ + ::nix::detail::materializeResult(std::move(_lix_awaited)); \ }) #define LIX_TRY_AWAIT_CONTEXT(_l_ctx, ...) \