Do not resume state while it is already closed

This commit is contained in:
Him188 2021-04-21 12:49:19 +08:00
parent 0e1b9da5e4
commit d70475b8ba
2 changed files with 14 additions and 6 deletions

View File

@ -183,7 +183,7 @@ internal abstract class NetworkHandlerSupport(
* You may need to call [BaseStateImpl.resumeConnection] to activate the new state, as states are lazy. * You may need to call [BaseStateImpl.resumeConnection] to activate the new state, as states are lazy.
*/ */
protected inline fun <S : BaseStateImpl> setState(crossinline new: () -> S): S = synchronized(this) { protected inline fun <S : BaseStateImpl> setState(crossinline new: () -> S): S = synchronized(this) {
// we can add hooks here for debug. if (_state.correspondingState == NetworkHandler.State.CLOSED) error("Cannot change state while it has already been CLOSED.")
val stateObserver = context.getOrNull(StateObserver) val stateObserver = context.getOrNull(StateObserver)

View File

@ -118,7 +118,8 @@ internal class NettyNetworkHandler(
} }
future.channel().closeFuture().addListener { future.channel().closeFuture().addListener {
setState { StateConnectionLost(it.cause()) } if (_state.correspondingState == State.CLOSED) return@addListener
setState { StateConnecting(ExceptionCollector(it.cause())) }
} }
return contextResult.await() return contextResult.await()
@ -189,9 +190,15 @@ internal class NettyNetworkHandler(
* *
* Dropped when state becomes [StateOK]. * Dropped when state becomes [StateOK].
*/ */
private val collectiveExceptions: ExceptionCollector private val collectiveExceptions: ExceptionCollector,
wait: Boolean = false
) : NettyState(State.CONNECTING) { ) : NettyState(State.CONNECTING) {
private val connection = async { createConnection(decodePipeline) } private val connection = async {
if (wait) {
delay(5000)
}
createConnection(decodePipeline)
}
private val connectResult = async { private val connectResult = async {
connection.join() connection.join()
@ -199,8 +206,9 @@ internal class NettyNetworkHandler(
}.apply { }.apply {
invokeOnCompletion { error -> invokeOnCompletion { error ->
if (error != null) setState { if (error != null) setState {
StateClosed( StateConnecting(
CancellationException("Connection failure.", collectiveExceptions.collectGet(error)) collectiveExceptions.apply { collect(error) },
wait = true
) )
} // logon failure closes the network handler. } // logon failure closes the network handler.
// and this error will also be thrown by `StateConnecting.resumeConnection` // and this error will also be thrown by `StateConnecting.resumeConnection`