fix: fix resource leak (#136)

When a running service is dropped, its connections should be closed and its resources should be
cleaned up.

This changes the default from leaving services running to closing them. Library users who want
their services to remain running should call `waiting` on their running service, in a new task
where necessary.

Co-authored-by: Paul Ellenbogen <pe5@cs.princeton.edu>
This commit is contained in:
Paul Ellenbogen 2025-04-28 02:56:20 -07:00 • committed by GitHub
commit b1542a6153
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 8 additions and 7 deletions

View file

@ -21,7 +21,7 @@ mod server;
pub use server::*; pub use server::*;
#[cfg(feature = "tower")] #[cfg(feature = "tower")]
mod tower; mod tower;
use tokio_util::sync::CancellationToken; use tokio_util::sync::{CancellationToken, DropGuard};
#[cfg(feature = "tower")] #[cfg(feature = "tower")]
pub use tower::*; pub use tower::*;
use tracing::instrument; use tracing::instrument;
@ -429,8 +429,8 @@ pub struct RunningService<R: ServiceRole, S: Service<R>> {
service: Arc<S>, service: Arc<S>,
peer: Peer<R>, peer: Peer<R>,
handle: tokio::task::JoinHandle<QuitReason>, handle: tokio::task::JoinHandle<QuitReason>,
/// cancellation token /// cancellation token with drop guard
ct: CancellationToken, dg: DropGuard,
} }
impl<R: ServiceRole, S: Service<R>> Deref for RunningService<R, S> { impl<R: ServiceRole, S: Service<R>> Deref for RunningService<R, S> {
type Target = Peer<R>; type Target = Peer<R>;
@ -453,8 +453,9 @@ impl<R: ServiceRole, S: Service<R>> RunningService<R, S> {
self.handle.await self.handle.await
} }
pub async fn cancel(self) -> Result<QuitReason, tokio::task::JoinError> { pub async fn cancel(self) -> Result<QuitReason, tokio::task::JoinError> {
self.ct.cancel(); let RunningService { dg, handle, .. } = self;
self.waiting().await dg.disarm().cancel();
handle.await
} }
} }
@ -759,6 +760,6 @@ where
service, service,
peer: peer_return, peer: peer_return,
handle, handle,
ct, dg: ct.drop_guard(),
}) })
} }

View file

@ -13,6 +13,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
let io = (tokio::io::stdin(), tokio::io::stdout()); let io = (tokio::io::stdin(), tokio::io::stdout());
serve_server(generic_service, io).await?; serve_server(generic_service, io).await?.waiting().await?;
Ok(()) Ok(())
} }