From 4ea98e1a8af84b068d8a95d2ba0de5c00e0dcdce Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Wed, 20 Nov 2019 19:11:04 +0800 Subject: [PATCH] Add SupervisorJob --- .../network/BotNetworkHandler.kt | 8 +++--- .../protocol/tim/TIMBotNetworkHandler.kt | 27 ++++++++++++------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt index e96526bee..33a8e3dd5 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt @@ -2,7 +2,7 @@ package net.mamoe.mirai.network import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancelChildren import net.mamoe.mirai.Bot import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler.BotSocketAdapter @@ -48,6 +48,8 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> : CoroutineScope { val socket: Socket val bot: Bot + val supervisor get() = SupervisorJob() + /** * 得到 [PacketHandler]. * `get(EventPacketHandler)` 返回 [EventPacketHandler] @@ -85,8 +87,6 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> : CoroutineScope { * 关闭网络接口, 停止所有有关协程和任务 */ suspend fun close(cause: Throwable? = null) { - val job = coroutineContext[Job] - checkNotNull(job) { "Job should not be null because there will always be a SupervisorJob. There may be a internal mistake" } - job.cancelChildren(CancellationException("handler closed", cause)) + supervisor.cancelChildren(CancellationException("handler closed", cause)) } } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt index fef5a2e5d..287834313 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt @@ -41,10 +41,11 @@ internal expect val NetworkDispatcher: CoroutineDispatcher internal class TIMBotNetworkHandler internal constructor(coroutineContext: CoroutineContext, override inline val bot: Bot) : BotNetworkHandler<TIMBotNetworkHandler.BotSocketAdapter>, PacketHandlerList() { + override val coroutineContext: CoroutineContext = coroutineContext + NetworkDispatcher + CoroutineExceptionHandler { _, e -> bot.logger.error("An exception was thrown in a coroutine under TIMBotNetworkHandler", e) - } + SupervisorJob() + } + supervisor override lateinit var socket: BotSocketAdapter @@ -70,7 +71,11 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou return withContext(this.coroutineContext) { TIMProtocol.SERVER_IP.forEach { ip -> bot.logger.info("Connecting server $ip") - socket = BotSocketAdapter(ip, configuration) + try { + socket = BotSocketAdapter(ip, configuration) + } catch (e: Exception) { + return@withContext LoginResult.NETWORK_UNAVAILABLE + } loginResult = CompletableDeferred() @@ -139,9 +144,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou try { channel.read(buffer)// JVM: withContext(IO) } catch (e: ClosedChannelException) { - withContext(userContext) { - close() - } + close() return } catch (e: ReadPacketInternalException) { bot.logger.error("Socket channel read failed: ${e.message}") @@ -278,11 +281,17 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou try { built.readAvailable(buffer) val shouldBeSent = buffer.readRemaining - check(channel.send(buffer) == shouldBeSent) { "Buffer is not entirely sent. Required sent length=$shouldBeSent, but after channel.send, buffer remains ${buffer.readBytes().toUHexString()}" }//JVM: withContext(IO) + check(channel.send(buffer) == shouldBeSent) { + "Buffer is not entirely sent. " + + "Required sent length=$shouldBeSent, but after channel.send, " + + "buffer remains ${buffer.readBytes().toUHexString()}" + }//JVM: withContext(IO) } catch (e: SendPacketInternalException) { - bot.logger.error("Caught SendPacketInternalException: ${e.cause?.message}") + if (e.cause !is CancellationException) { + bot.logger.error("Caught SendPacketInternalException: ${e.cause?.message}") + } - withContext(userContext) { + GlobalScope.launch(userContext) { bot.reinitializeNetworkHandler(configuration, e) } return@withContext @@ -513,7 +522,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou HeartbeatPacket( bot.qqAccount, sessionKey - ).sendAndExpectAsync<HeartbeatPacketResponse>().join() + ).sendAndExpect<HeartbeatPacketResponse>() } == null) { bot.logger.warning("Heartbeat timed out") bot.reinitializeNetworkHandler(configuration, HeartbeatTimeoutException())