@@ -72,7 +72,7 @@ use core::{cmp, mem};
7272use core:: cell:: RefCell ;
7373use crate :: io:: Read ;
7474use crate :: sync:: { Arc , Mutex , RwLock , RwLockReadGuard , FairRwLock , LockTestExt , LockHeldState } ;
75- use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
75+ use core:: sync:: atomic:: { AtomicUsize , AtomicBool , Ordering } ;
7676use core:: time:: Duration ;
7777use core:: ops:: Deref ;
7878
@@ -926,6 +926,8 @@ where
926926
927927 /// See `ChannelManager` struct-level documentation for lock order requirements.
928928 pending_events : Mutex < Vec < events:: Event > > ,
929+ /// A simple atomic flag to ensure only one task at a time can be processing events asynchronously.
930+ pending_events_processor : AtomicBool ,
929931 /// See `ChannelManager` struct-level documentation for lock order requirements.
930932 pending_background_events : Mutex < Vec < BackgroundEvent > > ,
931933 /// Used when we have to take a BIG lock to make sure everything is self-consistent.
@@ -1741,6 +1743,7 @@ where
17411743 per_peer_state : FairRwLock :: new ( HashMap :: new ( ) ) ,
17421744
17431745 pending_events : Mutex :: new ( Vec :: new ( ) ) ,
1746+ pending_events_processor : AtomicBool :: new ( false ) ,
17441747 pending_background_events : Mutex :: new ( Vec :: new ( ) ) ,
17451748 total_consistency_lock : RwLock :: new ( ( ) ) ,
17461749 persistence_notifier : Notifier :: new ( ) ,
@@ -5282,7 +5285,8 @@ where
52825285
52835286 /// Process pending events from the [`chain::Watch`], returning whether any events were processed.
52845287 fn process_pending_monitor_events ( & self ) -> bool {
5285- debug_assert ! ( self . total_consistency_lock. try_write( ) . is_err( ) ) ; // Caller holds read lock
5288+ debug_assert ! ( self . total_consistency_lock. try_write( ) . is_err( ) ||
5289+ self . pending_events_processor. load( Ordering :: Relaxed ) ) ; // Caller holds read lock or processes events asynchronously.
52865290
52875291 let mut failed_channels = Vec :: new ( ) ;
52885292 let mut pending_monitor_events = self . chain_monitor . release_pending_monitor_events ( ) ;
@@ -5775,9 +5779,9 @@ where
57755779 pub async fn process_pending_events_async < Future : core:: future:: Future , H : Fn ( Event ) -> Future > (
57765780 & self , handler : H
57775781 ) {
5778- // We'll acquire our total consistency lock until the returned future completes so that
5779- // we can be sure no other persists happen while processing events.
5780- let _read_guard = self . total_consistency_lock . read ( ) . unwrap ( ) ;
5782+ if self . pending_events_processor . compare_exchange ( false , true , Ordering :: Acquire , Ordering :: Relaxed ) . is_err ( ) {
5783+ return ;
5784+ }
57815785
57825786 let mut result = NotifyOption :: SkipPersist ;
57835787
@@ -5787,7 +5791,8 @@ where
57875791 result = NotifyOption :: DoPersist ;
57885792 }
57895793
5790- let pending_events = mem:: replace ( & mut * self . pending_events . lock ( ) . unwrap ( ) , vec ! [ ] ) ;
5794+ let pending_events = self . pending_events . lock ( ) . unwrap ( ) . clone ( ) ;
5795+ let num_events = pending_events. len ( ) ;
57915796 if !pending_events. is_empty ( ) {
57925797 result = NotifyOption :: DoPersist ;
57935798 }
@@ -5796,9 +5801,13 @@ where
57965801 handler ( event) . await ;
57975802 }
57985803
5804+ self . pending_events . lock ( ) . unwrap ( ) . drain ( ..num_events) ;
5805+
57995806 if result == NotifyOption :: DoPersist {
58005807 self . persistence_notifier . notify ( ) ;
58015808 }
5809+
5810+ self . pending_events_processor . store ( false , Ordering :: Release ) ;
58025811 }
58035812}
58045813
@@ -7926,6 +7935,7 @@ where
79267935 per_peer_state : FairRwLock :: new ( per_peer_state) ,
79277936
79287937 pending_events : Mutex :: new ( pending_events_read) ,
7938+ pending_events_processor : AtomicBool :: new ( false ) ,
79297939 pending_background_events : Mutex :: new ( pending_background_events) ,
79307940 total_consistency_lock : RwLock :: new ( ( ) ) ,
79317941 persistence_notifier : Notifier :: new ( ) ,
0 commit comments