diff --git a/include/ircd/exception.h b/include/ircd/exception.h index d3c47bbd4..8c20794da 100644 --- a/include/ircd/exception.h +++ b/include/ircd/exception.h @@ -41,6 +41,7 @@ namespace ircd std::system_error make_system_error(const boost::system::system_error &); template std::exception_ptr make_system_eptr(args&&...); template [[noreturn]] void throw_system_error(args&&...); + template std::exception_ptr make_exception_ptr(args&&...); string_view string(const mutable_buffer &, const std::error_code &); string_view string(const mutable_buffer &, const std::system_error &); @@ -221,6 +222,19 @@ namespace ircd IRCD_PANICKING(panic, not_implemented) } +template +std::exception_ptr +ircd::make_exception_ptr(args&&... a) +try +{ + throw E{std::forward(a)...}; +} +catch(const E &) +{ + return std::current_exception(); +}; + template void ircd::throw_system_error(args&&... a) diff --git a/include/ircd/server/tag.h b/include/ircd/server/tag.h index 9da1b62d3..99231360f 100644 --- a/include/ircd/server/tag.h +++ b/include/ircd/server/tag.h @@ -43,7 +43,7 @@ struct ircd::server::tag std::unique_ptr cancellation; void set_exception(std::exception_ptr); - template void set_exception(args&&...); + template void set_exception(args&&...); template void set_value(args&&...); const_buffer make_write_content_buffer() const; diff --git a/ircd/ctx.cc b/ircd/ctx.cc index 352f782bd..be0a82a95 100644 --- a/ircd/ctx.cc +++ b/ircd/ctx.cc @@ -2039,16 +2039,20 @@ noexcept } ircd::ctx::promise_base::~promise_base() -noexcept +noexcept try { if(!valid()) return; if(refcount(state()) == 1) - set_exception(std::make_exception_ptr(broken_promise())); + throw broken_promise{}; else remove(state(), *this); } +catch(const std::exception &e) +{ + set_exception(std::current_exception()); +} void ircd::ctx::promise_base::set_exception(std::exception_ptr eptr) diff --git a/ircd/server.cc b/ircd/server.cc index d7e8965a6..7b61440ce 100644 --- a/ircd/server.cc +++ b/ircd/server.cc @@ -311,10 +311,7 @@ ircd::server::cancel(request &request) }; */ - tag.set_exception(canceled - { - "Request canceled" - }); + tag.set_exception("Request canceled"); // We got off easy... The link's write loop won't start an abandoned // request. All that has to be done is indicate a full cancellation @@ -414,10 +411,10 @@ void ircd::server::peer::cancel() { for(auto &link : this->links) - link.cancel_all(std::make_exception_ptr(canceled - { + link.cancel_all(make_exception_ptr + ( "Request was aborted due to interruption." - })); + )); } bool @@ -503,10 +500,10 @@ try "No link to peer %s available", hostcanon }; else - request.tag->set_exception(unavailable - { + request.tag->set_exception + ( "No link to peer %s available", hostcanon - }); + ); } catch(const std::exception &e) { @@ -854,10 +851,10 @@ void ircd::server::peer::disperse(link &link) { disperse_uncommitted(link); - link.cancel_committed(std::make_exception_ptr(canceled - { + link.cancel_committed(make_exception_ptr + ( "Request was aborted; though it was partially completed" - })); + )); assert(link.queue.empty()); } @@ -1738,9 +1735,9 @@ try assert(done || empty(overrun)); return overrun; } -catch(const buffer_overrun &e) +catch(const buffer_overrun &) { - tag.set_exception(e); + tag.set_exception(std::current_exception()); throw; } @@ -2573,13 +2570,13 @@ ircd::server::tag::read_content(const const_buffer &buffer, if(content_overflow() && !req.opt->truncate_content) { assert(state.content_read > size(content)); - set_exception(buffer_overrun - { + set_exception + ( "buffer of %zu bytes too small for content-length %zu bytes by %zu bytes", size(content), state.content_length, content_overflow() - }); + ); } else set_value(state.status); } @@ -3309,21 +3306,30 @@ ircd::server::tag::set_value(args&&... a) data(request->in.content), size(request->in.content) }; - set_exception(http::error{code, std::string{content}}); + set_exception(code, std::string{content}); return; } p.set_value(code); } -template +template void ircd::server::tag::set_exception(args&&... a) +try { if(abandoned()) return; - set_exception(std::make_exception_ptr(std::forward(a)...)); + throw E + { + std::forward(a)... + }; +} +catch(const std::exception &e) +{ + set_exception(std::current_exception()); } void diff --git a/modules/s_dns.cc b/modules/s_dns.cc index 69c38948a..cb2da6db4 100644 --- a/modules/s_dns.cc +++ b/modules/s_dns.cc @@ -65,13 +65,8 @@ ircd::net::dns::handle_ipport__A(callback_ipport_one callback, const hostport &hp, const rfc1035::record::A &record) { - static const ircd::net::not_found no_record - { - "Host has no A record" - }; - if(!eptr && !record.ip4) - eptr = std::make_exception_ptr(no_record); + eptr = make_exception_ptr("Host has no A record"); const ipport ipport { diff --git a/modules/s_dns_cache.cc b/modules/s_dns_cache.cc index b3456364d..50712d4e3 100644 --- a/modules/s_dns_cache.cc +++ b/modules/s_dns_cache.cc @@ -101,10 +101,12 @@ ircd::net::dns::cache::_get(const hostport &hp, //TODO: we don't cache what the error was, assuming it's //TODO: NXDomain can be incorrect and in bad ways downstream... static const auto rcode{3}; //NXDomain - eptr = std::make_exception_ptr(rfc1035::error - { - "protocol error #%u (cached) :%s", rcode, rfc1035::rcode.at(rcode) - }); + eptr = make_exception_ptr + ( + "protocol error #%u (cached) :%s", + rcode, + rfc1035::rcode.at(rcode) + ); } if(count < record.size()) @@ -143,10 +145,12 @@ ircd::net::dns::cache::_get(const hostport &hp, //TODO: we don't cache what the error was, assuming it's //TODO: NXDomain can be incorrect and in bad ways downstream... static const auto rcode{3}; //NXDomain - eptr = std::make_exception_ptr(rfc1035::error - { - "protocol error #%u (cached) :%s", rcode, rfc1035::rcode.at(rcode) - }); + eptr = make_exception_ptr + ( + "protocol error #%u (cached) :%s", + rcode, + rfc1035::rcode.at(rcode) + ); } if(count < record.size())