diff --git a/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandler.kt b/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandler.kt index 2423988ce..088a2b2d1 100644 --- a/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandler.kt +++ b/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandler.kt @@ -148,6 +148,8 @@ internal interface NetworkHandler : CoroutineScope { /** * Closes this handler gracefully (i.e. asynchronously). + * + * After invocation of [close], [state] will always be [State.CLOSED]. */ fun close(cause: Throwable?) diff --git a/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandlerSupport.kt b/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandlerSupport.kt index 0dd0028f2..ec3470244 100644 --- a/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandlerSupport.kt +++ b/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandlerSupport.kt @@ -47,11 +47,6 @@ internal abstract class NetworkHandlerSupport( } override fun close(cause: Throwable?) { -// if (cause == null) { -// logger.info { "NetworkHandler '$this' closed" } -// } else { -// logger.info { "NetworkHandler '$this' closed: $cause" } -// } if (coroutineContext.job.isActive) { coroutineContext.job.cancel("NetworkHandler closed", cause) } @@ -202,6 +197,7 @@ internal abstract class NetworkHandlerSupport( protected data class StateSwitchingException( val old: BaseStateImpl, val new: BaseStateImpl, + override val cause: Throwable? = new.getCause(), // so it can be unwrapped ) : CancellationException("State is switched from $old to $new") /** diff --git a/mirai-core/src/commonMain/kotlin/network/impl/netty/NettyNetworkHandler.kt b/mirai-core/src/commonMain/kotlin/network/impl/netty/NettyNetworkHandler.kt index 1d92ddcf5..2c9cffc85 100644 --- a/mirai-core/src/commonMain/kotlin/network/impl/netty/NettyNetworkHandler.kt +++ b/mirai-core/src/commonMain/kotlin/network/impl/netty/NettyNetworkHandler.kt @@ -195,15 +195,14 @@ internal open class NettyNetworkHandler( /////////////////////////////////////////////////////////////////////////// override fun close(cause: Throwable?) { - if (state == State.CLOSED) return // already - super.close(cause) - // when coroutine scope completed, state is already set to CLOSED, - // see the following `init` block. + if (state == State.CLOSED) return // quick check if already closed + if (setState { StateClosed(cause) } == null) return // atomic check + super.close(cause) // cancel coroutine scope } init { coroutineContext.job.invokeOnCompletion { e -> - setState { StateClosed(e?.unwrapCancellationException()) } + close(e?.unwrapCancellationException()) } }