From 2351b174f8983abc1463b58b97ea51092bb1d826 Mon Sep 17 00:00:00 2001 From: ericek111 Date: Fri, 2 Oct 2026 06:55:15 +0000 Subject: [PATCH] Leave all servers in parallel on shutdown Quitting tells every server goodbye at once, so leaving takes as long as the slowest server rather than all of them together. Desktop and Android both go through ServerSession.shutdownAll. Co-Authored-By: Claude Opus 5.5 --- .../com/ts3client/android/ServerController.kt | 5 ++--- .../ts3client/android/SessionController.kt | 5 ++++- .../com/ts3client/session/ServerSession.java | 21 +++++++++++++++++++ .../java/com/ts3client/session/Sessions.java | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/android/app/src/main/java/com/ts3client/android/ServerController.kt b/android/app/src/main/java/com/ts3client/android/ServerController.kt index edbc870..cc83b2e 100644 --- a/android/app/src/main/java/com/ts3client/android/ServerController.kt +++ b/android/app/src/main/java/com/ts3client/android/ServerController.kt @@ -117,11 +117,10 @@ class ServerController internal constructor( session.disconnect() } - /** Leaves the server before returning, for when the app goes away with the connection. */ - internal fun leave() { + /** Before the app goes away with the connection, which [SessionController.leave] then ends. */ + internal fun leaving() { left = true network.leaving() - session.shutdown() } internal fun dispose() { diff --git a/android/app/src/main/java/com/ts3client/android/SessionController.kt b/android/app/src/main/java/com/ts3client/android/SessionController.kt index 6730dd7..a15dedb 100644 --- a/android/app/src/main/java/com/ts3client/android/SessionController.kt +++ b/android/app/src/main/java/com/ts3client/android/SessionController.kt @@ -21,6 +21,7 @@ import com.ts3client.myts.MyTeamSpeak import com.ts3client.net.HostButton import com.ts3client.myts.MyTeamSpeakLogin import com.ts3client.session.SelfState +import com.ts3client.session.ServerSession import com.ts3client.session.Sessions import com.ts3client.sound.SoundNotifier import com.ts3client.sound.SoundPack @@ -199,7 +200,9 @@ class SessionController(private val context: Context) { /** Leaves every server before returning, for when the app goes away with the connections. */ fun leave() { - _servers.value.forEach(ServerController::leave) + val servers = _servers.value + servers.forEach(ServerController::leaving) + ServerSession.shutdownAll(servers.map { it.session }) contactStore.flush() } diff --git a/ts3-client/core/src/main/java/com/ts3client/session/ServerSession.java b/ts3-client/core/src/main/java/com/ts3client/session/ServerSession.java index 7643a76..9fcc174 100644 --- a/ts3-client/core/src/main/java/com/ts3client/session/ServerSession.java +++ b/ts3-client/core/src/main/java/com/ts3client/session/ServerSession.java @@ -208,6 +208,27 @@ public final class ServerSession { if (isBusy()) conn.disconnectBlocking("Leaving"); } + /** + * {@link #shutdown()}s every session at once, so leaving takes as long as the slowest + * server rather than all of them together: a frontend may have little time left. + */ + public static void shutdownAll(List sessions) { + List leaving = new ArrayList<>(); + for (ServerSession s : sessions) { + Thread t = new Thread(s::shutdown, "ts3-leave"); + t.start(); + leaving.add(t); + } + for (Thread t : leaving) { + try { + t.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + } + } + /** Releases the background resources of a session that is being thrown away. */ public void dispose() { conn.getIcons().shutdown(); diff --git a/ts3-client/core/src/main/java/com/ts3client/session/Sessions.java b/ts3-client/core/src/main/java/com/ts3client/session/Sessions.java index 745c7ef..ddbd700 100644 --- a/ts3-client/core/src/main/java/com/ts3client/session/Sessions.java +++ b/ts3-client/core/src/main/java/com/ts3client/session/Sessions.java @@ -153,7 +153,7 @@ public final class Sessions { /** Leaves every server, waiting until each has been told. */ public void shutdown() { - for (ServerSession s : new ArrayList<>(sessions)) s.shutdown(); + ServerSession.shutdownAll(new ArrayList<>(sessions)); handover.shutdown(); } }