From ede2439a552202170411076890fb8066ca659928 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Fri, 15 Mar 2019 13:01:26 -0700 Subject: [PATCH] ircd: Add support for configurable soft-assertions. --- configure.ac | 31 ++++++++++++++- include/ircd/assert.h | 39 +++++++++++++++++++ include/ircd/ircd.h | 1 + include/ircd/logger.h | 24 +++++++++--- include/ircd/stdinc.h | 1 + ircd/Makefile.am | 1 + ircd/assert.cc | 91 +++++++++++++++++++++++++++++++++++++++++++ ircd/exception.cc | 4 +- 8 files changed, 183 insertions(+), 9 deletions(-) create mode 100644 include/ircd/assert.h create mode 100644 ircd/assert.cc diff --git a/configure.ac b/configure.ac index 54d14b1f2..4f70c5561 100644 --- a/configure.ac +++ b/configure.ac @@ -184,6 +184,34 @@ AM_COND_IF(ASSERT, CPPDEFINE([NDEBUG]) ]) +dnl +dnl Switch to control the action of assert() +dnl + +AC_MSG_CHECKING(whether to change the behavior of assertions) +AC_ARG_WITH(assert, AC_HELP_STRING([--with-assert[[[=trap]]]], [Soften assertion behavior]), +[ + assert_type=$withval + AC_MSG_RESULT([yes]) + AC_SUBST(ASSERT_TYPE, $assert_type) +], [ + AM_COND_IF(DEBUG, + [ + assert_type="trap" + AC_MSG_RESULT([no, defaulting to "$assert_type"]) + AC_SUBST(ASSERT_TYPE, $assert_type) + ], [ + AC_MSG_RESULT([no]) + ]) +]) + +AM_COND_IF(ASSERT, +[ + if [[ ! -z "$assert_type" ]]; then + RB_DEFINE_UNQUOTED([ASSERT], ["$assert_type"], [Assertion behavior]) + fi +]) + dnl dnl Explicit optimize switch for enabling optimization when using --enable-debug dnl @@ -616,6 +644,7 @@ RB_CHK_SYSHEADER(stdarg.h, [STDARG_H]) dnl libc++ RB_CHK_SYSHEADER(cstddef, [CSTDDEF]) RB_CHK_SYSHEADER(cstdint, [CSTDINT]) +RB_CHK_SYSHEADER(cstdlib, [CSTDLIB]) RB_CHK_SYSHEADER(limits, [LIMITS]) RB_CHK_SYSHEADER(type_traits, [TYPE_TRAITS]) RB_CHK_SYSHEADER(typeindex, [TYPEINDEX]) @@ -1582,7 +1611,7 @@ echo "Linux AIO support ................. $aio" echo "IPv6 support ...................... $ipv6" echo "Precompiled headers ............... $build_pch" echo "Developer debug ................... $debug" -echo "Developer assert .................. $assert" +echo "Developer assert .................. $assert ($assert_type)" echo "Optimized build ................... $optimize" echo "Link-time optimized ............... $lto" echo "Optimization level ................ $optimize_level" diff --git a/include/ircd/assert.h b/include/ircd/assert.h new file mode 100644 index 000000000..5858f58d0 --- /dev/null +++ b/include/ircd/assert.h @@ -0,0 +1,39 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +// This header allows for the use of soft-assertions. It is included before +// the standard and these declarations will take precedence. +// +// These declarations exist because the system declarations may have +// __attribute__((noreturn)) and our only modification here is to remove +// that. Alternative definitions to the standard library also exist in +// ircd/assert.cc + +#if defined(RB_ASSERT) && !defined(NDEBUG) +#define _ASSERT_H_DECLS + +extern "C" void +__assert_fail(const char *__assertion, + const char *__file, + unsigned int __line, + const char *__function); + +extern "C" void +__assert_perror_fail(int __errnum, + const char *__file, + unsigned int __line, + const char *__function); + +extern "C" void +__assert(const char *__assertion, + const char *__file, + int __line); + +#endif diff --git a/include/ircd/ircd.h b/include/ircd/ircd.h index 57ef00050..b521c8566 100644 --- a/include/ircd/ircd.h +++ b/include/ircd/ircd.h @@ -12,6 +12,7 @@ // Generated by ./configure #include "config.h" +#include "assert.h" #include "stdinc.h" #include "string_view.h" #include "vector_view.h" diff --git a/include/ircd/logger.h b/include/ircd/logger.h index 555a2897e..b56ca8ea1 100644 --- a/include/ircd/logger.h +++ b/include/ircd/logger.h @@ -100,7 +100,7 @@ struct ircd::log::log public: template void operator()(const level &, const string_view &fmt, args&&...); - #if RB_LOG_LEVEL >= 0 && !defined(NDEBUG) + #if RB_LOG_LEVEL >= 0 && !defined(NDEBUG) && !defined(RB_ASSERT) template [[noreturn]] void critical(const string_view &fmt, args&&...); #elif RB_LOG_LEVEL >= 0 template void critical(const string_view &fmt, args&&...); @@ -398,18 +398,30 @@ struct ircd::log::error #if RB_LOG_LEVEL >= 0 && !defined(NDEBUG) struct ircd::log::critical { - template [[noreturn]] + template + #if !defined(RB_ASSERT) + [[noreturn]] + #endif critical(const log &log, const string_view &fmt, args&&... a) { vlog(log, level::CRITICAL, fmt, va_rtti{std::forward(a)...}); - ircd::terminate(); + + #ifndef NDEBUG + __assert_fail("critical", "", 0, ""); + #endif } - template [[noreturn]] + template + #if !defined(RB_ASSERT) + [[noreturn]] + #endif critical(const string_view &fmt, args&&... a) { vlog(general, level::CRITICAL, fmt, va_rtti{std::forward(a)...}); - ircd::terminate(); + + #ifndef NDEBUG + __assert_fail("critical", "", 0, ""); + #endif } }; #elif RB_LOG_LEVEL >= 0 @@ -570,7 +582,7 @@ ircd::log::log::critical(const string_view &fmt, operator()(level::CRITICAL, fmt, va_rtti{std::forward(a)...}); #ifndef NDEBUG - ircd::terminate();; + __assert_fail("critical", "", 0, ""); #endif } #else diff --git a/include/ircd/stdinc.h b/include/ircd/stdinc.h index 3659d7643..0f62c364e 100644 --- a/include/ircd/stdinc.h +++ b/include/ircd/stdinc.h @@ -39,6 +39,7 @@ extern "C" #include +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#if !defined(NDEBUG) && defined(RB_ASSERT) +#include "); +} +#endif diff --git a/ircd/exception.cc b/ircd/exception.cc index d849c8cbe..4fa250da7 100644 --- a/ircd/exception.cc +++ b/ircd/exception.cc @@ -25,7 +25,7 @@ noexcept } void -#ifndef NDEBUG +#if !defined(NDEBUG) && !defined(RB_ASSERT) __attribute__((noreturn)) #endif ircd::panicking(const std::exception_ptr &eptr) @@ -41,7 +41,7 @@ noexcept /// log a critical message, which is actually what triggers a termination when /// assertions are enabled (!NDEBUG) otherwise a no-op. void -#ifndef NDEBUG +#if !defined(NDEBUG) && !defined(RB_ASSERT) __attribute__((noreturn)) #endif ircd::panicking(const std::exception &e)