From cfdcb4f39c182b2fdea3a0f97a30d8314e8349b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Sun, 27 Oct 2024 18:47:59 +0100 Subject: [PATCH] Move assert to a dedicated header --- nano/lib/CMakeLists.txt | 2 ++ nano/lib/assert.cpp | 45 +++++++++++++++++++++++++++++++++++++++++ nano/lib/assert.hpp | 33 ++++++++++++++++++++++++++++++ nano/lib/utility.cpp | 41 ------------------------------------- nano/lib/utility.hpp | 30 +-------------------------- 5 files changed, 81 insertions(+), 70 deletions(-) create mode 100644 nano/lib/assert.cpp create mode 100644 nano/lib/assert.hpp diff --git a/nano/lib/CMakeLists.txt b/nano/lib/CMakeLists.txt index 748df5439..0caefa9f7 100644 --- a/nano/lib/CMakeLists.txt +++ b/nano/lib/CMakeLists.txt @@ -21,6 +21,8 @@ add_library( ${platform_sources} asio.hpp asio.cpp + assert.hpp + assert.cpp block_sideband.hpp block_sideband.cpp block_type.hpp diff --git a/nano/lib/assert.cpp b/nano/lib/assert.cpp new file mode 100644 index 000000000..7d8652efb --- /dev/null +++ b/nano/lib/assert.cpp @@ -0,0 +1,45 @@ +#include +#include + +#include + +/* + * Backing code for "release_assert" & "debug_assert", which are macros + */ +void assert_internal (char const * check_expr, char const * func, char const * file, unsigned int line, bool is_release_assert, std::string_view error_msg) +{ + std::cerr << "Assertion (" << check_expr << ") failed\n" + << func << "\n" + << file << ":" << line << "\n"; + if (!error_msg.empty ()) + { + std::cerr << "Error: " << error_msg << "\n"; + } + std::cerr << "\n"; + + // Output stack trace to cerr + auto backtrace_str = nano::generate_stacktrace (); + std::cerr << backtrace_str << std::endl; + + // "abort" at the end of this function will go into any signal handlers (the daemon ones will generate a stack trace and load memory address files on non-Windows systems). + // As there is no async-signal-safe way to generate stacktraces on Windows it must be done before aborting +#ifdef _WIN32 + { + // Try construct the stacktrace dump in the same folder as the running executable, otherwise use the current directory. + boost::system::error_code err; + auto running_executable_filepath = boost::dll::program_location (err); + std::string filename = is_release_assert ? "nano_node_backtrace_release_assert.txt" : "nano_node_backtrace_assert.txt"; + std::string filepath = filename; + if (!err) + { + filepath = (running_executable_filepath.parent_path () / filename).string (); + } + + std::ofstream file (filepath); + nano::set_secure_perm_file (filepath); + file << backtrace_str; + } +#endif + + abort (); +} \ No newline at end of file diff --git a/nano/lib/assert.hpp b/nano/lib/assert.hpp new file mode 100644 index 000000000..94eb20559 --- /dev/null +++ b/nano/lib/assert.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +#include + +[[noreturn]] void assert_internal (char const * check_expr, char const * func, char const * file, unsigned int line, bool is_release_assert, std::string_view error = ""); + +#define release_assert_1(check) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, true) +#define release_assert_2(check, error_msg) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, true, error_msg) +#if !BOOST_PP_VARIADICS_MSVC +#define release_assert(...) \ + BOOST_PP_OVERLOAD (release_assert_, __VA_ARGS__) \ + (__VA_ARGS__) +#else +#define release_assert(...) BOOST_PP_CAT (BOOST_PP_OVERLOAD (release_assert_, __VA_ARGS__) (__VA_ARGS__), BOOST_PP_EMPTY ()) +#endif + +#ifdef NDEBUG +#define debug_assert(...) (void)0 +#else +#define debug_assert_1(check) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, false) +#define debug_assert_2(check, error_msg) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, false, error_msg) +#if !BOOST_PP_VARIADICS_MSVC +#define debug_assert(...) \ + BOOST_PP_OVERLOAD (debug_assert_, __VA_ARGS__) \ + (__VA_ARGS__) +#else +#define debug_assert(...) BOOST_PP_CAT (BOOST_PP_OVERLOAD (debug_assert_, __VA_ARGS__) (__VA_ARGS__), BOOST_PP_EMPTY ()) +#endif +#endif \ No newline at end of file diff --git a/nano/lib/utility.cpp b/nano/lib/utility.cpp index d33a7e765..6eaf6fa6c 100644 --- a/nano/lib/utility.cpp +++ b/nano/lib/utility.cpp @@ -87,47 +87,6 @@ void nano::move_all_files_to_dir (std::filesystem::path const & from, std::files } } -/* - * Backing code for "release_assert" & "debug_assert", which are macros - */ -void assert_internal (char const * check_expr, char const * func, char const * file, unsigned int line, bool is_release_assert, std::string_view error_msg) -{ - std::cerr << "Assertion (" << check_expr << ") failed\n" - << func << "\n" - << file << ":" << line << "\n"; - if (!error_msg.empty ()) - { - std::cerr << "Error: " << error_msg << "\n"; - } - std::cerr << "\n"; - - // Output stack trace to cerr - auto backtrace_str = nano::generate_stacktrace (); - std::cerr << backtrace_str << std::endl; - - // "abort" at the end of this function will go into any signal handlers (the daemon ones will generate a stack trace and load memory address files on non-Windows systems). - // As there is no async-signal-safe way to generate stacktraces on Windows it must be done before aborting -#ifdef _WIN32 - { - // Try construct the stacktrace dump in the same folder as the running executable, otherwise use the current directory. - boost::system::error_code err; - auto running_executable_filepath = boost::dll::program_location (err); - std::string filename = is_release_assert ? "nano_node_backtrace_release_assert.txt" : "nano_node_backtrace_assert.txt"; - std::string filepath = filename; - if (!err) - { - filepath = (running_executable_filepath.parent_path () / filename).string (); - } - - std::ofstream file (filepath); - nano::set_secure_perm_file (filepath); - file << backtrace_str; - } -#endif - - abort (); -} - // Issue #3748 void nano::sort_options_description (const boost::program_options::options_description & source, boost::program_options::options_description & target) { diff --git a/nano/lib/utility.hpp b/nano/lib/utility.hpp index d8bb29bec..d4ea83ba9 100644 --- a/nano/lib/utility.hpp +++ b/nano/lib/utility.hpp @@ -1,12 +1,10 @@ #pragma once +#include #include #include -#include #include -#include -#include #include #include @@ -28,32 +26,6 @@ namespace program_options } } -[[noreturn]] void assert_internal (char const * check_expr, char const * func, char const * file, unsigned int line, bool is_release_assert, std::string_view error = ""); - -#define release_assert_1(check) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, true) -#define release_assert_2(check, error_msg) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, true, error_msg) -#if !BOOST_PP_VARIADICS_MSVC -#define release_assert(...) \ - BOOST_PP_OVERLOAD (release_assert_, __VA_ARGS__) \ - (__VA_ARGS__) -#else -#define release_assert(...) BOOST_PP_CAT (BOOST_PP_OVERLOAD (release_assert_, __VA_ARGS__) (__VA_ARGS__), BOOST_PP_EMPTY ()) -#endif - -#ifdef NDEBUG -#define debug_assert(...) (void)0 -#else -#define debug_assert_1(check) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, false) -#define debug_assert_2(check, error_msg) check ? (void)0 : assert_internal (#check, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, false, error_msg) -#if !BOOST_PP_VARIADICS_MSVC -#define debug_assert(...) \ - BOOST_PP_OVERLOAD (debug_assert_, __VA_ARGS__) \ - (__VA_ARGS__) -#else -#define debug_assert(...) BOOST_PP_CAT (BOOST_PP_OVERLOAD (debug_assert_, __VA_ARGS__) (__VA_ARGS__), BOOST_PP_EMPTY ()) -#endif -#endif - namespace nano { // Lower priority of calling work generating thread