Skip to content

Commit

Permalink
Merge pull request #1719 from AntelopeIO/GH-1716-GH-1490-main-fixes-4.0
Browse files Browse the repository at this point in the history
[4.0] Fix possible segfault switching between read/write windows
  • Loading branch information
heifner authored Oct 6, 2023
2 parents cdfe867 + adc24ae commit e3f11c4
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 26 deletions.
5 changes: 5 additions & 0 deletions libraries/custom_appbase/include/eosio/chain/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ class two_queue_executor {
else
return read_only_queue_.wrap( priority, --order_, std::forward<Function>( func));
}

void stop() {
read_only_queue_.stop();
read_write_queue_.stop();
}

void clear() {
read_only_queue_.clear();
Expand Down
30 changes: 19 additions & 11 deletions libraries/custom_appbase/include/eosio/chain/exec_pri_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ class exec_pri_queue : public boost::asio::execution_context
{
public:

void stop() {
std::lock_guard g( mtx_ );
exiting_blocking_ = true;
cond_.notify_all();
}

void enable_locking(uint32_t num_threads, std::function<bool()> should_exit) {
assert(num_threads > 0 && num_waiting_ == 0);
lock_enabled_ = true;
Expand Down Expand Up @@ -47,17 +53,6 @@ class exec_pri_queue : public boost::asio::execution_context
handlers_ = prio_queue();
}

// only call when no lock required
bool execute_highest()
{
if( !handlers_.empty() ) {
handlers_.top()->execute();
handlers_.pop();
}

return !handlers_.empty();
}

private:
// has to be defined before use, auto return type
auto pop() {
Expand All @@ -68,6 +63,19 @@ class exec_pri_queue : public boost::asio::execution_context

public:

// only call when no lock required
bool execute_highest()
{
if( !handlers_.empty() ) {
auto t = pop();
bool empty = handlers_.empty();
t->execute();
return !empty;
}

return false;
}

bool execute_highest_locked(bool should_block) {
std::unique_lock g(mtx_);
if (should_block) {
Expand Down
4 changes: 2 additions & 2 deletions libraries/custom_appbase/tests/custom_appbase_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE( default_exec_window ) {
app->executor().post( priority::lowest, exec_queue::read_only, [&]() {
// read_only_queue should only contain the current lambda function,
// and read_write_queue should have executed all its functions
BOOST_REQUIRE_EQUAL( app->executor().read_only_queue().size(), 1); // pop()s after execute
BOOST_REQUIRE_EQUAL( app->executor().read_only_queue().size(), 0); // pop()s before execute
BOOST_REQUIRE_EQUAL( app->executor().read_write_queue().size(), 0 );
app->quit();
} );
Expand Down Expand Up @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE( execute_from_both_queues ) {
// stop application. Use lowest at the end to make sure this executes the last
app->executor().post( priority::lowest, exec_queue::read_only, [&]() {
// read_queue should have current function and write_queue's functions are all executed
BOOST_REQUIRE_EQUAL( app->executor().read_only_queue().size(), 1); // pop()s after execute
BOOST_REQUIRE_EQUAL( app->executor().read_only_queue().size(), 0); // pop()s before execute
BOOST_REQUIRE_EQUAL( app->executor().read_write_queue().size(), 0 );
app->quit();
} );
Expand Down
18 changes: 5 additions & 13 deletions plugins/producer_plugin/producer_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1389,20 +1389,12 @@ void producer_plugin::plugin_startup()
} FC_CAPTURE_AND_RETHROW() }

void producer_plugin::plugin_shutdown() {
try {
my->_timer.cancel();
} catch ( const std::bad_alloc& ) {
chain_plugin::handle_bad_alloc();
} catch ( const boost::interprocess::bad_alloc& ) {
chain_plugin::handle_bad_alloc();
} catch(const fc::exception& e) {
edump((e.to_detail_string()));
} catch(const std::exception& e) {
edump((fc::std_exception_wrapper::from_current_exception(e).to_detail_string()));
}

boost::system::error_code ec;
my->_timer.cancel(ec);
my->_ro_timer.cancel(ec);
app().executor().stop();
my->_ro_thread_pool.stop();
my->_thread_pool.stop();

my->_unapplied_transactions.clear();

app().executor().post( 0, [me = my](){} ); // keep my pointer alive until queue is drained
Expand Down

0 comments on commit e3f11c4

Please sign in to comment.