Leave all servers in parallel on shutdown
Some checks are pending
test / test (push) Waiting to run

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 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 06:55:15 +00:00
parent 5fd2a612b9
commit 2351b174f8
4 changed files with 28 additions and 5 deletions

View File

@@ -117,11 +117,10 @@ class ServerController internal constructor(
session.disconnect() session.disconnect()
} }
/** Leaves the server before returning, for when the app goes away with the connection. */ /** Before the app goes away with the connection, which [SessionController.leave] then ends. */
internal fun leave() { internal fun leaving() {
left = true left = true
network.leaving() network.leaving()
session.shutdown()
} }
internal fun dispose() { internal fun dispose() {

View File

@@ -21,6 +21,7 @@ import com.ts3client.myts.MyTeamSpeak
import com.ts3client.net.HostButton import com.ts3client.net.HostButton
import com.ts3client.myts.MyTeamSpeakLogin import com.ts3client.myts.MyTeamSpeakLogin
import com.ts3client.session.SelfState import com.ts3client.session.SelfState
import com.ts3client.session.ServerSession
import com.ts3client.session.Sessions import com.ts3client.session.Sessions
import com.ts3client.sound.SoundNotifier import com.ts3client.sound.SoundNotifier
import com.ts3client.sound.SoundPack 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. */ /** Leaves every server before returning, for when the app goes away with the connections. */
fun leave() { fun leave() {
_servers.value.forEach(ServerController::leave) val servers = _servers.value
servers.forEach(ServerController::leaving)
ServerSession.shutdownAll(servers.map { it.session })
contactStore.flush() contactStore.flush()
} }

View File

@@ -208,6 +208,27 @@ public final class ServerSession {
if (isBusy()) conn.disconnectBlocking("Leaving"); 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<ServerSession> sessions) {
List<Thread> 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. */ /** Releases the background resources of a session that is being thrown away. */
public void dispose() { public void dispose() {
conn.getIcons().shutdown(); conn.getIcons().shutdown();

View File

@@ -153,7 +153,7 @@ public final class Sessions {
/** Leaves every server, waiting until each has been told. */ /** Leaves every server, waiting until each has been told. */
public void shutdown() { public void shutdown() {
for (ServerSession s : new ArrayList<>(sessions)) s.shutdown(); ServerSession.shutdownAll(new ArrayList<>(sessions));
handover.shutdown(); handover.shutdown();
} }
} }