From f13db9de6477147a52268ae586023a059b39617e Mon Sep 17 00:00:00 2001 From: Brad Bishop Date: Wed, 28 Aug 2024 12:27:47 -0400 Subject: [PATCH] Fix socket and memory leak on shutdown When the client is shutting down, its likely that the async_connection_process_loop is polling the stream(socket) and input channel futures, and never wakes so that the stop/shutdown channel can be checked. As a result the async_connection_process_loop task never exits and while not harmful to subsequent connections, the memory associated with the future is never released, and, since the task owns the stream, the socket itself is leaked as well. The fix provided by this patch is straightforward, simply poll the stop channel future as well. An even better fix than the one provided here would be to save the task handle future returned by spawn, poll it somewhere (in case it fails), and join the main task to it on shutdown, after the stop channel has been written to. --- src/client/connection.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client/connection.rs b/src/client/connection.rs index 1ad414b..edc2635 100644 --- a/src/client/connection.rs +++ b/src/client/connection.rs @@ -470,7 +470,7 @@ where let mut pending = 0; // main traffic loop - while let Err(oneshot::error::TryRecvError::Empty) = stop_ch.try_recv() { + loop { if pending > 0 { match conn_ch.try_send(Ok(buffer[0..pending].to_owned())) { Err(TrySendError::Full(_message)) => (), @@ -480,6 +480,7 @@ where } tokio::select! { + _ = &mut stop_ch => break, result = stream.read(&mut buffer), if pending == 0 => { match result { Ok(nread) => {