Acquire `per_peer_state` `write` lock earlier in `ChannelManager::write`
authorElias Rohrer <dev@tnull.de>
Wed, 17 Apr 2024 09:54:25 +0000 (11:54 +0200)
committerElias Rohrer <dev@tnull.de>
Wed, 17 Apr 2024 10:02:00 +0000 (12:02 +0200)
Previously, we would hold the `per_peer_state` `read` lock during the
serialization of channel objects. While this might have reduced lock
congestion minimally, we also calculated the number of serializable
peers in this phase, only to use it later after dropping and reacquiring
the `per_peer_state` `write` lock.

This could potentially result in inconsistiencies if the
`serializable_peer_count` would change after we dropped the `read` lock
but before we acquired the `write` lock.

To mitigate the issue we just acquire the `write` lock ealier and hold
it for the remainder of `ChannelManager::write`.

lightning/src/ln/channelmanager.rs

index abbab5ff0a70d8f0d5b4b7bf58b3bf4702647566..6581500d7124221e0b03bf8806a040eba61a52d4 100644 (file)
@@ -11035,9 +11035,10 @@ where
                        best_block.block_hash.write(writer)?;
                }
 
+               let per_peer_state = self.per_peer_state.write().unwrap();
+
                let mut serializable_peer_count: u64 = 0;
                {
-                       let per_peer_state = self.per_peer_state.read().unwrap();
                        let mut number_of_funded_channels = 0;
                        for (_, peer_state_mutex) in per_peer_state.iter() {
                                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
@@ -11084,8 +11085,6 @@ where
                        decode_update_add_htlcs_opt = Some(decode_update_add_htlcs);
                }
 
-               let per_peer_state = self.per_peer_state.write().unwrap();
-
                let pending_inbound_payments = self.pending_inbound_payments.lock().unwrap();
                let claimable_payments = self.claimable_payments.lock().unwrap();
                let pending_outbound_payments = self.pending_outbound_payments.pending_outbound_payments.lock().unwrap();