diff --git a/zebra-network/src/meta_addr/peer_addr.rs b/zebra-network/src/meta_addr/peer_addr.rs index e7aa6859318..92a27defcca 100644 --- a/zebra-network/src/meta_addr/peer_addr.rs +++ b/zebra-network/src/meta_addr/peer_addr.rs @@ -3,7 +3,7 @@ use std::{ fmt, - net::SocketAddr, + net::{Ipv4Addr, SocketAddr}, ops::{Deref, DerefMut}, str::FromStr, }; @@ -66,6 +66,11 @@ impl DerefMut for PeerSocketAddr { } impl PeerSocketAddr { + /// Returns an unspecified `PeerSocketAddr`, which can't be used for outbound connections. + pub fn unspecified() -> Self { + Self(SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0)) + } + /// Return the underlying [`SocketAddr`], which allows sensitive peer address information to /// be printed and logged. pub fn remove_socket_addr_privacy(&self) -> SocketAddr { diff --git a/zebra-network/src/peer_set/initialize.rs b/zebra-network/src/peer_set/initialize.rs index cdd4807e61b..8b91320fef8 100644 --- a/zebra-network/src/peer_set/initialize.rs +++ b/zebra-network/src/peer_set/initialize.rs @@ -213,7 +213,17 @@ where // Wait for the initial seed peer count let mut active_outbound_connections = initial_peers_join .await - .expect("unexpected panic in spawned initial peers task") + .unwrap_or_else(|e @ JoinError { .. }| { + if e.is_panic() { + panic!("panic in initial peer connections task: {e:?}"); + } else { + info!( + "task error during initial peer connections: {e:?},\ + is Zebra shutting down?" + ); + Err(e.into()) + } + }) .expect("unexpected error connecting to initial peers"); let active_initial_peer_count = active_outbound_connections.update_count(); @@ -353,8 +363,18 @@ where .collect(); while let Some(handshake_result) = handshakes.next().await { - let handshake_result = - handshake_result.expect("unexpected panic in initial peer handshake"); + let handshake_result = handshake_result.unwrap_or_else(|e @ JoinError { .. }| { + if e.is_panic() { + panic!("panic in initial peer connection: {e:?}"); + } else { + info!( + "task error during initial peer connection: {e:?},\ + is Zebra shutting down?" + ); + // Fake the address, it doesn't matter because we're shutting down anyway + Err((PeerSocketAddr::unspecified(), e.into())) + } + }); match handshake_result { Ok(change) => { handshake_success_total += 1; diff --git a/zebrad/src/components/sync.rs b/zebrad/src/components/sync.rs index 2e984b3af25..89ee01fb34b 100644 --- a/zebrad/src/components/sync.rs +++ b/zebrad/src/components/sync.rs @@ -8,7 +8,7 @@ use color_eyre::eyre::{eyre, Report}; use futures::stream::{FuturesUnordered, StreamExt}; use indexmap::IndexSet; use serde::{Deserialize, Serialize}; -use tokio::{sync::watch, time::sleep}; +use tokio::{sync::watch, task::JoinError, time::sleep}; use tower::{ builder::ServiceBuilder, hedge::Hedge, limit::ConcurrencyLimit, retry::Retry, timeout::Timeout, Service, ServiceExt, @@ -668,7 +668,17 @@ where let mut download_set = IndexSet::new(); while let Some(res) = requests.next().await { match res - .expect("panic in spawned obtain tips request") + .unwrap_or_else(|e @ JoinError { .. }| { + if e.is_panic() { + panic!("panic in obtain tips task: {e:?}"); + } else { + info!( + "task error during obtain tips task: {e:?},\ + is Zebra shutting down?" + ); + Err(e.into()) + } + }) .map_err::(|e| eyre!(e)) { Ok(zn::Response::BlockHashes(hashes)) => {