diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index c8ac4affdd5..20ca6960276 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -32,6 +32,8 @@ #include #include +#include + namespace eosio { namespace chain { using resource_limits::resource_limits_manager; @@ -213,6 +215,14 @@ struct pending_state { }; struct controller_impl { + + // LLVM sets the new handler, we need to reset this to throw a bad_alloc exception so we can possibly exit cleanly + // and not just abort. + struct reset_new_handler { + reset_new_handler() { std::set_new_handler([](){ throw std::bad_alloc(); }); } + }; + + reset_new_handler rnh; // placed here to allow for this to be set before constructing the other fields controller& self; chainbase::database db; chainbase::database reversible_blocks; ///< a special database to persist blocks that have successfully been applied but are still reversible @@ -286,7 +296,8 @@ struct controller_impl { } controller_impl( const controller::config& cfg, controller& s, protocol_feature_set&& pfs, const chain_id_type& chain_id ) - :self(s), + :rnh(), + self(s), db( cfg.state_dir, cfg.read_only ? database::read_only : database::read_write, cfg.state_size, false, cfg.db_map_mode, cfg.db_hugepage_paths ), diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 4f96075fabc..b17afd01da5 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -57,7 +57,6 @@ namespace eosio { namespace chain { class controller { public: - struct config { flat_set sender_bypass_whiteblacklist; flat_set actor_whitelist; diff --git a/unittests/misc_tests.cpp b/unittests/misc_tests.cpp index 6e465674092..7414c8a104b 100644 --- a/unittests/misc_tests.cpp +++ b/unittests/misc_tests.cpp @@ -1110,6 +1110,16 @@ BOOST_AUTO_TEST_CASE(stable_priority_queue_test) { } FC_LOG_AND_RETHROW() } +// test that std::bad_alloc is being thrown +BOOST_AUTO_TEST_CASE(bad_alloc_test) { + tester t; // force a controller to be constructed and set the new_handler + int* ptr = nullptr; + const auto fail = [&]() { + ptr = new int[std::numeric_limits::max()/16]; + }; + BOOST_CHECK_THROW( fail(), std::bad_alloc ); + BOOST_CHECK( ptr == nullptr ); +} BOOST_AUTO_TEST_SUITE_END()