diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index bbb9f8cb8..a16446019 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -4405,6 +4405,10 @@ impl BeaconChain { } /// Called by the timer on every slot. + /// + /// Note: this function **MUST** be called from a non-async context since + /// it contains a call to `fork_choice` which may eventually call + /// `tokio::runtime::block_on` in certain cases. pub fn per_slot_task(self: &Arc) { trace!(self.log, "Running beacon chain per slot tasks"); if let Some(slot) = self.slot_clock.now() { diff --git a/beacon_node/timer/src/lib.rs b/beacon_node/timer/src/lib.rs index d0f449bab..9c6bf1ca8 100644 --- a/beacon_node/timer/src/lib.rs +++ b/beacon_node/timer/src/lib.rs @@ -3,7 +3,7 @@ //! This service allows task execution on the beacon node for various functionality. use beacon_chain::{BeaconChain, BeaconChainTypes}; -use slog::info; +use slog::{debug, info, warn}; use slot_clock::SlotClock; use std::sync::Arc; use std::time::Duration; @@ -24,10 +24,30 @@ pub fn spawn_timer( // Warning: `interval_at` panics if `seconds_per_slot` = 0. let mut interval = interval_at(start_instant, Duration::from_secs(seconds_per_slot)); + let per_slot_executor = executor.clone(); let timer_future = async move { + let log = per_slot_executor.log().clone(); loop { interval.tick().await; - beacon_chain.per_slot_task(); + let chain = beacon_chain.clone(); + if let Some(handle) = per_slot_executor + .spawn_blocking_handle(move || chain.per_slot_task(), "timer_per_slot_task") + { + if let Err(e) = handle.await { + warn!( + log, + "Per slot task failed"; + "info" => ?e + ); + } + } else { + debug!( + log, + "Per slot task timer stopped"; + "info" => "shutting down" + ); + break; + } } };