Cleaner server shutdown

This commit is contained in:
DBotThePony 2024-05-22 19:00:42 +07:00
parent 0b3aac6189
commit a2cc4ba6c3
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 32 additions and 12 deletions

View File

@ -12,11 +12,7 @@ class IntegratedStarboundServer(val client: StarboundClient, root: File) : Starb
override fun tick0(delta: Double) { override fun tick0(delta: Double) {
if (client.isShutdown) { if (client.isShutdown) {
shutdown() close()
} }
} }
override fun close0() {
}
} }

View File

@ -49,9 +49,12 @@ import ru.dbotthepony.kstarbound.world.SystemWorld
import ru.dbotthepony.kstarbound.world.SystemWorldLocation import ru.dbotthepony.kstarbound.world.SystemWorldLocation
import ru.dbotthepony.kstarbound.world.UniversePos import ru.dbotthepony.kstarbound.world.UniversePos
import java.util.UUID import java.util.UUID
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future import java.util.concurrent.Future
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.locks.ReentrantLock
import java.util.stream.Collectors import java.util.stream.Collectors
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.math.min import kotlin.math.min
@ -523,6 +526,15 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
// set to true so failed connection attempts don't appear in chat // set to true so failed connection attempts don't appear in chat
private var announcedDisconnect = true private var announcedDisconnect = true
private val isDisconnecting = AtomicBoolean() private val isDisconnecting = AtomicBoolean()
private val disconnectSignal = CompletableFuture<Boolean>()
fun waitDisconnect(howLong: Long, timeUnit: TimeUnit): Boolean {
try {
return disconnectSignal.get(howLong, timeUnit)
} catch (err: Throwable) {
return false
}
}
private suspend fun disconnect0(reason: String) { private suspend fun disconnect0(reason: String) {
// make server forget shipworld right away // make server forget shipworld right away
@ -601,8 +613,11 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
channel.flush() channel.flush()
channel.close() channel.close()
} }
disconnectSignal.complete(true)
} catch (err: Throwable) { } catch (err: Throwable) {
LOGGER.error("Exception while disconnecting $this", err) LOGGER.error("Exception while disconnecting $this", err)
disconnectSignal.complete(false)
} finally { } finally {
// don't leave residue entities in worlds if we encountered an exception // don't leave residue entities in worlds if we encountered an exception
tracker?.remove("Disconnect: $reason") tracker?.remove("Disconnect: $reason")
@ -614,7 +629,9 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
override fun disconnect(reason: String) { override fun disconnect(reason: String) {
if (isDisconnecting.compareAndSet(false, true)) { if (isDisconnecting.compareAndSet(false, true)) {
server.scope.launch { disconnect0(reason) } // launch with global scope because server will pause its own thread
// and wait for us to disconnect (if server is shutting down)
Starbound.GLOBAL_SCOPE.launch { disconnect0(reason) }
} }
} }

View File

@ -467,8 +467,10 @@ sealed class StarboundServer(val root: File) : BlockableEventLoop("Server thread
} }
fun notifyWorldUnloaded(worldID: WorldID) { fun notifyWorldUnloaded(worldID: WorldID) {
execute { if (!isShutdown) {
worlds.remove(worldID) execute {
worlds.remove(worldID)
}
} }
} }
@ -516,7 +518,11 @@ sealed class StarboundServer(val root: File) : BlockableEventLoop("Server thread
return channels.connections.firstOrNull { it.uuid == uuid } return channels.connections.firstOrNull { it.uuid == uuid }
} }
protected abstract fun close0() protected open fun close() {
channels.close()
shutdown()
}
protected abstract fun tick0(delta: Double) protected abstract fun tick0(delta: Double)
private fun tick(delta: Double) { private fun tick(delta: Double) {
@ -560,7 +566,6 @@ sealed class StarboundServer(val root: File) : BlockableEventLoop("Server thread
database.commit() database.commit()
databaseCleanable.clean() databaseCleanable.clean()
universe.close() universe.close()
close0()
} }
companion object { companion object {

View File

@ -207,8 +207,10 @@ class ServerWorld private constructor(
clients.forEach { clients.forEach {
LOGGER.info("Kicking ${it.client.alias()} off dying world") LOGGER.info("Kicking ${it.client.alias()} off dying world")
it.remove("World shutting down", setReturnWarp = false) it.remove("World shutting down", setReturnWarp = !uncleanShutdown)
it.client.enqueueWarp(WarpAlias.Return)
if (!server.isShutdown)
it.client.enqueueWarp(WarpAlias.Return)
} }
if (!uncleanShutdown) { if (!uncleanShutdown) {