From 7612ec9c0bce1fa1f9def17f221435ca07e4119d Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:16:21 +0200 Subject: [PATCH] req-resp: Fix memory leak of pending substreams (#297) Similar to https://github.com/paritytech/litep2p/pull/296, there is a possibility of leaking memory in the following edge-case: - T0: Connection is established and outbound substream is initiated with peer - This maps the substream ID to the request bytes information - T1: Connection is closed before the service has a chance to report `TransportEvent::SubstreamOpened` or `TransportEvent::SubstreamOpenFailure` In this case, if we connect and immediately disconnect with a request in flight, we are effectively leaking the request bytes. Detected by: - https://github.com/paritytech/litep2p/pull/294 ### Dashboard - We are leaking ~111 requests over 3 days timespan: Screenshot 2024-12-03 at 10 41 01 cc @paritytech/networking Signed-off-by: Alexandru Vasile --- src/protocol/request_response/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/protocol/request_response/mod.rs b/src/protocol/request_response/mod.rs index 38e631a1..3a64a386 100644 --- a/src/protocol/request_response/mod.rs +++ b/src/protocol/request_response/mod.rs @@ -292,6 +292,9 @@ impl RequestResponseProtocol { async fn on_connection_closed(&mut self, peer: PeerId) { tracing::debug!(target: LOG_TARGET, ?peer, protocol = %self.protocol, "connection closed"); + // Remove any pending outbound substreams for this peer. + self.pending_outbound.retain(|_, context| context.peer != peer); + let Some(context) = self.peers.remove(&peer) else { tracing::error!( target: LOG_TARGET,