Fix Proxy slow disconnect.
Build android container / android-release-builder-container-build (push) Successful in 10s
Build Mumble Web 2 release builder containers / windows-release-builder-container-build (push) Successful in 13s
Build Mumble Web 2 / linux_build (push) Successful in 1m25s
Build Mumble Web 2 / windows_build (push) Successful in 2m37s
Build Mumble Web 2 / android_build (push) Successful in 5m57s

When `select!` drops a JoinHandle, it doesn't abort the spawned task - it detaches it. From tokio docs:

A JoinHandle detaches the associated task when it is dropped, which means that there is no
longer any handle to the task, and no way to join on it.

This means the spawn task is still spinning in the background:
  1. c2s completes (client disconnected)
  2. select! drops the s2c JoinHandle
  3. The s2c task continues running in the background, detached
  4. That task holds the Mumble server connection open

The fix is to hand the async calls directly to select! instead of
calling tokio::spawn.
This commit is contained in:
2026-01-19 19:17:23 -07:00
parent 7c75e64a64
commit a30082eebe
+6 -12
View File
@@ -335,19 +335,13 @@ async fn connect_proxy_impl(
info!("connected to Mumble server"); info!("connected to Mumble server");
// Spawn tasks to handle transmitting data between the WebTransport client and Mumble TCP Server // Handle transmitting data between the WebTransport client and Mumble TCP Server
let c2s = tokio::spawn( // When one direction completes/fails, the other is dropped and its streams are closed
pass_bytes_loop(incoming, write_server)
.instrument(info_span!("Handler", "Client to server")),
);
let s2c = tokio::spawn(
pass_bytes_loop(read_server, outgoing)
.instrument(info_span!("Handler", "Server to client")),
);
tokio::select! { tokio::select! {
res = c2s => res??, res = pass_bytes_loop(incoming, write_server)
res = s2c => res??, .instrument(info_span!("Handler", "Client to server")) => res?,
res = pass_bytes_loop(read_server, outgoing)
.instrument(info_span!("Handler", "Server to client")) => res?,
}; };
Ok(()) Ok(())
} }