From 3c1e510922d8a7c69b84a40c3f49e43aef5591ec Mon Sep 17 00:00:00 2001 From: Huang-Ming Huang Date: Mon, 3 May 2021 14:55:32 -0500 Subject: [PATCH 1/3] exit on write failure --- .../state_history_log.hpp | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp index 3bf19eb012a..f58603a398c 100644 --- a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp +++ b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp @@ -87,39 +87,45 @@ class state_history_log { template void write_entry(const state_history_log_header& header, const chain::block_id_type& prev_id, F write_payload) { - auto block_num = chain::block_header::num_from_id(header.block_id); - EOS_ASSERT(_begin_block == _end_block || block_num <= _end_block, chain::plugin_exception, - "missed a block in ${name}.log", ("name", name)); + try { + auto block_num = chain::block_header::num_from_id(header.block_id); + EOS_ASSERT(_begin_block == _end_block || block_num <= _end_block, chain::plugin_exception, + "missed a block in ${name}.log", ("name", name)); - if (_begin_block != _end_block && block_num > _begin_block) { - if (block_num == _end_block) { - EOS_ASSERT(prev_id == last_block_id, chain::plugin_exception, "missed a fork change in ${name}.log", - ("name", name)); - } else { - state_history_log_header prev; - get_entry(block_num - 1, prev); - EOS_ASSERT(prev_id == prev.block_id, chain::plugin_exception, "missed a fork change in ${name}.log", - ("name", name)); + if (_begin_block != _end_block && block_num > _begin_block) { + if (block_num == _end_block) { + EOS_ASSERT(prev_id == last_block_id, chain::plugin_exception, "missed a fork change in ${name}.log", + ("name", name)); + } else { + state_history_log_header prev; + get_entry(block_num - 1, prev); + EOS_ASSERT(prev_id == prev.block_id, chain::plugin_exception, "missed a fork change in ${name}.log", + ("name", name)); + } } - } - if (block_num < _end_block) - truncate(block_num); - log.seek_end(0); - uint64_t pos = log.tellp(); - write_header(header); - write_payload(log); - uint64_t end = log.tellp(); - EOS_ASSERT(end == pos + state_history_log_header_serial_size + header.payload_size, chain::plugin_exception, - "wrote payload with incorrect size to ${name}.log", ("name", name)); - log.write((char*)&pos, sizeof(pos)); + if (block_num < _end_block) + truncate(block_num); + log.seek_end(0); + uint64_t pos = log.tellp(); + write_header(header); + write_payload(log); + uint64_t end = log.tellp(); + EOS_ASSERT(end == pos + state_history_log_header_serial_size + header.payload_size, chain::plugin_exception, + "wrote payload with incorrect size to ${name}.log", ("name", name)); + log.write((char*)&pos, sizeof(pos)); - index.seek_end(0); - index.write((char*)&pos, sizeof(pos)); - if (_begin_block == _end_block) - _begin_block = block_num; - _end_block = block_num + 1; - last_block_id = header.block_id; + index.seek_end(0); + index.write((char*)&pos, sizeof(pos)); + if (_begin_block == _end_block) + _begin_block = block_num; + _end_block = block_num + 1; + last_block_id = header.block_id; + } + catch(const chain::plugin_exception& e) { + wlog( "chain::plugin_exception: ${details}", ("details", e.to_detail_string()) ); + EOS_THROW(chain::controller_emit_signal_exception, "State history encountered an Error which it cannot recover from. Please resolve the error and relaunch the process") + } } // returns cfile positioned at payload From aa20b4c3a31dc4d0b1fd13c76315217032beb35c Mon Sep 17 00:00:00 2001 From: Huang-Ming Huang Date: Tue, 4 May 2021 10:17:12 -0500 Subject: [PATCH 2/3] Just call app().quit() --- .../eosio/state_history_plugin/state_history_log.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp index f58603a398c..7942630aa44 100644 --- a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp +++ b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp @@ -9,7 +9,7 @@ #include #include #include - +#include namespace eosio { /* @@ -123,8 +123,10 @@ class state_history_log { last_block_id = header.block_id; } catch(const chain::plugin_exception& e) { - wlog( "chain::plugin_exception: ${details}", ("details", e.to_detail_string()) ); - EOS_THROW(chain::controller_emit_signal_exception, "State history encountered an Error which it cannot recover from. Please resolve the error and relaunch the process") + elog( "chain::plugin_exception: ${details}", ("details", e.to_detail_string()) ); + elog("State history encountered an Error which it cannot recover from. Please resolve the error and relaunch " + "the process"); + appbase::app().quit(); } } From b2a83f8b98a758228564a439c9f5cdd05afee082 Mon Sep 17 00:00:00 2001 From: Huang-Ming Huang Date: Wed, 5 May 2021 09:04:19 -0500 Subject: [PATCH 3/3] throw exception and provide rationale --- libraries/chain/include/eosio/chain/exceptions.hpp | 2 ++ .../eosio/state_history_plugin/state_history_log.hpp | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/chain/include/eosio/chain/exceptions.hpp b/libraries/chain/include/eosio/chain/exceptions.hpp index 528fa437c18..c19cc97858e 100644 --- a/libraries/chain/include/eosio/chain/exceptions.hpp +++ b/libraries/chain/include/eosio/chain/exceptions.hpp @@ -480,6 +480,8 @@ namespace eosio { namespace chain { 3140000, "Exceptions that are allowed to bubble out of emit calls in controller" ) FC_DECLARE_DERIVED_EXCEPTION( checkpoint_exception, controller_emit_signal_exception, 3140001, "Block does not match checkpoint" ) + FC_DECLARE_DERIVED_EXCEPTION( state_history_write_exception, controller_emit_signal_exception, + 3140002, "State history write error" ) FC_DECLARE_DERIVED_EXCEPTION( abi_exception, chain_exception, diff --git a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp index 7942630aa44..0848ad9037e 100644 --- a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp +++ b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_log.hpp @@ -124,9 +124,14 @@ class state_history_log { } catch(const chain::plugin_exception& e) { elog( "chain::plugin_exception: ${details}", ("details", e.to_detail_string()) ); - elog("State history encountered an Error which it cannot recover from. Please resolve the error and relaunch " - "the process"); + // Both app().quit() and exception throwing are required. Without app().quit(), + // the exception would be caught and drop before reaching main(). The exception is + // to ensure the block won't be commited. appbase::app().quit(); + EOS_THROW( + chain::state_history_write_exception, + "State history encountered an Error which it cannot recover from. Please resolve the error and relaunch " + "the process"); } }