Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move assert to a dedicated header #4773

Merged
merged 3 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nano/core_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_executable(
fakes/websocket_client.hpp
fakes/work_peer.hpp
active_elections.cpp
assert.cpp
async.cpp
backlog.cpp
block.cpp
Expand Down
15 changes: 15 additions & 0 deletions nano/core_test/assert.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <nano/lib/assert.hpp>

#include <gtest/gtest.h>

TEST (assert_DeathTest, debug_assert)
{
debug_assert (true);
ASSERT_DEATH (debug_assert (false), ".*Assertion \\(false\\) failed.*");
}

TEST (assert_DeathTest, release_assert)
{
release_assert (true);
ASSERT_DEATH (release_assert (false), ".*Assertion \\(false\\) failed.*");
}
1 change: 1 addition & 0 deletions nano/core_test/block_store.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <nano/crypto_lib/random_pool.hpp>
#include <nano/lib/block_type.hpp>
#include <nano/lib/blocks.hpp>
#include <nano/lib/files.hpp>
#include <nano/lib/lmdbconfig.hpp>
#include <nano/lib/logging.hpp>
#include <nano/lib/stats.hpp>
Expand Down
1 change: 1 addition & 0 deletions nano/core_test/entry.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <nano/lib/files.hpp>
#include <nano/lib/logging.hpp>
#include <nano/lib/memory.hpp>
#include <nano/secure/utility.hpp>
Expand Down
1 change: 1 addition & 0 deletions nano/core_test/utility.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <nano/lib/files.hpp>
#include <nano/lib/optional_ptr.hpp>
#include <nano/lib/rate_limiting.hpp>
#include <nano/lib/relaxed_atomic.hpp>
Expand Down
4 changes: 4 additions & 0 deletions nano/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -49,6 +51,8 @@ add_library(
epochs.hpp
errors.hpp
errors.cpp
files.hpp
files.cpp
fwd.hpp
id_dispenser.hpp
interval.hpp
Expand Down
49 changes: 49 additions & 0 deletions nano/lib/assert.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <nano/lib/assert.hpp>
#include <nano/lib/files.hpp>
#include <nano/lib/stacktrace.hpp>

#include <boost/dll/runtime_symbol_info.hpp>

#include <fstream>
#include <iostream>

/*
* 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 ();
}
33 changes: 33 additions & 0 deletions nano/lib/assert.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <boost/current_function.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/facilities/overload.hpp>

#include <string_view>

[[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
85 changes: 85 additions & 0 deletions nano/lib/files.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include <nano/lib/files.hpp>

#include <cstddef>
#include <cstring>
#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
#include <string_view>
#include <thread>

#ifndef _WIN32
#include <sys/resource.h>
#endif

std::size_t nano::get_file_descriptor_limit ()
{
std::size_t fd_limit = std::numeric_limits<std::size_t>::max ();
#ifndef _WIN32
rlimit limit{};
if (getrlimit (RLIMIT_NOFILE, &limit) == 0)
{
fd_limit = static_cast<std::size_t> (limit.rlim_cur);
}
#endif
return fd_limit;
}

void nano::set_file_descriptor_limit (std::size_t limit)
{
#ifndef _WIN32
rlimit fd_limit{};
if (-1 == getrlimit (RLIMIT_NOFILE, &fd_limit))
{
std::cerr << "WARNING: Unable to get current limits for the number of open file descriptors: " << std::strerror (errno);
return;
}

if (fd_limit.rlim_cur >= limit)
{
return;
}

fd_limit.rlim_cur = std::min (static_cast<rlim_t> (limit), fd_limit.rlim_max);
if (-1 == setrlimit (RLIMIT_NOFILE, &fd_limit))
{
std::cerr << "WARNING: Unable to set limits for the number of open file descriptors: " << std::strerror (errno);
return;
}
#endif
}

void nano::initialize_file_descriptor_limit ()
{
nano::set_file_descriptor_limit (DEFAULT_FILE_DESCRIPTOR_LIMIT);
auto limit = nano::get_file_descriptor_limit ();
if (limit < DEFAULT_FILE_DESCRIPTOR_LIMIT)
{
std::cerr << "WARNING: Current file descriptor limit of " << limit << " is lower than the " << DEFAULT_FILE_DESCRIPTOR_LIMIT << " recommended. Node was unable to change it." << std::endl;
}
}

void nano::remove_all_files_in_dir (std::filesystem::path const & dir)
{
for (auto & p : std::filesystem::directory_iterator (dir))
{
auto path = p.path ();
if (std::filesystem::is_regular_file (path))
{
std::filesystem::remove (path);
}
}
}

void nano::move_all_files_to_dir (std::filesystem::path const & from, std::filesystem::path const & to)
{
for (auto & p : std::filesystem::directory_iterator (from))
{
auto path = p.path ();
if (std::filesystem::is_regular_file (path))
{
std::filesystem::rename (path, to / path.filename ());
}
}
}
48 changes: 48 additions & 0 deletions nano/lib/files.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once

#include <filesystem>

namespace nano
{
/*
* Functions for managing filesystem permissions, platform specific
*/
void set_umask ();
void set_secure_perm_directory (std::filesystem::path const & path);
void set_secure_perm_directory (std::filesystem::path const & path, std::error_code & ec);
void set_secure_perm_file (std::filesystem::path const & path);
void set_secure_perm_file (std::filesystem::path const & path, std::error_code & ec);

/*
* Function to check if running Windows as an administrator
*/
bool is_windows_elevated ();

/*
* Function to check if the Windows Event log registry key exists
*/
bool event_log_reg_entry_exists ();

/*
* Create the load memory addresses for the executable and shared libraries.
*/
void create_load_memory_address_files ();

/**
* Some systems, especially in virtualized environments, may have very low file descriptor limits,
* causing the node to fail. This function attempts to query the limit and returns the value. If the
* limit cannot be queried, or running on a Windows system, this returns max-value of std::size_t.
* Increasing the limit programmatically can be done only for the soft limit, the hard one requiring
* super user permissions to modify.
*/
std::size_t get_file_descriptor_limit ();
void set_file_descriptor_limit (std::size_t limit);
/**
* This should be called from entry points. It sets the file descriptor limit to the maximum allowed and logs any errors.
*/
constexpr std::size_t DEFAULT_FILE_DESCRIPTOR_LIMIT = 16384;
void initialize_file_descriptor_limit ();

void remove_all_files_in_dir (std::filesystem::path const & dir);
void move_all_files_to_dir (std::filesystem::path const & from, std::filesystem::path const & to);
}
1 change: 1 addition & 0 deletions nano/lib/jsonconfig.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <nano/boost/asio/ip/address_v6.hpp>
#include <nano/lib/files.hpp>
#include <nano/lib/jsonconfig.hpp>

#include <boost/property_tree/json_parser.hpp>
Expand Down
1 change: 1 addition & 0 deletions nano/lib/jsonconfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/property_tree/ptree.hpp>

#include <filesystem>
#include <fstream>

namespace boost
Expand Down
1 change: 1 addition & 0 deletions nano/lib/plat/default/debugging.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <nano/lib/files.hpp>
#include <nano/lib/utility.hpp>

void nano::create_load_memory_address_files ()
Expand Down
1 change: 1 addition & 0 deletions nano/lib/plat/linux/debugging.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <nano/lib/files.hpp>
#include <nano/lib/utility.hpp>

#include <cstring>
Expand Down
1 change: 1 addition & 0 deletions nano/lib/plat/posix/perms.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <nano/lib/files.hpp>
#include <nano/lib/utility.hpp>

#include <sys/stat.h>
Expand Down
1 change: 1 addition & 0 deletions nano/lib/plat/windows/perms.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <nano/lib/files.hpp>
#include <nano/lib/utility.hpp>

// clang-format off
Expand Down
1 change: 1 addition & 0 deletions nano/lib/plat/windows/priority.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <windows.h>

namespace nano
{
void work_thread_reprioritize ()
Expand Down
1 change: 1 addition & 0 deletions nano/lib/tomlconfig.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <nano/boost/asio/ip/address_v6.hpp>
#include <nano/lib/files.hpp>
#include <nano/lib/tomlconfig.hpp>

nano::tomlconfig::tomlconfig () :
Expand Down
2 changes: 2 additions & 0 deletions nano/lib/tomlconfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>

#include <filesystem>

#include <cpptoml.h>

namespace boost
Expand Down
Loading
Loading