@@ -72,7 +72,7 @@ use core::{cmp, mem};
72
72
use core:: cell:: RefCell ;
73
73
use crate :: io:: Read ;
74
74
use crate :: sync:: { Arc , Mutex , RwLock , RwLockReadGuard , FairRwLock , LockTestExt , LockHeldState } ;
75
- use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
75
+ use core:: sync:: atomic:: { AtomicUsize , AtomicBool , Ordering } ;
76
76
use core:: time:: Duration ;
77
77
use core:: ops:: Deref ;
78
78
@@ -934,6 +934,8 @@ where
934
934
935
935
/// See `ChannelManager` struct-level documentation for lock order requirements.
936
936
pending_events : Mutex < Vec < events:: Event > > ,
937
+ /// A simple atomic flag to ensure only one task at a time can be processing events asynchronously.
938
+ pending_events_processor : AtomicBool ,
937
939
/// See `ChannelManager` struct-level documentation for lock order requirements.
938
940
pending_background_events : Mutex < Vec < BackgroundEvent > > ,
939
941
/// Used when we have to take a BIG lock to make sure everything is self-consistent.
@@ -1696,30 +1698,47 @@ macro_rules! handle_new_monitor_update {
1696
1698
1697
1699
macro_rules! process_events_body {
1698
1700
( $self: expr, $event_to_handle: expr, $handle_event: expr) => {
1699
- // We'll acquire our total consistency lock until the returned future completes so that
1700
- // we can be sure no other persists happen while processing events.
1701
- let _read_guard = $self. total_consistency_lock. read( ) . unwrap( ) ;
1701
+ let mut processed_all_events = false ;
1702
+ while !processed_all_events {
1703
+ if $self. pending_events_processor. compare_exchange( false , true , Ordering :: Acquire , Ordering :: Relaxed ) . is_err( ) {
1704
+ return ;
1705
+ }
1702
1706
1703
- let mut result = NotifyOption :: SkipPersist ;
1707
+ let mut result = NotifyOption :: SkipPersist ;
1704
1708
1705
- // TODO: This behavior should be documented. It's unintuitive that we query
1706
- // ChannelMonitors when clearing other events.
1707
- if $self. process_pending_monitor_events( ) {
1708
- result = NotifyOption :: DoPersist ;
1709
- }
1709
+ {
1710
+ // We'll acquire our total consistency lock so that we can be sure no other
1711
+ // persists happen while processing monitor events.
1712
+ let _read_guard = $self. total_consistency_lock. read( ) . unwrap( ) ;
1713
+
1714
+ // TODO: This behavior should be documented. It's unintuitive that we query
1715
+ // ChannelMonitors when clearing other events.
1716
+ if $self. process_pending_monitor_events( ) {
1717
+ result = NotifyOption :: DoPersist ;
1718
+ }
1719
+ }
1710
1720
1711
- let pending_events = mem:: replace( & mut * $self. pending_events. lock( ) . unwrap( ) , vec![ ] ) ;
1712
- if !pending_events. is_empty( ) {
1713
- result = NotifyOption :: DoPersist ;
1714
- }
1721
+ let pending_events = $self. pending_events. lock( ) . unwrap( ) . clone( ) ;
1722
+ let num_events = pending_events. len( ) ;
1723
+ if !pending_events. is_empty( ) {
1724
+ result = NotifyOption :: DoPersist ;
1725
+ }
1715
1726
1716
- for event in pending_events {
1717
- $event_to_handle = event;
1718
- $handle_event;
1719
- }
1727
+ for event in pending_events {
1728
+ $event_to_handle = event;
1729
+ $handle_event;
1730
+ }
1720
1731
1721
- if result == NotifyOption :: DoPersist {
1722
- $self. persistence_notifier. notify( ) ;
1732
+ {
1733
+ let mut pending_events = $self. pending_events. lock( ) . unwrap( ) ;
1734
+ pending_events. drain( ..num_events) ;
1735
+ processed_all_events = pending_events. is_empty( ) ;
1736
+ $self. pending_events_processor. store( false , Ordering :: Release ) ;
1737
+ }
1738
+
1739
+ if result == NotifyOption :: DoPersist {
1740
+ $self. persistence_notifier. notify( ) ;
1741
+ }
1723
1742
}
1724
1743
}
1725
1744
}
@@ -1787,6 +1806,7 @@ where
1787
1806
per_peer_state : FairRwLock :: new ( HashMap :: new ( ) ) ,
1788
1807
1789
1808
pending_events : Mutex :: new ( Vec :: new ( ) ) ,
1809
+ pending_events_processor : AtomicBool :: new ( false ) ,
1790
1810
pending_background_events : Mutex :: new ( Vec :: new ( ) ) ,
1791
1811
total_consistency_lock : RwLock :: new ( ( ) ) ,
1792
1812
persistence_notifier : Notifier :: new ( ) ,
@@ -8026,6 +8046,7 @@ where
8026
8046
per_peer_state : FairRwLock :: new ( per_peer_state) ,
8027
8047
8028
8048
pending_events : Mutex :: new ( pending_events_read) ,
8049
+ pending_events_processor : AtomicBool :: new ( false ) ,
8029
8050
pending_background_events : Mutex :: new ( pending_background_events) ,
8030
8051
total_consistency_lock : RwLock :: new ( ( ) ) ,
8031
8052
persistence_notifier : Notifier :: new ( ) ,
@@ -8057,8 +8078,6 @@ mod tests {
8057
8078
use bitcoin:: hashes:: Hash ;
8058
8079
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
8059
8080
use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
8060
- #[ cfg( feature = "std" ) ]
8061
- use core:: time:: Duration ;
8062
8081
use core:: sync:: atomic:: Ordering ;
8063
8082
use crate :: events:: { Event , HTLCDestination , MessageSendEvent , MessageSendEventsProvider , ClosureReason } ;
8064
8083
use crate :: ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
0 commit comments