From 5769cff60bc16e18b292db68324df70a94ae50b4 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 22 May 2024 19:04:05 +0700 Subject: [PATCH] Wait for clients to disconnect (within reasonable timeframe) before initiating server shutdown --- .../kstarbound/server/ServerChannels.kt | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/server/ServerChannels.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/server/ServerChannels.kt index 68263760..33561da9 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/server/ServerChannels.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/server/ServerChannels.kt @@ -17,6 +17,7 @@ import java.io.Closeable import java.net.SocketAddress import java.util.* import java.util.concurrent.CopyOnWriteArrayList +import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock @@ -112,15 +113,18 @@ class ServerChannels(val server: StarboundServer) : Closeable { val channel = ServerBootstrap().channel(LocalServerChannel::class.java).group(Connection.NIO_POOL).childHandler(object : ChannelInitializer() { override fun initChannel(ch: Channel) { - LOGGER.info("Incoming connection from ${ch.remoteAddress()}") + lock.withLock { + if (isClosed) return + LOGGER.info("Incoming connection from ${ch.remoteAddress()}") - try { - val connection = ServerConnection(server, ConnectionType.MEMORY) - connections.add(connection) - connection.bind(ch) - } catch (err: Throwable) { - LOGGER.error("Error while accepting new connection from ${ch.remoteAddress()}", err) - ch.close() + try { + val connection = ServerConnection(server, ConnectionType.MEMORY) + connections.add(connection) + connection.bind(ch) + } catch (err: Throwable) { + LOGGER.error("Error while accepting new connection from ${ch.remoteAddress()}", err) + ch.close() + } } } }).bind(LocalAddress.ANY).syncUninterruptibly() @@ -141,15 +145,18 @@ class ServerChannels(val server: StarboundServer) : Closeable { lock.withLock { val channel = ServerBootstrap().channel(NioServerSocketChannel::class.java).group(Connection.NIO_POOL).childHandler(object : ChannelInitializer() { override fun initChannel(ch: Channel) { - LOGGER.info("Incoming connection from ${ch.remoteAddress()}") + lock.withLock { + if (isClosed) return + LOGGER.info("Incoming connection from ${ch.remoteAddress()}") - try { - val connection = ServerConnection(server, ConnectionType.NETWORK) - connections.add(connection) - connection.bind(ch) - } catch (err: Throwable) { - LOGGER.error("Error while accepting new connection from ${ch.remoteAddress()}", err) - ch.close() + try { + val connection = ServerConnection(server, ConnectionType.NETWORK) + connections.add(connection) + connection.bind(ch) + } catch (err: Throwable) { + LOGGER.error("Error while accepting new connection from ${ch.remoteAddress()}", err) + ch.close() + } } } }).bind(localAddress).syncUninterruptibly() @@ -168,9 +175,18 @@ class ServerChannels(val server: StarboundServer) : Closeable { override fun close() { lock.withLock { if (isClosed) return + isClosed = true - connections.forEach { it.disconnect("Server shutting down") } channels.forEach { it.channel().close() } + connections.forEach { it.disconnect("Server shutting down") } + + // aeugh + connections.forEach { + if (!it.waitDisconnect(2L, TimeUnit.SECONDS)) { + LOGGER.warn("Giving up waiting for $it to disconnect") + } + } + channels.clear() connections.clear() }