Skip to content

Commit

Permalink
GH-570 Avoid tight loop by returning paused
Browse files Browse the repository at this point in the history
  • Loading branch information
heifner committed Dec 4, 2024
1 parent 7c6e5dc commit a7b65cc
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 25 deletions.
48 changes: 25 additions & 23 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1358,9 +1358,9 @@ struct controller_impl {

// When in IRREVERSIBLE mode fork_db blocks are applied and marked valid when they become irreversible
template<typename ForkDB, typename BSP>
bool apply_irreversible_block(ForkDB& fork_db, const BSP& bsp) {
controller::apply_blocks_result apply_irreversible_block(ForkDB& fork_db, const BSP& bsp) {
if (read_mode != db_read_mode::IRREVERSIBLE)
return true; // ignore
return controller::apply_blocks_result::complete; // ignore
if constexpr (std::is_same_v<block_state_legacy_ptr, std::decay_t<decltype(bsp)>>) {
// before transition to savanna
return apply_block(bsp, controller::block_status::complete, trx_meta_cache_lookup{});
Expand All @@ -1376,22 +1376,23 @@ struct controller_impl {
return apply_block(bsp, controller::block_status::complete, trx_meta_cache_lookup{});
}
// only called during transition when not a proper savanna block
return fork_db_.apply_l<bool>([&](const auto& fork_db_l) {
return fork_db_.apply_l<controller::apply_blocks_result>([&](const auto& fork_db_l) {
block_state_legacy_ptr legacy = fork_db_l.get_block(bsp->id());
fork_db_.switch_to(fork_database::in_use_t::legacy); // apply block uses to know what types to create
block_state_ptr prev = fork_db.get_block(legacy->previous(), include_root_t::yes);
assert(prev);
if( apply_block(legacy, controller::block_status::complete, trx_meta_cache_lookup{}) ) {
controller::apply_blocks_result r = apply_block(legacy, controller::block_status::complete, trx_meta_cache_lookup{});
if( r == controller::apply_blocks_result::complete) {
fc::scoped_exit<std::function<void()>> e([&]{fork_db_.switch_to(fork_database::in_use_t::both);});
// irreversible apply was just done, calculate new_valid here instead of in transition_to_savanna()
assert(legacy->action_mroot_savanna);
transition_add_to_savanna_fork_db(fork_db, legacy, bsp, prev);
return true;
return r;
}
// add to fork_db as it expects root != head
transition_add_to_savanna_fork_db(fork_db, legacy, bsp, prev);
fork_db_.switch_to(fork_database::in_use_t::legacy);
return false;
return r;
});
}
}
Expand Down Expand Up @@ -1574,7 +1575,7 @@ struct controller_impl {
auto it = v.begin();

for( auto bitr = branch.rbegin(); bitr != branch.rend() && should_process(*bitr); ++bitr ) {
if (!apply_irreversible_block(fork_db, *bitr))
if (apply_irreversible_block(fork_db, *bitr) != controller::apply_blocks_result::complete)
break;

emit( irreversible_block, std::tie((*bitr)->block, (*bitr)->id()), __FILE__, __LINE__ );
Expand Down Expand Up @@ -3697,16 +3698,16 @@ struct controller_impl {
}

template<class BSP>
bool apply_block( const BSP& bsp, controller::block_status s,
const trx_meta_cache_lookup& trx_lookup ) {
controller::apply_blocks_result apply_block( const BSP& bsp, controller::block_status s,
const trx_meta_cache_lookup& trx_lookup ) {
try {
try {
if (should_terminate()) {
shutdown();
return false;
return controller::apply_blocks_result::incomplete;
}
if (should_pause()) {
return false;
return controller::apply_blocks_result::paused;
}

auto start = fc::time_point::now(); // want to report total time of applying a block
Expand Down Expand Up @@ -3864,7 +3865,7 @@ struct controller_impl {

commit_block(s);

return true;
return controller::apply_blocks_result::complete;
} catch ( const std::bad_alloc& ) {
throw;
} catch ( const boost::interprocess::bad_alloc& ) {
Expand Down Expand Up @@ -4336,7 +4337,7 @@ struct controller_impl {

BSP bsp = std::make_shared<typename BSP::element_type>(*head, b, protocol_features.get_protocol_feature_set(), validator, skip_validate_signee);

if (apply_block(bsp, controller::block_status::irreversible, trx_meta_cache_lookup{})) {
if (apply_block(bsp, controller::block_status::irreversible, trx_meta_cache_lookup{}) == controller::apply_blocks_result::complete) {
// On replay, log_irreversible is not called and so no irreversible_block signal is emitted.
// So emit it explicitly here.
emit( irreversible_block, std::tie(bsp->block, bsp->id()), __FILE__, __LINE__ );
Expand Down Expand Up @@ -4422,23 +4423,24 @@ struct controller_impl {
auto except = std::exception_ptr{};
const auto& bsp = *ritr;
try {
bool applied = apply_block( bsp, bsp->is_valid() ? controller::block_status::validated
: controller::block_status::complete, trx_lookup );
result = apply_block( bsp, bsp->is_valid() ? controller::block_status::validated
: controller::block_status::complete, trx_lookup );
if (!switch_fork) {
if (check_shutdown()) {
shutdown();
break; // result should be complete since we are shutting down
}
// Break every ~500ms to allow other tasks (e.g. get_info, SHiP) opportunity to run. User expected
// to call apply_blocks again if this returns incomplete.
const bool more_blocks_to_process = ritr + 1 != new_head_branch.rend();
if (!replaying && more_blocks_to_process && fc::time_point::now() - start_apply_blocks_loop > fc::milliseconds(500)) {
result = controller::apply_blocks_result::incomplete;
break;
if (result == controller::apply_blocks_result::complete) {
// Break every ~500ms to allow other tasks (e.g. get_info, SHiP) opportunity to run. User expected
// to call apply_blocks again if this returns incomplete.
const bool more_blocks_to_process = ritr + 1 != new_head_branch.rend();
if (!replaying && more_blocks_to_process && fc::time_point::now() - start_apply_blocks_loop > fc::milliseconds(500)) {
result = controller::apply_blocks_result::incomplete;
break;
}
}
}
if (!applied) {
result = controller::apply_blocks_result::incomplete;
if (result != controller::apply_blocks_result::complete) {
break;
}
} catch ( const std::bad_alloc& ) {
Expand Down
5 changes: 3 additions & 2 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,9 @@ namespace eosio::chain {

/// Apply any blocks that are ready from the fork_db
enum class apply_blocks_result {
complete, // all ready blocks in forkdb have been applied
incomplete // time limit reached, additional blocks may be available in forkdb to process
complete, // all ready blocks in forkdb have been applied
incomplete, // time limit reached, additional blocks may be available in forkdb to process
paused // apply blocks currently paused
};
apply_blocks_result apply_blocks(const forked_callback_t& cb, const trx_meta_cache_lookup& trx_lookup);

Expand Down

0 comments on commit a7b65cc

Please sign in to comment.