Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Fix db exhaustion - 1.7.x #7745

Merged
merged 8 commits into from
Aug 9, 2019
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
11 changes: 9 additions & 2 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ struct controller_impl {
template<typename Signal, typename Arg>
void emit( const Signal& s, Arg&& a ) {
try {
s(std::forward<Arg>(a));
s( std::forward<Arg>( a ));
} catch (std::bad_alloc& e) {
wlog( "std::bad_alloc" );
throw e;
} catch (boost::interprocess::bad_alloc& e) {
wlog( "bad alloc" );
throw e;
Expand Down Expand Up @@ -1154,13 +1157,17 @@ struct controller_impl {
});
in_trx_requiring_checks = true;
push_transaction( onbtrx, fc::time_point::maximum(), self.get_global_properties().configuration.min_transaction_cpu_usage, true );
} catch( const boost::interprocess::bad_alloc& e ) {
} catch( const std::bad_alloc& e ) {
elog( "on block transaction failed due to a std::bad_alloc" );
throw;
} catch( const boost::interprocess::bad_alloc& e ) {
elog( "on block transaction failed due to a bad allocation" );
throw;
} catch( const fc::exception& e ) {
wlog( "on block transaction failed, but shouldn't impact block generation, system contract needs update" );
edump((e.to_detail_string()));
} catch( ... ) {
elog( "on block transaction failed due to unknown exception" );
}

clear_expired_input_transactions();
Expand Down
19 changes: 16 additions & 3 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ fc::microseconds chain_plugin::get_abi_serializer_max_time() const {
return my->abi_serializer_max_time_ms;
}

void chain_plugin::log_guard_exception(const chain::guard_exception&e ) const {
void chain_plugin::log_guard_exception(const chain::guard_exception&e ) {
if (e.code() == chain::database_guard_exception::code_value) {
elog("Database has reached an unsafe level of usage, shutting down to avoid corrupting the database. "
"Please increase the value set for \"chain-state-db-size-mb\" and restart the process!");
Expand All @@ -993,7 +993,7 @@ void chain_plugin::log_guard_exception(const chain::guard_exception&e ) const {
dlog("Details: ${details}", ("details", e.to_detail_string()));
}

void chain_plugin::handle_guard_exception(const chain::guard_exception& e) const {
void chain_plugin::handle_guard_exception(const chain::guard_exception& e) {
log_guard_exception(e);

// quit the app
Expand All @@ -1006,6 +1006,12 @@ void chain_plugin::handle_db_exhaustion() {
std::_Exit(1);
}

void chain_plugin::handle_bad_alloc() {
elog("std::bad_alloc - memory exhausted");
//return -2 -- it's what programs/nodeos/main.cpp reports for std::exception
std::_Exit(-2);
}

namespace chain_apis {

const string read_only::KEYi64 = "i64";
Expand Down Expand Up @@ -1547,6 +1553,8 @@ void read_write::push_block(read_write::push_block_params&& params, next_functio
next(read_write::push_block_results{});
} catch ( boost::interprocess::bad_alloc& ) {
chain_plugin::handle_db_exhaustion();
} catch ( const std::bad_alloc& ) {
chain_plugin::handle_bad_alloc();
} CATCH_AND_CALL(next);
}

Expand Down Expand Up @@ -1584,6 +1592,8 @@ void read_write::push_transaction(const read_write::push_transaction_params& par

} catch ( boost::interprocess::bad_alloc& ) {
chain_plugin::handle_db_exhaustion();
} catch ( const std::bad_alloc& ) {
chain_plugin::handle_bad_alloc();
} CATCH_AND_CALL(next);
}

Expand Down Expand Up @@ -1616,7 +1626,10 @@ void read_write::push_transactions(const read_write::push_transactions_params& p
result->reserve(params.size());

push_recurse(this, 0, params_copy, result, next);

} catch ( boost::interprocess::bad_alloc& ) {
chain_plugin::handle_db_exhaustion();
} catch ( const std::bad_alloc& ) {
chain_plugin::handle_bad_alloc();
} CATCH_AND_CALL(next);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,11 +694,11 @@ class chain_plugin : public plugin<chain_plugin> {
chain::chain_id_type get_chain_id() const;
fc::microseconds get_abi_serializer_max_time() const;

void handle_guard_exception(const chain::guard_exception& e) const;

static void handle_guard_exception(const chain::guard_exception& e);
static void handle_db_exhaustion();
static void handle_bad_alloc();
private:
void log_guard_exception(const chain::guard_exception& e) const;
static void log_guard_exception(const chain::guard_exception& e);

unique_ptr<class chain_plugin_impl> my;
};
Expand Down
71 changes: 45 additions & 26 deletions plugins/producer_plugin/producer_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,30 @@ using std::vector;
using std::deque;
using boost::signals2::scoped_connection;

#undef FC_LOG_AND_DROP
#define LOG_AND_DROP() \
catch ( const guard_exception& e ) { \
chain_plugin::handle_guard_exception(e); \
} catch ( const std::bad_alloc& ) { \
chain_plugin::handle_bad_alloc(); \
} catch ( boost::interprocess::bad_alloc& ) { \
chain_plugin::handle_db_exhaustion(); \
} catch( fc::exception& er ) { \
wlog( "${details}", ("details",er.to_detail_string()) ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
FC_LOG_MESSAGE( warn, "std::exception: ${what}: ",("what",e.what()) ), \
fc::std_exception_code,\
BOOST_CORE_TYPEID(e).name(), \
e.what() ) ; \
wlog( "${details}", ("details",fce.to_detail_string()) ); \
} catch( ... ) { \
fc::unhandled_exception e( \
FC_LOG_MESSAGE( warn, "unknown: ", ), \
std::current_exception() ); \
wlog( "${details}", ("details",e.to_detail_string()) ); \
}

const fc::string logger_name("producer_plugin");
fc::logger _log;

Expand Down Expand Up @@ -312,14 +336,15 @@ class producer_plugin_impl : public std::enable_shared_from_this<producer_plugin
try {
chain.push_block( bsf );
} catch ( const guard_exception& e ) {
chain_plug->handle_guard_exception(e);
chain_plugin::handle_guard_exception(e);
return;
} catch( const fc::exception& e ) {
elog((e.to_detail_string()));
except = true;
} catch ( const std::bad_alloc& ) {
chain_plugin::handle_bad_alloc();
} catch ( boost::interprocess::bad_alloc& ) {
chain_plugin::handle_db_exhaustion();
return;
}

if( except ) {
Expand Down Expand Up @@ -441,9 +466,11 @@ class producer_plugin_impl : public std::enable_shared_from_this<producer_plugin
}

} catch ( const guard_exception& e ) {
chain_plug->handle_guard_exception(e);
chain_plugin::handle_guard_exception(e);
} catch ( boost::interprocess::bad_alloc& ) {
chain_plugin::handle_db_exhaustion();
} catch ( std::bad_alloc& ) {
chain_plugin::handle_bad_alloc();
} CATCH_AND_CALL(send_response);
}

Expand Down Expand Up @@ -703,13 +730,13 @@ void producer_plugin::plugin_initialize(const boost::program_options::variables_
my->_incoming_block_subscription = app().get_channel<incoming::channels::block>().subscribe([this](const signed_block_ptr& block){
try {
my->on_incoming_block(block);
} FC_LOG_AND_DROP();
} LOG_AND_DROP();
});

my->_incoming_transaction_subscription = app().get_channel<incoming::channels::transaction>().subscribe([this](const transaction_metadata_ptr& trx){
try {
my->on_incoming_transaction_async(trx, false, [](const auto&){});
} FC_LOG_AND_DROP();
} LOG_AND_DROP();
});

my->_incoming_block_sync_provider = app().get_method<incoming::methods::block_sync>().register_provider([this](const signed_block_ptr& block){
Expand Down Expand Up @@ -1117,7 +1144,7 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() {

chain.abort_block();
chain.start_block(block_time, blocks_to_confirm);
} FC_LOG_AND_DROP();
} LOG_AND_DROP();

const auto& pbs = chain.pending_block_state();
if (pbs) {
Expand Down Expand Up @@ -1241,10 +1268,7 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() {
} else {
++num_applied;
}
} catch ( const guard_exception& e ) {
chain_plug->handle_guard_exception(e);
return start_block_result::failed;
} FC_LOG_AND_DROP();
} LOG_AND_DROP();
}

itr = itr_next;
Expand Down Expand Up @@ -1355,10 +1379,7 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() {
} else {
num_applied++;
}
} catch ( const guard_exception& e ) {
chain_plug->handle_guard_exception(e);
return start_block_result::failed;
} FC_LOG_AND_DROP();
} LOG_AND_DROP();

_incoming_trx_weight += _incoming_defer_ratio;
if (!orig_pending_txn_size) _incoming_trx_weight = 0.0;
Expand All @@ -1378,6 +1399,8 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() {

}

if( app().is_quiting() ) // db guard exception above in LOG_AND_DROP could have called app().quit()
return start_block_result::failed;
if (exhausted || preprocess_deadline <= fc::time_point::now()) {
return start_block_result::exhausted;
} else {
Expand All @@ -1397,9 +1420,13 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() {
return start_block_result::succeeded;
}

} catch ( const guard_exception& e ) {
chain_plugin::handle_guard_exception(e);
return start_block_result::failed;
} catch ( std::bad_alloc& ) {
chain_plugin::handle_bad_alloc();
} catch ( boost::interprocess::bad_alloc& ) {
chain_plugin::handle_db_exhaustion();
return start_block_result::failed;
}

}
Expand Down Expand Up @@ -1522,17 +1549,9 @@ bool producer_plugin_impl::maybe_produce_block() {
});

try {
try {
produce_block();
return true;
} catch ( const guard_exception& e ) {
chain_plug->handle_guard_exception(e);
return false;
} FC_LOG_AND_DROP();
} catch ( boost::interprocess::bad_alloc&) {
raise(SIGUSR1);
return false;
}
produce_block();
return true;
} LOG_AND_DROP();

fc_dlog(_log, "Aborting block due to produce_block error");
chain::controller& chain = chain_plug->chain();
Expand Down