diff --git a/nano/core_test/CMakeLists.txt b/nano/core_test/CMakeLists.txt index 96f75f2bb0..bb4e6e9a09 100644 --- a/nano/core_test/CMakeLists.txt +++ b/nano/core_test/CMakeLists.txt @@ -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 diff --git a/nano/core_test/assert.cpp b/nano/core_test/assert.cpp new file mode 100644 index 0000000000..32a40a3000 --- /dev/null +++ b/nano/core_test/assert.cpp @@ -0,0 +1,15 @@ +#include + +#include + +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.*"); +} \ No newline at end of file diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index 191b7575fc..e4294663e5 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include diff --git a/nano/core_test/entry.cpp b/nano/core_test/entry.cpp index 7c51ce85b9..929544a834 100644 --- a/nano/core_test/entry.cpp +++ b/nano/core_test/entry.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/nano/core_test/utility.cpp b/nano/core_test/utility.cpp index e7049a7d9d..049484fa5e 100644 --- a/nano/core_test/utility.cpp +++ b/nano/core_test/utility.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/nano/lib/CMakeLists.txt b/nano/lib/CMakeLists.txt index 748df54398..9ef472a1b4 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 @@ -49,6 +51,8 @@ add_library( epochs.hpp errors.hpp errors.cpp + files.hpp + files.cpp fwd.hpp id_dispenser.hpp interval.hpp diff --git a/nano/lib/assert.cpp b/nano/lib/assert.cpp new file mode 100644 index 0000000000..cc2a9bb32d --- /dev/null +++ b/nano/lib/assert.cpp @@ -0,0 +1,49 @@ +#include +#include +#include + +#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 0000000000..94eb205595 --- /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/files.cpp b/nano/lib/files.cpp new file mode 100644 index 0000000000..434a32c8f3 --- /dev/null +++ b/nano/lib/files.cpp @@ -0,0 +1,85 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +std::size_t nano::get_file_descriptor_limit () +{ + std::size_t fd_limit = std::numeric_limits::max (); +#ifndef _WIN32 + rlimit limit{}; + if (getrlimit (RLIMIT_NOFILE, &limit) == 0) + { + fd_limit = static_cast (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 (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 ()); + } + } +} \ No newline at end of file diff --git a/nano/lib/files.hpp b/nano/lib/files.hpp new file mode 100644 index 0000000000..b0ed9dcaa6 --- /dev/null +++ b/nano/lib/files.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include + +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); +} \ No newline at end of file diff --git a/nano/lib/jsonconfig.cpp b/nano/lib/jsonconfig.cpp index 74523154c2..a92ac7ca00 100644 --- a/nano/lib/jsonconfig.cpp +++ b/nano/lib/jsonconfig.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/nano/lib/jsonconfig.hpp b/nano/lib/jsonconfig.hpp index 27827dfc72..d7ca5fc33f 100644 --- a/nano/lib/jsonconfig.hpp +++ b/nano/lib/jsonconfig.hpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace boost diff --git a/nano/lib/plat/default/debugging.cpp b/nano/lib/plat/default/debugging.cpp index 1489fa80ac..3ca179f024 100644 --- a/nano/lib/plat/default/debugging.cpp +++ b/nano/lib/plat/default/debugging.cpp @@ -1,3 +1,4 @@ +#include #include void nano::create_load_memory_address_files () diff --git a/nano/lib/plat/linux/debugging.cpp b/nano/lib/plat/linux/debugging.cpp index caee1b910e..e9f4207a88 100644 --- a/nano/lib/plat/linux/debugging.cpp +++ b/nano/lib/plat/linux/debugging.cpp @@ -1,3 +1,4 @@ +#include #include #include diff --git a/nano/lib/plat/posix/perms.cpp b/nano/lib/plat/posix/perms.cpp index 5512c4546b..2544451af6 100644 --- a/nano/lib/plat/posix/perms.cpp +++ b/nano/lib/plat/posix/perms.cpp @@ -1,3 +1,4 @@ +#include #include #include diff --git a/nano/lib/plat/windows/perms.cpp b/nano/lib/plat/windows/perms.cpp index dc5122b7f2..ac2ff14840 100644 --- a/nano/lib/plat/windows/perms.cpp +++ b/nano/lib/plat/windows/perms.cpp @@ -1,3 +1,4 @@ +#include #include // clang-format off diff --git a/nano/lib/plat/windows/priority.cpp b/nano/lib/plat/windows/priority.cpp index e9945b0b0f..4a87451708 100644 --- a/nano/lib/plat/windows/priority.cpp +++ b/nano/lib/plat/windows/priority.cpp @@ -1,4 +1,5 @@ #include + namespace nano { void work_thread_reprioritize () diff --git a/nano/lib/tomlconfig.cpp b/nano/lib/tomlconfig.cpp index ff998dbab9..4922d67fcf 100644 --- a/nano/lib/tomlconfig.cpp +++ b/nano/lib/tomlconfig.cpp @@ -1,4 +1,5 @@ #include +#include #include nano::tomlconfig::tomlconfig () : diff --git a/nano/lib/tomlconfig.hpp b/nano/lib/tomlconfig.hpp index a56524c021..bf32806cdd 100644 --- a/nano/lib/tomlconfig.hpp +++ b/nano/lib/tomlconfig.hpp @@ -6,6 +6,8 @@ #include #include +#include + #include namespace boost diff --git a/nano/lib/utility.cpp b/nano/lib/utility.cpp index d33a7e765d..9fa56e9589 100644 --- a/nano/lib/utility.cpp +++ b/nano/lib/utility.cpp @@ -1,133 +1,7 @@ -#include #include -#include #include -#include -#include -#include -#include -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - -std::size_t nano::get_file_descriptor_limit () -{ - std::size_t fd_limit = std::numeric_limits::max (); -#ifndef _WIN32 - rlimit limit{}; - if (getrlimit (RLIMIT_NOFILE, &limit) == 0) - { - fd_limit = static_cast (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 (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 ()); - } - } -} - -/* - * 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 d8bb29bec1..ef31b01e35 100644 --- a/nano/lib/utility.hpp +++ b/nano/lib/utility.hpp @@ -1,17 +1,12 @@ #pragma once +#include #include #include -#include #include -#include -#include -#include -#include #include -#include #include #include @@ -28,79 +23,11 @@ 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 void work_thread_reprioritize (); -/* - * 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); - template void transform_if (InputIt first, InputIt last, OutputIt dest, Pred pred, Func transform) { diff --git a/nano/nano_node/daemon.cpp b/nano/nano_node/daemon.cpp index 45eaea5509..2922b729de 100644 --- a/nano/nano_node/daemon.cpp +++ b/nano/nano_node/daemon.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index 5477769e7d..740916bb29 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include diff --git a/nano/nano_rpc/entry.cpp b/nano/nano_rpc/entry.cpp index c54b335869..3b59879335 100644 --- a/nano/nano_rpc/entry.cpp +++ b/nano/nano_rpc/entry.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/nano/nano_wallet/entry.cpp b/nano/nano_wallet/entry.cpp index 4f149aa51d..a8ce90d34b 100644 --- a/nano/nano_wallet/entry.cpp +++ b/nano/nano_wallet/entry.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include diff --git a/nano/node/cli.cpp b/nano/node/cli.cpp index e0622e940a..c5b29888d2 100644 --- a/nano/node/cli.cpp +++ b/nano/node/cli.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/nano/node/node.cpp b/nano/node/node.cpp index d27d2188b4..8ec67d597b 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/nano/node/node_wrapper.cpp b/nano/node/node_wrapper.cpp index 5f4f1a17b9..a49fd759bb 100644 --- a/nano/node/node_wrapper.cpp +++ b/nano/node/node_wrapper.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index ba65fe0dc5..c2c2101c70 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/nano/qt_test/entry.cpp b/nano/qt_test/entry.cpp index 1847ff850d..e0a4255078 100644 --- a/nano/qt_test/entry.cpp +++ b/nano/qt_test/entry.cpp @@ -1,3 +1,4 @@ +#include #include #include diff --git a/nano/rpc_test/entry.cpp b/nano/rpc_test/entry.cpp index e16a3f4e5f..4cfa6e0b3d 100644 --- a/nano/rpc_test/entry.cpp +++ b/nano/rpc_test/entry.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index 854b04375a..d644741863 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/nano/slow_test/entry.cpp b/nano/slow_test/entry.cpp index 83d12130de..0659075b55 100644 --- a/nano/slow_test/entry.cpp +++ b/nano/slow_test/entry.cpp @@ -1,3 +1,4 @@ +#include #include #include diff --git a/nano/store/lmdb/lmdb_env.cpp b/nano/store/lmdb/lmdb_env.cpp index b30718960f..eeae96d584 100644 --- a/nano/store/lmdb/lmdb_env.cpp +++ b/nano/store/lmdb/lmdb_env.cpp @@ -1,3 +1,4 @@ +#include #include #include diff --git a/nano/store/rocksdb/rocksdb.cpp b/nano/store/rocksdb/rocksdb.cpp index 75f3e51497..b356064f42 100644 --- a/nano/store/rocksdb/rocksdb.cpp +++ b/nano/store/rocksdb/rocksdb.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include