mirror of
https://github.com/matrix-construct/construct
synced 2024-12-27 07:54:05 +01:00
ircd: Add ircd::assertion and exception suite for assertive errors.
This commit is contained in:
parent
c8aaeb491f
commit
9e086e9acd
2 changed files with 75 additions and 2 deletions
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
namespace ircd
|
namespace ircd
|
||||||
{
|
{
|
||||||
|
// Root exception
|
||||||
struct exception;
|
struct exception;
|
||||||
|
|
||||||
// Prefer ircd::terminate() to std::terminate() if possible.
|
// Prefer ircd::terminate() to std::terminate() if possible.
|
||||||
|
@ -35,6 +36,11 @@ namespace ircd
|
||||||
[[noreturn]] void terminate(std::exception_ptr) noexcept;
|
[[noreturn]] void terminate(std::exception_ptr) noexcept;
|
||||||
[[noreturn]] void terminate() noexcept;
|
[[noreturn]] void terminate() noexcept;
|
||||||
|
|
||||||
|
// Terminates in debug mode; throws in release mode; always logs critical.
|
||||||
|
[[noreturn]] void assertion(const std::exception &) noexcept(RB_DEBUG);
|
||||||
|
[[noreturn]] void assertion(std::exception_ptr) noexcept(RB_DEBUG);
|
||||||
|
[[noreturn]] void assertion() noexcept(RB_DEBUG);
|
||||||
|
|
||||||
// Can be used to clobber the std::terminate_handler
|
// Can be used to clobber the std::terminate_handler
|
||||||
void aborting() noexcept;
|
void aborting() noexcept;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +153,31 @@ struct name \
|
||||||
} \
|
} \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Creates an assertion-type exception.
|
||||||
|
///
|
||||||
|
/// Throwable exception which will terminate on construction in debug mode
|
||||||
|
/// but throw normally in release mode. Ideally this should never be thrown
|
||||||
|
/// in release mode because the termination in debug means a test can never
|
||||||
|
/// pass and the triggering callsite should be eliminated. Nevertheless it
|
||||||
|
/// throws normally in release mode.
|
||||||
|
#define IRCD_ASSERTION(parent, name) \
|
||||||
|
struct name \
|
||||||
|
:parent \
|
||||||
|
{ \
|
||||||
|
template<class... args> \
|
||||||
|
name(const char *const &fmt = " ", args&&... ap) noexcept(RB_DEBUG) \
|
||||||
|
:parent{generate_skip} \
|
||||||
|
{ \
|
||||||
|
generate(#name, fmt, va_rtti{std::forward<args>(ap)...}); \
|
||||||
|
ircd::assertion(*this); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
name(generate_skip_t) noexcept(RB_DEBUG) \
|
||||||
|
:parent{generate_skip} \
|
||||||
|
{ \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
|
||||||
namespace ircd
|
namespace ircd
|
||||||
{
|
{
|
||||||
/// Root error exception type. Inherit from this.
|
/// Root error exception type. Inherit from this.
|
||||||
|
@ -157,4 +188,8 @@ namespace ircd
|
||||||
///
|
///
|
||||||
IRCD_EXCEPTION(exception, error) // throw ircd::error("something bad")
|
IRCD_EXCEPTION(exception, error) // throw ircd::error("something bad")
|
||||||
IRCD_EXCEPTION(error, user_error) // throw ircd::user_error("something silly")
|
IRCD_EXCEPTION(error, user_error) // throw ircd::user_error("something silly")
|
||||||
|
|
||||||
|
// Assertion errors; see IRCD_ASSERTION docs.
|
||||||
|
IRCD_ASSERTION(exception, assertive)
|
||||||
|
IRCD_ASSERTION(assertive, not_implemented)
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,44 @@ noexcept
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::assertion()
|
||||||
|
noexcept(RB_DEBUG)
|
||||||
|
{
|
||||||
|
if(std::uncaught_exceptions())
|
||||||
|
{
|
||||||
|
assertion(std::current_exception());
|
||||||
|
} else {
|
||||||
|
log::critical("IRCd Assertion without active exception.");
|
||||||
|
assert(0);
|
||||||
|
throw assertive{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::assertion(std::exception_ptr eptr)
|
||||||
|
noexcept(RB_DEBUG) try
|
||||||
|
{
|
||||||
|
std::rethrow_exception(eptr);
|
||||||
|
}
|
||||||
|
catch(const std::exception &e)
|
||||||
|
{
|
||||||
|
assertion(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::assertion(const std::exception &e)
|
||||||
|
noexcept(RB_DEBUG)
|
||||||
|
{
|
||||||
|
log::critical("IRCd Assertion %s", e.what());
|
||||||
|
|
||||||
|
#ifdef RB_DEBUG
|
||||||
|
terminate(e);
|
||||||
|
#else
|
||||||
|
throw e;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ircd::terminate()
|
ircd::terminate()
|
||||||
noexcept
|
noexcept
|
||||||
|
@ -76,7 +114,7 @@ ircd::terminate(const std::exception &e)
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
log::critical("IRCd Terminated: %s", e.what());
|
log::critical("IRCd Terminated: %s", e.what());
|
||||||
std::terminate();
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] static void
|
[[noreturn]] static void
|
||||||
|
|
Loading…
Reference in a new issue