@@ -128,8 +128,8 @@ pub use builder::NodeBuilder as Builder;
128
128
use chain:: ChainSource ;
129
129
use config:: {
130
130
default_user_config, may_announce_channel, ChannelConfig , Config ,
131
- LDK_EVENT_HANDLER_SHUTDOWN_TIMEOUT_SECS , NODE_ANN_BCAST_INTERVAL , PEER_RECONNECTION_INTERVAL ,
132
- RGS_SYNC_INTERVAL ,
131
+ BACKGROUND_TASK_SHUTDOWN_TIMEOUT_SECS , LDK_EVENT_HANDLER_SHUTDOWN_TIMEOUT_SECS ,
132
+ NODE_ANN_BCAST_INTERVAL , PEER_RECONNECTION_INTERVAL , RGS_SYNC_INTERVAL ,
133
133
} ;
134
134
use connection:: ConnectionManager ;
135
135
use event:: { EventHandler , EventQueue } ;
@@ -180,6 +180,7 @@ pub struct Node {
180
180
runtime : Arc < RwLock < Option < Arc < tokio:: runtime:: Runtime > > > > ,
181
181
stop_sender : tokio:: sync:: watch:: Sender < ( ) > ,
182
182
background_processor_task : Mutex < Option < tokio:: task:: JoinHandle < ( ) > > > ,
183
+ background_tasks : Mutex < Option < tokio:: task:: JoinSet < ( ) > > > ,
183
184
config : Arc < Config > ,
184
185
wallet : Arc < Wallet > ,
185
186
chain_source : Arc < ChainSource > ,
@@ -233,6 +234,9 @@ impl Node {
233
234
return Err ( Error :: AlreadyRunning ) ;
234
235
}
235
236
237
+ let mut background_tasks = tokio:: task:: JoinSet :: new ( ) ;
238
+ let runtime_handle = runtime. handle ( ) ;
239
+
236
240
log_info ! (
237
241
self . logger,
238
242
"Starting up LDK Node with node ID {} on network: {}" ,
@@ -259,19 +263,27 @@ impl Node {
259
263
let sync_cman = Arc :: clone ( & self . channel_manager ) ;
260
264
let sync_cmon = Arc :: clone ( & self . chain_monitor ) ;
261
265
let sync_sweeper = Arc :: clone ( & self . output_sweeper ) ;
262
- runtime. spawn ( async move {
263
- chain_source
264
- . continuously_sync_wallets ( stop_sync_receiver, sync_cman, sync_cmon, sync_sweeper)
265
- . await ;
266
- } ) ;
266
+ background_tasks. spawn_on (
267
+ async move {
268
+ chain_source
269
+ . continuously_sync_wallets (
270
+ stop_sync_receiver,
271
+ sync_cman,
272
+ sync_cmon,
273
+ sync_sweeper,
274
+ )
275
+ . await ;
276
+ } ,
277
+ runtime_handle,
278
+ ) ;
267
279
268
280
if self . gossip_source . is_rgs ( ) {
269
281
let gossip_source = Arc :: clone ( & self . gossip_source ) ;
270
282
let gossip_sync_store = Arc :: clone ( & self . kv_store ) ;
271
283
let gossip_sync_logger = Arc :: clone ( & self . logger ) ;
272
284
let gossip_node_metrics = Arc :: clone ( & self . node_metrics ) ;
273
285
let mut stop_gossip_sync = self . stop_sender . subscribe ( ) ;
274
- runtime . spawn ( async move {
286
+ background_tasks . spawn_on ( async move {
275
287
let mut interval = tokio:: time:: interval ( RGS_SYNC_INTERVAL ) ;
276
288
loop {
277
289
tokio:: select! {
@@ -312,7 +324,7 @@ impl Node {
312
324
}
313
325
}
314
326
}
315
- } ) ;
327
+ } , runtime_handle ) ;
316
328
}
317
329
318
330
if let Some ( listening_addresses) = & self . config . listening_addresses {
@@ -338,7 +350,7 @@ impl Node {
338
350
bind_addrs. extend ( resolved_address) ;
339
351
}
340
352
341
- runtime . spawn ( async move {
353
+ background_tasks . spawn_on ( async move {
342
354
{
343
355
let listener =
344
356
tokio:: net:: TcpListener :: bind ( & * bind_addrs) . await
@@ -357,7 +369,7 @@ impl Node {
357
369
_ = stop_listen. changed( ) => {
358
370
log_debug!(
359
371
listening_logger,
360
- "Stopping listening to inbound connections." ,
372
+ "Stopping listening to inbound connections."
361
373
) ;
362
374
break ;
363
375
}
@@ -376,7 +388,7 @@ impl Node {
376
388
}
377
389
378
390
listening_indicator. store ( false , Ordering :: Release ) ;
379
- } ) ;
391
+ } , runtime_handle ) ;
380
392
}
381
393
382
394
// Regularly reconnect to persisted peers.
@@ -385,15 +397,15 @@ impl Node {
385
397
let connect_logger = Arc :: clone ( & self . logger ) ;
386
398
let connect_peer_store = Arc :: clone ( & self . peer_store ) ;
387
399
let mut stop_connect = self . stop_sender . subscribe ( ) ;
388
- runtime . spawn ( async move {
400
+ background_tasks . spawn_on ( async move {
389
401
let mut interval = tokio:: time:: interval ( PEER_RECONNECTION_INTERVAL ) ;
390
402
interval. set_missed_tick_behavior ( tokio:: time:: MissedTickBehavior :: Skip ) ;
391
403
loop {
392
404
tokio:: select! {
393
405
_ = stop_connect. changed( ) => {
394
406
log_debug!(
395
407
connect_logger,
396
- "Stopping reconnecting known peers." ,
408
+ "Stopping reconnecting known peers."
397
409
) ;
398
410
return ;
399
411
}
@@ -413,7 +425,7 @@ impl Node {
413
425
}
414
426
}
415
427
}
416
- } ) ;
428
+ } , runtime_handle ) ;
417
429
418
430
// Regularly broadcast node announcements.
419
431
let bcast_cm = Arc :: clone ( & self . channel_manager ) ;
@@ -425,7 +437,7 @@ impl Node {
425
437
let mut stop_bcast = self . stop_sender . subscribe ( ) ;
426
438
let node_alias = self . config . node_alias . clone ( ) ;
427
439
if may_announce_channel ( & self . config ) . is_ok ( ) {
428
- runtime . spawn ( async move {
440
+ background_tasks . spawn_on ( async move {
429
441
// We check every 30 secs whether our last broadcast is NODE_ANN_BCAST_INTERVAL away.
430
442
#[ cfg( not( test) ) ]
431
443
let mut interval = tokio:: time:: interval ( Duration :: from_secs ( 30 ) ) ;
@@ -496,7 +508,7 @@ impl Node {
496
508
}
497
509
}
498
510
}
499
- } ) ;
511
+ } , runtime_handle ) ;
500
512
}
501
513
502
514
let mut stop_tx_bcast = self . stop_sender . subscribe ( ) ;
@@ -605,24 +617,30 @@ impl Node {
605
617
let mut stop_liquidity_handler = self . stop_sender . subscribe ( ) ;
606
618
let liquidity_handler = Arc :: clone ( & liquidity_source) ;
607
619
let liquidity_logger = Arc :: clone ( & self . logger ) ;
608
- runtime. spawn ( async move {
609
- loop {
610
- tokio:: select! {
611
- _ = stop_liquidity_handler. changed( ) => {
612
- log_debug!(
613
- liquidity_logger,
614
- "Stopping processing liquidity events." ,
615
- ) ;
616
- return ;
620
+ background_tasks. spawn_on (
621
+ async move {
622
+ loop {
623
+ tokio:: select! {
624
+ _ = stop_liquidity_handler. changed( ) => {
625
+ log_debug!(
626
+ liquidity_logger,
627
+ "Stopping processing liquidity events." ,
628
+ ) ;
629
+ return ;
630
+ }
631
+ _ = liquidity_handler. handle_next_event( ) => { }
617
632
}
618
- _ = liquidity_handler. handle_next_event( ) => { }
619
633
}
620
- }
621
- } ) ;
634
+ } ,
635
+ runtime_handle,
636
+ ) ;
622
637
}
623
638
624
639
* runtime_lock = Some ( runtime) ;
625
640
641
+ debug_assert ! ( self . background_tasks. lock( ) . unwrap( ) . is_none( ) ) ;
642
+ * self . background_tasks . lock ( ) . unwrap ( ) = Some ( background_tasks) ;
643
+
626
644
log_info ! ( self . logger, "Startup complete." ) ;
627
645
Ok ( ( ) )
628
646
}
@@ -661,13 +679,52 @@ impl Node {
661
679
self . chain_source . stop ( ) ;
662
680
log_debug ! ( self . logger, "Stopped chain sources." ) ;
663
681
682
+ // Wait until all background tasks (mod LDK's background processor) are done.
683
+ let runtime_handle = runtime. handle ( ) ;
684
+ if let Some ( mut tasks) = self . background_tasks . lock ( ) . unwrap ( ) . take ( ) {
685
+ tokio:: task:: block_in_place ( move || {
686
+ runtime_handle. block_on ( async {
687
+ loop {
688
+ let timeout_fut = tokio:: time:: timeout (
689
+ Duration :: from_secs ( BACKGROUND_TASK_SHUTDOWN_TIMEOUT_SECS ) ,
690
+ tasks. join_next_with_id ( ) ,
691
+ ) ;
692
+ match timeout_fut. await {
693
+ Ok ( Some ( Ok ( ( id, _) ) ) ) => {
694
+ log_trace ! ( self . logger, "Stopped background task with id {}" , id) ;
695
+ } ,
696
+ Ok ( Some ( Err ( e) ) ) => {
697
+ tasks. abort_all ( ) ;
698
+ log_trace ! ( self . logger, "Stopping background task failed: {}" , e) ;
699
+ break ;
700
+ } ,
701
+ Ok ( None ) => {
702
+ log_debug ! ( self . logger, "Stopped all background tasks" ) ;
703
+ break ;
704
+ } ,
705
+ Err ( e) => {
706
+ tasks. abort_all ( ) ;
707
+ log_error ! (
708
+ self . logger,
709
+ "Stopping background task timed out: {}" ,
710
+ e
711
+ ) ;
712
+ break ;
713
+ } ,
714
+ }
715
+ }
716
+ } )
717
+ } ) ;
718
+ }
719
+
664
720
// Wait until background processing stopped, at least until a timeout is reached.
665
721
if let Some ( background_processor_task) =
666
722
self . background_processor_task . lock ( ) . unwrap ( ) . take ( )
667
723
{
724
+ let runtime_handle = runtime. handle ( ) ;
668
725
let abort_handle = background_processor_task. abort_handle ( ) ;
669
726
let timeout_res = tokio:: task:: block_in_place ( move || {
670
- runtime . block_on ( async {
727
+ runtime_handle . block_on ( async {
671
728
tokio:: time:: timeout (
672
729
Duration :: from_secs ( LDK_EVENT_HANDLER_SHUTDOWN_TIMEOUT_SECS ) ,
673
730
background_processor_task,
0 commit comments