Skip to content

zaino-state: Race conditions in NodeBackedChainIndex::{status, shutdown} #498

@str4d

Description

@str4d

/// Shut down the sync process, for a cleaner drop
/// an error indicates a failure to cleanly shutdown. Dropping the
/// chain index should still stop everything
pub async fn shutdown(&self) -> Result<(), FinalisedStateError> {
self.finalized_db.shutdown().await?;
self.mempool.close();
self.status.store(StatusType::Closing as usize);
Ok(())
}
/// Displays the status of the chain_index
pub fn status(&self) -> StatusType {
let finalized_status = self.finalized_db.status();
let mempool_status = self.mempool.status();
let combined_status = StatusType::from(self.status.load())
.combine(finalized_status)
.combine(mempool_status);
self.status.store(combined_status as usize);
combined_status
}

I noticed a couple of issues here (there may be more):

  • NodeBackedChainIndex::shutdown calls its inner shutdown methods, and only sets self.status to StatusType::Closing once they all return. This means that there is a window of time where a subscriber can check NodeBackedChainIndex::status and see the indexer is running, then try to perform some action while self.finalized_db is actually in a partially or fully shut down state.
    • There happens to be no race with any caller that executes after self.mempool.close() starts, because that method sets its internal status to StatusType::Closing first, and then NodeBackedChainIndex::status will take that as the most important status when combining. But we can't rely on that overall.
  • If the self.status.store(StatusType::Closing) call inside NodeBackedChainIndex::shutdown were moved to the start of the method (to fix the above race condition), this would introduce a race condition between that and NodeBackedChainIndex::status, because the latter also calls self.status.store() and could overwrite the StatusType::Closing status, creating another window in which an external subscriber can observe the status of the indexer to be "running" when it is actually partially shut down.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions