Skip to content

Commit f2ecf8d

Browse files
committed
Split PeerManager::handle_message to avoid explicit mem::drop
Previously, `handle_message` was a single large method consisting of two logical parts: one modifying the peer state hence requiring us to hold the `peer_lock` `MutexGuard`, and, after calling `mem::drop(peer_lock)`, the remainder which does not only *not* require to hold the `MutexGuard`, but relies on it being dropped to avoid double-locking. However, the `mem::drop` was easily overlooked, making reasoning about lock orders etc. a headache. Here, we therefore have `handle_message` call two sub-methods reflecting the two logical parts, allowing us to avoid the explicit `mem::drop`, while at the same time making it less error-prone due to the two methods' signatures.
1 parent b8b1ef3 commit f2ecf8d

File tree

1 file changed

+40
-6
lines changed

1 file changed

+40
-6
lines changed

lightning/src/ln/peer_handler.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,15 +1588,37 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
15881588
}
15891589

15901590
/// Process an incoming message and return a decision (ok, lightning error, peer handling error) regarding the next action with the peer
1591+
///
15911592
/// Returns the message back if it needs to be broadcasted to all other peers.
15921593
fn handle_message(
15931594
&self,
15941595
peer_mutex: &Mutex<Peer>,
1595-
mut peer_lock: MutexGuard<Peer>,
1596-
message: wire::Message<<<CMH as core::ops::Deref>::Target as wire::CustomMessageReader>::CustomMessage>
1597-
) -> Result<Option<wire::Message<<<CMH as core::ops::Deref>::Target as wire::CustomMessageReader>::CustomMessage>>, MessageHandlingError> {
1596+
peer_lock: MutexGuard<Peer>,
1597+
message: wire::Message<<<CMH as Deref>::Target as wire::CustomMessageReader>::CustomMessage>
1598+
) -> Result<Option<wire::Message<<<CMH as Deref>::Target as wire::CustomMessageReader>::CustomMessage>>, MessageHandlingError> {
15981599
let their_node_id = peer_lock.their_node_id.clone().expect("We know the peer's public key by the time we receive messages").0;
15991600
let logger = WithContext::from(&self.logger, Some(their_node_id), None);
1601+
1602+
let message = match self.do_handle_message_holding_peer_lock(peer_lock, message, &their_node_id, &logger)? {
1603+
Some(processed_message) => processed_message,
1604+
None => return Ok(None),
1605+
};
1606+
1607+
self.do_handle_message_without_peer_lock(peer_mutex, message, &their_node_id, &logger)
1608+
}
1609+
1610+
// Conducts all message processing that requires us to hold the `peer_lock`.
1611+
//
1612+
// Returns `None` if the message was fully processed and otherwise returns the message back to
1613+
// allow it to be subsequently processed by `do_handle_message_without_peer_lock`.
1614+
fn do_handle_message_holding_peer_lock<'a>(
1615+
&self,
1616+
mut peer_lock: MutexGuard<Peer>,
1617+
message: wire::Message<<<CMH as Deref>::Target as wire::CustomMessageReader>::CustomMessage>,
1618+
their_node_id: &PublicKey,
1619+
logger: &WithContext<'a, L>
1620+
) -> Result<Option<wire::Message<<<CMH as Deref>::Target as wire::CustomMessageReader>::CustomMessage>>, MessageHandlingError>
1621+
{
16001622
peer_lock.received_message_since_timer_tick = true;
16011623

16021624
// Need an Init as first message
@@ -1677,8 +1699,20 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
16771699
peer_lock.received_channel_announce_since_backlogged = true;
16781700
}
16791701

1680-
mem::drop(peer_lock);
1702+
Ok(Some(message))
1703+
}
16811704

1705+
// Conducts all message processing that doesn't require us to hold the `peer_lock`.
1706+
//
1707+
// Returns the message back if it needs to be broadcasted to all other peers.
1708+
fn do_handle_message_without_peer_lock<'a>(
1709+
&self,
1710+
peer_mutex: &Mutex<Peer>,
1711+
message: wire::Message<<<CMH as Deref>::Target as wire::CustomMessageReader>::CustomMessage>,
1712+
their_node_id: &PublicKey,
1713+
logger: &WithContext<'a, L>
1714+
) -> Result<Option<wire::Message<<<CMH as Deref>::Target as wire::CustomMessageReader>::CustomMessage>>, MessageHandlingError>
1715+
{
16821716
if is_gossip_msg(message.type_id()) {
16831717
log_gossip!(logger, "Received message {:?} from {}", message, log_pubkey!(their_node_id));
16841718
} else {
@@ -1880,7 +1914,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
18801914
Ok(should_forward)
18811915
}
18821916

1883-
fn forward_broadcast_msg(&self, peers: &HashMap<Descriptor, Mutex<Peer>>, msg: &wire::Message<<<CMH as core::ops::Deref>::Target as wire::CustomMessageReader>::CustomMessage>, except_node: Option<&PublicKey>) {
1917+
fn forward_broadcast_msg(&self, peers: &HashMap<Descriptor, Mutex<Peer>>, msg: &wire::Message<<<CMH as Deref>::Target as wire::CustomMessageReader>::CustomMessage>, except_node: Option<&PublicKey>) {
18841918
match msg {
18851919
wire::Message::ChannelAnnouncement(ref msg) => {
18861920
log_gossip!(self.logger, "Sending message to all peers except {:?} or the announced channel's counterparties: {:?}", except_node, msg);
@@ -2272,7 +2306,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
22722306
// We do not have the peers write lock, so we just store that we're
22732307
// about to disconnect the peer and do it after we finish
22742308
// processing most messages.
2275-
let msg = msg.map(|msg| wire::Message::<<<CMH as core::ops::Deref>::Target as wire::CustomMessageReader>::CustomMessage>::Error(msg));
2309+
let msg = msg.map(|msg| wire::Message::<<<CMH as Deref>::Target as wire::CustomMessageReader>::CustomMessage>::Error(msg));
22762310
peers_to_disconnect.insert(node_id, msg);
22772311
},
22782312
msgs::ErrorAction::DisconnectPeerWithWarning { msg } => {

0 commit comments

Comments
 (0)