0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-05-18 10:53:48 +02:00

ircd: Add support for configurable soft-assertions.

This commit is contained in:
Jason Volk 2019-03-15 13:01:26 -07:00
parent 11afd2e590
commit ede2439a55
8 changed files with 183 additions and 9 deletions

View file

@ -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"

39
include/ircd/assert.h Normal file
View file

@ -0,0 +1,39 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
//
// 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 <assert.h> 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

View file

@ -12,6 +12,7 @@
// Generated by ./configure
#include "config.h"
#include "assert.h"
#include "stdinc.h"
#include "string_view.h"
#include "vector_view.h"

View file

@ -100,7 +100,7 @@ struct ircd::log::log
public:
template<class... args> 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<class... args> [[noreturn]] void critical(const string_view &fmt, args&&...);
#elif RB_LOG_LEVEL >= 0
template<class... args> 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<class... args> [[noreturn]]
template<class... args>
#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<args>(a)...});
ircd::terminate();
#ifndef NDEBUG
__assert_fail("critical", "", 0, "");
#endif
}
template<class... args> [[noreturn]]
template<class... args>
#if !defined(RB_ASSERT)
[[noreturn]]
#endif
critical(const string_view &fmt, args&&... a)
{
vlog(general, level::CRITICAL, fmt, va_rtti{std::forward<args>(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<args>(a)...});
#ifndef NDEBUG
ircd::terminate();;
__assert_fail("critical", "", 0, "");
#endif
}
#else

View file

@ -39,6 +39,7 @@ extern "C"
#include <RB_INC_CSTDDEF
#include <RB_INC_CSTDINT
#include <RB_INC_CSTDLIB
#include <RB_INC_LIMITS
#include <RB_INC_TYPE_TRAITS
#include <RB_INC_TYPEINDEX

View file

@ -100,6 +100,7 @@ libircd_la_LIBADD = \
# the units that compile spirit grammars otherwise they thrash weaker
# systems.
libircd_la_SOURCES = \
assert.cc \
info.cc \
allocator.cc \
exception.cc \

91
ircd/assert.cc Normal file
View file

@ -0,0 +1,91 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
//
// 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 <RB_INC_SIGNAL_H
#endif
#if !defined(NDEBUG) && defined(RB_ASSERT)
void
__assert_fail(const char *__assertion,
const char *__file,
unsigned int __line,
const char *__function)
{
if(strcmp(__assertion, "critical") != 0)
fprintf(stderr, "\nassertion failed [%s +%u] %s :%s\n",
__file,
__line,
__function,
__assertion);
if(strcmp(RB_ASSERT, "trap") == 0)
__asm__ volatile ("int $3");
else if(strcmp(RB_ASSERT, "quit") == 0)
ircd::quit();
#if defined(HAVE_EXCEPTION)
else if(strcmp(RB_ASSERT, "term") == 0)
{
std::terminate();
__builtin_unreachable();
}
#endif
#if defined(HAVE_CSTDLIB)
else if(strcmp(RB_ASSERT, "abort") == 0)
{
abort();
__builtin_unreachable();
}
#endif
#if defined(HAVE_SIGNAL_H)
else if(strcmp(RB_ASSERT, "SIGTRAP") == 0)
raise(SIGTRAP);
#endif
#if defined(HAVE_SIGNAL_H)
else if(strcmp(RB_ASSERT, "SIGQUIT") == 0)
raise(SIGSTOP);
#endif
#if defined(HAVE_SIGNAL_H)
else if(strcmp(RB_ASSERT, "SIGQUIT") == 0)
raise(SIGQUIT);
#endif
else __builtin_trap();
}
#endif
#if !defined(NDEBUG) && defined(RB_ASSERT)
void
__assert_perror_fail(int __errnum,
const char *__file,
unsigned int __line,
const char *__function)
{
char buf[32];
snprintf(buf, sizeof(buf), "perror #%d: ", __errnum);
__assert_fail(buf, __file, __line, __function);
}
#endif
#if !defined(NDEBUG) && defined(RB_ASSERT)
void
__assert(const char *__assertion,
const char *__file,
int __line)
{
__assert_fail(__assertion, __file, __line, "<no function>");
}
#endif

View file

@ -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)