diff --git a/src/dorkbox/network/Server.kt b/src/dorkbox/network/Server.kt index 0649398a..c1d9bb08 100644 --- a/src/dorkbox/network/Server.kt +++ b/src/dorkbox/network/Server.kt @@ -398,7 +398,7 @@ open class Server( * Closes the server and all it's connections. After a close, you may call 'bind' again. */ final override fun close0() { - // when we call close, it will shutdown the polling mechanism, then wait for us to tell it to cleanup connections. + // when we call close, it will shut-down the polling mechanism, then wait for us to tell it to clean-up connections. // // Aeron + the Media Driver will have already been shutdown at this point. if (bindAlreadyCalled.getAndSet(false)) { diff --git a/src/dorkbox/network/connection/EndPoint.kt b/src/dorkbox/network/connection/EndPoint.kt index e3b407a5..e5ecb8f4 100644 --- a/src/dorkbox/network/connection/EndPoint.kt +++ b/src/dorkbox/network/connection/EndPoint.kt @@ -903,38 +903,19 @@ internal constructor(val type: Class<*>, if (shutdown.compareAndSet(expect = false, update = true)) { logger.info { "Shutting down..." } - - // the server has to be able to call server.notifyDisconnect() on a list of connections. If we remove the connections - // inside of connection.close(), then the server does not have a list of connections to call the global notifyDisconnect() - val enableRemove = type == Client::class.java - connections.forEach { - logger.info { "[${it.id}/${it.streamId}] Closing connection" } - it.close(enableRemove) - } - - runBlocking { - // Connections are closed first, because we want to make sure that no RMI messages can be received + closeAction { + // Connections MUST be closed first, because we want to make sure that no RMI messages can be received // when we close the RMI support objects (in which case, weird - but harmless - errors show up) - // this will wait for RMI timeouts if there are RMI in-progress. (this happens if we close via and RMI method) + // this will wait for RMI timeouts if there are RMI in-progress. (this happens if we close via an RMI method) responseManager.close() + + // the storage is closed via this as well. + storage.close() } - // the storage is closed via this as well. - storage.close() - - close0() - - aeronDriver.close() - - shutdownLatch = CountDownLatch(1) - - // if we are waiting for shutdown, cancel the waiting thread (since we have shutdown now) - shutdownLatch.countDown() - logger.info { "Done shutting down..." } } } - /** * Close in such a way that we enable us to be restarted. This is the same as a "normal close", but DOES NOT close * - response manager @@ -944,28 +925,37 @@ internal constructor(val type: Class<*>, if (shutdown.compareAndSet(expect = false, update = true)) { logger.info { "Shutting down for restart..." } - - // the server has to be able to call server.notifyDisconnect() on a list of connections. If we remove the connections - // inside of connection.close(), then the server does not have a list of connections to call the global notifyDisconnect() - val enableRemove = type == Client::class.java - connections.forEach { - logger.info { "[${it.id}/${it.streamId}] Closing connection" } - it.close(enableRemove) - } - - close0() - - aeronDriver.close() - - shutdownLatch = CountDownLatch(1) - - // if we are waiting for shutdown, cancel the waiting thread (since we have shutdown now) - shutdownLatch.countDown() + closeAction() logger.info { "Done shutting down for restart..." } } } + private fun closeAction(extraActions: suspend () -> Unit = {}) { + // the server has to be able to call server.notifyDisconnect() on a list of connections. If we remove the connections + // inside of connection.close(), then the server does not have a list of connections to call the global notifyDisconnect() + val enableRemove = type == Client::class.java + connections.forEach { + logger.info { "[${it.id}/${it.streamId}] Closing connection" } + it.close(enableRemove) + } + + // must run after connections have been closed, but before anything else + runBlocking { + extraActions() + } + + close0() + + aeronDriver.close() + + shutdownLatch = CountDownLatch(1) + + // if we are waiting for shutdown, cancel the waiting thread (since we have shutdown now) + shutdownLatch.countDown() + } + + internal open fun close0() {}