33use std:: collections:: { HashMap , HashSet } ;
44use std:: net:: SocketAddr ;
55use std:: path:: PathBuf ;
6- use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
6+ use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
77use std:: sync:: Arc ;
88use std:: time:: { Duration , SystemTime } ;
99use tokio:: sync:: { mpsc, Mutex } ;
@@ -14,6 +14,7 @@ use async_trait::async_trait;
1414use dashcore:: network:: constants:: ServiceFlags ;
1515use dashcore:: network:: message:: NetworkMessage ;
1616use dashcore:: Network ;
17+ use tokio_util:: sync:: CancellationToken ;
1718
1819use crate :: client:: config:: MempoolStrategy ;
1920use crate :: client:: ClientConfig ;
@@ -43,8 +44,8 @@ pub struct PeerNetworkManager {
4344 reputation_manager : Arc < PeerReputationManager > ,
4445 /// Network type
4546 network : Network ,
46- /// Shutdown signal
47- shutdown : Arc < AtomicBool > ,
47+ /// Shutdown token
48+ shutdown_token : CancellationToken ,
4849 /// Channel for incoming messages
4950 message_tx : mpsc:: Sender < ( SocketAddr , NetworkMessage ) > ,
5051 message_rx : Arc < Mutex < mpsc:: Receiver < ( SocketAddr , NetworkMessage ) > > > ,
@@ -109,7 +110,7 @@ impl PeerNetworkManager {
109110 peer_store : Arc :: new ( peer_store) ,
110111 reputation_manager,
111112 network : config. network ,
112- shutdown : Arc :: new ( AtomicBool :: new ( false ) ) ,
113+ shutdown_token : CancellationToken :: new ( ) ,
113114 message_tx,
114115 message_rx : Arc :: new ( Mutex :: new ( message_rx) ) ,
115116 tasks : Arc :: new ( Mutex :: new ( JoinSet :: new ( ) ) ) ,
@@ -204,7 +205,7 @@ impl PeerNetworkManager {
204205 let network = self . network ;
205206 let message_tx = self . message_tx . clone ( ) ;
206207 let addrv2_handler = self . addrv2_handler . clone ( ) ;
207- let shutdown = self . shutdown . clone ( ) ;
208+ let shutdown_token = self . shutdown_token . clone ( ) ;
208209 let reputation_manager = self . reputation_manager . clone ( ) ;
209210 let mempool_strategy = self . mempool_strategy ;
210211 let user_agent = self . user_agent . clone ( ) ;
@@ -245,7 +246,7 @@ impl PeerNetworkManager {
245246 pool. clone ( ) ,
246247 message_tx,
247248 addrv2_handler,
248- shutdown ,
249+ shutdown_token ,
249250 reputation_manager. clone ( ) ,
250251 connected_peer_count. clone ( ) ,
251252 )
@@ -287,19 +288,19 @@ impl PeerNetworkManager {
287288 pool : Arc < ConnectionPool > ,
288289 message_tx : mpsc:: Sender < ( SocketAddr , NetworkMessage ) > ,
289290 addrv2_handler : Arc < AddrV2Handler > ,
290- shutdown : Arc < AtomicBool > ,
291+ shutdown_token : CancellationToken ,
291292 reputation_manager : Arc < PeerReputationManager > ,
292293 connected_peer_count : Arc < AtomicUsize > ,
293294 ) {
294295 tokio:: spawn ( async move {
295296 log:: debug!( "Starting peer reader loop for {}" , addr) ;
296297 let mut loop_iteration = 0 ;
297298
298- while !shutdown . load ( Ordering :: Relaxed ) {
299+ loop {
299300 loop_iteration += 1 ;
300301
301302 // Check shutdown signal first with detailed logging
302- if shutdown . load ( Ordering :: Relaxed ) {
303+ if shutdown_token . is_cancelled ( ) {
303304 log:: info!( "Breaking peer reader loop for {} - shutdown signal received (iteration {})" , addr, loop_iteration) ;
304305 break ;
305306 }
@@ -326,7 +327,15 @@ impl PeerNetworkManager {
326327
327328 // Now get write lock only for the duration of the read
328329 let mut conn_guard = conn. write ( ) . await ;
329- conn_guard. receive_message ( ) . await
330+ tokio:: select! {
331+ message = conn_guard. receive_message( ) => {
332+ message
333+ } ,
334+ _ = shutdown_token. cancelled( ) => {
335+ log:: info!( "Breaking peer reader loop for {} - shutdown signal received while reading (iteration {})" , addr, loop_iteration) ;
336+ break ;
337+ }
338+ }
330339 } ;
331340
332341 match msg_result {
@@ -576,7 +585,7 @@ impl PeerNetworkManager {
576585 let pool = self . pool . clone ( ) ;
577586 let discovery = self . discovery . clone ( ) ;
578587 let network = self . network ;
579- let shutdown = self . shutdown . clone ( ) ;
588+ let shutdown_token = self . shutdown_token . clone ( ) ;
580589 let addrv2_handler = self . addrv2_handler . clone ( ) ;
581590 let peer_store = self . peer_store . clone ( ) ;
582591 let reputation_manager = self . reputation_manager . clone ( ) ;
@@ -599,7 +608,7 @@ impl PeerNetworkManager {
599608
600609 let mut tasks = self . tasks . lock ( ) . await ;
601610 tasks. spawn ( async move {
602- while !shutdown . load ( Ordering :: Relaxed ) {
611+ while !shutdown_token . is_cancelled ( ) {
603612 // Clean up disconnected peers
604613 pool. cleanup_disconnected ( ) . await ;
605614
@@ -612,7 +621,13 @@ impl PeerNetworkManager {
612621 for addr in initial_peers. iter ( ) {
613622 if !pool. is_connected ( addr) . await && !pool. is_connecting ( addr) . await {
614623 log:: info!( "Reconnecting to exclusive peer: {}" , addr) ;
615- connect_fn ( * addr) . await ;
624+ tokio:: select! {
625+ _= connect_fn( * addr) => { } ,
626+ _ = shutdown_token. cancelled( ) => {
627+ log:: info!( "Maintenance loop shutting down during connection attempt (exclusive)" ) ;
628+ break ;
629+ }
630+ }
616631 }
617632 }
618633 } else {
@@ -642,7 +657,13 @@ impl PeerNetworkManager {
642657
643658 for addr in best_peers {
644659 if !pool. is_connected ( & addr) . await && !pool. is_connecting ( & addr) . await {
645- connect_fn ( addr) . await ;
660+ tokio:: select! {
661+ _= connect_fn( addr) => { } ,
662+ _ = shutdown_token. cancelled( ) => {
663+ log:: info!( "Maintenance loop shutting down during connection attempt (min peers)" ) ;
664+ break ;
665+ }
666+ }
646667 attempted += 1 ;
647668 if attempted >= needed {
648669 break ;
@@ -661,11 +682,23 @@ impl PeerNetworkManager {
661682 } ) ;
662683 if elapsed >= DNS_DISCOVERY_DELAY {
663684 log:: info!( "Using DNS discovery after {}s delay" , elapsed. as_secs( ) ) ;
664- let dns_peers = discovery. discover_peers ( network) . await ;
685+ let dns_peers = tokio:: select! {
686+ peers = discovery. discover_peers( network) => peers,
687+ _ = shutdown_token. cancelled( ) => {
688+ log:: info!( "Maintenance loop shutting down during DNS discovery" ) ;
689+ break ;
690+ }
691+ } ;
665692 let mut dns_attempted = 0 ;
666693 for addr in dns_peers. into_iter ( ) {
667694 if !pool. is_connected ( & addr) . await && !pool. is_connecting ( & addr) . await {
668- connect_fn ( addr) . await ;
695+ tokio:: select! {
696+ _= connect_fn( addr) => { } ,
697+ _ = shutdown_token. cancelled( ) => {
698+ log:: info!( "Maintenance loop shutting down during connection attempt (dns)" ) ;
699+ break ;
700+ }
701+ }
669702 dns_attempted += 1 ;
670703 if dns_attempted >= needed {
671704 break ;
@@ -719,7 +752,15 @@ impl PeerNetworkManager {
719752 }
720753 }
721754
722- time:: sleep ( MAINTENANCE_INTERVAL ) . await ;
755+ tokio:: select! {
756+ _ = time:: sleep( MAINTENANCE_INTERVAL ) => {
757+ log:: debug!( "Maintenance interval elapsed" ) ;
758+ }
759+ _ = shutdown_token. cancelled( ) => {
760+ log:: info!( "Maintenance loop shutting down" ) ;
761+ break ;
762+ }
763+ }
723764 }
724765 } ) ;
725766 }
@@ -942,7 +983,7 @@ impl PeerNetworkManager {
942983 /// Shutdown the network manager
943984 pub async fn shutdown ( & self ) {
944985 log:: info!( "Shutting down peer network manager" ) ;
945- self . shutdown . store ( true , Ordering :: Relaxed ) ;
986+ self . shutdown_token . cancel ( ) ;
946987
947988 // Save known peers before shutdown
948989 let addresses = self . addrv2_handler . get_addresses_for_peer ( MAX_ADDR_TO_STORE ) . await ;
@@ -983,7 +1024,7 @@ impl Clone for PeerNetworkManager {
9831024 peer_store : self . peer_store . clone ( ) ,
9841025 reputation_manager : self . reputation_manager . clone ( ) ,
9851026 network : self . network ,
986- shutdown : self . shutdown . clone ( ) ,
1027+ shutdown_token : self . shutdown_token . clone ( ) ,
9871028 message_tx : self . message_tx . clone ( ) ,
9881029 message_rx : self . message_rx . clone ( ) ,
9891030 tasks : self . tasks . clone ( ) ,
0 commit comments