PR: #32 feat/07-block-listener
File: crates/charon-cli/src/main.rs — run_listen, inside for loop over chains
Problem
tokio::spawn(async move {
if let Err(err) = listener.run().await {
warn!(chain = %name, error = ?err, "listener terminated");
}
});
JoinHandle dropped immediately. If spawned task panics (unwrap inside ChainProvider::connect or alloy internals), tokio catches panic and marks JoinHandle as panicked — but because handle dropped, panic silently discarded. warn! closure never fires on panic, only on Err. Sender for that chain dropped, meaning no further ChainEvents from that chain, but rx.recv() continues returning events from other chains with no indication chain missing.
Impact
Single-chain panic takes that chain's listener permanently offline for lifetime of process with no observable error, no counter increment, no alert. Single-chain deploy (BSC only): bot runs silently with no events.
Fix
Use tokio::task::JoinSet to collect and supervise handles:
let mut set = tokio::task::JoinSet::new();
for (name, chain_cfg) in config.chain {
let tx2 = tx.clone();
set.spawn(async move { ... });
}
drop(tx);
// In select! arm, await set.join_next() and log panics.
Or store handles in Vec<JoinHandle<_>> and poll in drain loop. At minimum, join_all on shutdown should surface panics.
PR: #32 feat/07-block-listener
File: crates/charon-cli/src/main.rs —
run_listen, insideforloop over chainsProblem
JoinHandledropped immediately. If spawned task panics (unwrap insideChainProvider::connector alloy internals), tokio catches panic and marksJoinHandleas panicked — but because handle dropped, panic silently discarded.warn!closure never fires on panic, only onErr. Sender for that chain dropped, meaning no furtherChainEvents from that chain, butrx.recv()continues returning events from other chains with no indication chain missing.Impact
Single-chain panic takes that chain's listener permanently offline for lifetime of process with no observable error, no counter increment, no alert. Single-chain deploy (BSC only): bot runs silently with no events.
Fix
Use
tokio::task::JoinSetto collect and supervise handles:Or store handles in
Vec<JoinHandle<_>>and poll in drain loop. At minimum,join_allon shutdown should surface panics.