From 2d84274840f091aad3d4b9c03bd3f6394bd30ccc Mon Sep 17 00:00:00 2001 From: canepat <16927169+canepat@users.noreply.github.com> Date: Sat, 21 Dec 2024 11:10:16 +0100 Subject: [PATCH] node: fix task caller lifecycle in Triggers schedule (#2605) --- .../node/stagedsync/stages/stage_triggers.cpp | 8 +-- .../node/stagedsync/stages/stage_triggers.hpp | 4 +- .../stagedsync/stages/stage_triggers_test.cpp | 50 +++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 silkworm/node/stagedsync/stages/stage_triggers_test.cpp diff --git a/silkworm/node/stagedsync/stages/stage_triggers.cpp b/silkworm/node/stagedsync/stages/stage_triggers.cpp index a418218464..e9f9877f44 100644 --- a/silkworm/node/stagedsync/stages/stage_triggers.cpp +++ b/silkworm/node/stagedsync/stages/stage_triggers.cpp @@ -40,13 +40,13 @@ Stage::Result TriggersStage::forward(db::RWTxn& tx) { } Task TriggersStage::schedule(std::function callback) { - auto task_caller = [this, c = std::move(callback)]() -> Task { - db::RWTxn* tx = this->current_tx_; + auto task_caller = [](auto* self, auto trigger) -> Task { + db::RWTxn* tx = self->current_tx_; SILKWORM_ASSERT(tx); - c(*tx); + trigger(*tx); co_return; }; - return concurrency::spawn_task(ioc_, task_caller()); + return concurrency::spawn_task(ioc_, task_caller(this, std::move(callback))); } bool TriggersStage::stop() { diff --git a/silkworm/node/stagedsync/stages/stage_triggers.hpp b/silkworm/node/stagedsync/stages/stage_triggers.hpp index b16e0de3b8..9686fccae4 100644 --- a/silkworm/node/stagedsync/stages/stage_triggers.hpp +++ b/silkworm/node/stagedsync/stages/stage_triggers.hpp @@ -37,8 +37,10 @@ class TriggersStage : public Stage, public datastore::StageScheduler { bool stop() override; - private: + protected: boost::asio::io_context ioc_; + + private: db::RWTxn* current_tx_{}; }; diff --git a/silkworm/node/stagedsync/stages/stage_triggers_test.cpp b/silkworm/node/stagedsync/stages/stage_triggers_test.cpp new file mode 100644 index 0000000000..e5fbea1179 --- /dev/null +++ b/silkworm/node/stagedsync/stages/stage_triggers_test.cpp @@ -0,0 +1,50 @@ +/* + Copyright 2024 The Silkworm Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "stage_triggers.hpp" + +#include + +#include +#include +#include + +namespace silkworm::stagedsync { + +using namespace silkworm::db; +using db::test_util::TempChainDataStore; + +class TriggersStateForTest : public TriggersStage { + public: + using TriggersStage::TriggersStage; + boost::asio::io_context& io_context() { return ioc_; } +}; + +TEST_CASE("TriggersStage: scheduled task lifetime") { + TempChainDataStore temp_chaindata; + RWTxn& txn{temp_chaindata.rw_txn()}; + txn.disable_commit(); + + stagedsync::SyncContext sync_context{}; + TriggersStateForTest stage_triggers{&sync_context}; + auto future = concurrency::spawn_future(stage_triggers.io_context(), stage_triggers.schedule([](auto& rw_txn) { + rw_txn.is_open(); + })); + REQUIRE(stage_triggers.forward(txn) == stagedsync::Stage::Result::kSuccess); + CHECK_NOTHROW(future.get()); +} + +} // namespace silkworm::stagedsync