From 444c7a961e8670eccd2555408e91ee86abed3da7 Mon Sep 17 00:00:00 2001 From: Federico Gimenez Date: Mon, 5 Aug 2024 16:12:36 +0200 Subject: [PATCH] fix: deadlock on StaticFileProvider::get_writer (#10069) Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com> --- crates/engine/tree/src/persistence.rs | 7 ++++++- crates/storage/provider/src/writer/mod.rs | 25 ++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/crates/engine/tree/src/persistence.rs b/crates/engine/tree/src/persistence.rs index 54410c096f..bfb04bce06 100644 --- a/crates/engine/tree/src/persistence.rs +++ b/crates/engine/tree/src/persistence.rs @@ -290,7 +290,12 @@ mod tests { persistence_handle.save_blocks(blocks, tx).unwrap(); - let actual_hash = rx.await.unwrap().unwrap(); + let actual_hash = tokio::time::timeout(std::time::Duration::from_secs(10), rx) + .await + .expect("test timed out") + .expect("channel closed unexpectedly") + .expect("no hash returned"); + assert_eq!(block_hash, actual_hash); } diff --git a/crates/storage/provider/src/writer/mod.rs b/crates/storage/provider/src/writer/mod.rs index 39dc3cf4eb..eb4c610e5f 100644 --- a/crates/storage/provider/src/writer/mod.rs +++ b/crates/storage/provider/src/writer/mod.rs @@ -155,16 +155,6 @@ where let first_number = first_block.number; let last_block_number = last_block.number; - // Only write receipts to static files if there is no receipt pruning configured. - let mut state_writer = if self.database().prune_modes_ref().has_receipts_pruning() { - UnifiedStorageWriter::from_database(self.database()) - } else { - UnifiedStorageWriter::from( - self.database(), - self.static_file().get_writer(first_block.number, StaticFileSegment::Receipts)?, - ) - }; - debug!(target: "provider::storage_writer", block_count = %blocks.len(), "Writing blocks and execution data to storage"); // TODO: remove all the clones and do performant / batched writes for each type of object @@ -185,6 +175,21 @@ where // Write state and changesets to the database. // Must be written after blocks because of the receipt lookup. let execution_outcome = block.execution_outcome().clone(); + + // Only write receipts to static files if there is no receipt pruning configured. + let mut state_writer = if self.database().prune_modes_ref().has_receipts_pruning() { + UnifiedStorageWriter::from_database(self.database()) + } else { + // This should be inside the hotloop, because preferably there should only be one + // mutable reference to a static file writer, since there's a 3 in 100 chance that + // another segment shares the same shard as the `Receipts` one. Which would result + // in a deadlock. + UnifiedStorageWriter::from( + self.database(), + self.static_file() + .get_writer(first_block.number, StaticFileSegment::Receipts)?, + ) + }; state_writer.write_to_storage(execution_outcome, OriginalValuesKnown::No)?; // insert hashes and intermediate merkle nodes