Commit 4ea98e1a authored by Him188's avatar Him188

Add SupervisorJob

parent 8cb29df5
...@@ -2,7 +2,7 @@ package net.mamoe.mirai.network ...@@ -2,7 +2,7 @@ package net.mamoe.mirai.network
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.cancelChildren
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler.BotSocketAdapter import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler.BotSocketAdapter
...@@ -48,6 +48,8 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> : CoroutineScope { ...@@ -48,6 +48,8 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> : CoroutineScope {
val socket: Socket val socket: Socket
val bot: Bot val bot: Bot
val supervisor get() = SupervisorJob()
/** /**
* 得到 [PacketHandler]. * 得到 [PacketHandler].
* `get(EventPacketHandler)` 返回 [EventPacketHandler] * `get(EventPacketHandler)` 返回 [EventPacketHandler]
...@@ -85,8 +87,6 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> : CoroutineScope { ...@@ -85,8 +87,6 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> : CoroutineScope {
* 关闭网络接口, 停止所有有关协程和任务 * 关闭网络接口, 停止所有有关协程和任务
*/ */
suspend fun close(cause: Throwable? = null) { suspend fun close(cause: Throwable? = null) {
val job = coroutineContext[Job] supervisor.cancelChildren(CancellationException("handler closed", cause))
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))
} }
} }
\ No newline at end of file
...@@ -41,10 +41,11 @@ internal expect val NetworkDispatcher: CoroutineDispatcher ...@@ -41,10 +41,11 @@ internal expect val NetworkDispatcher: CoroutineDispatcher
internal class TIMBotNetworkHandler internal constructor(coroutineContext: CoroutineContext, override inline val bot: Bot) : internal class TIMBotNetworkHandler internal constructor(coroutineContext: CoroutineContext, override inline val bot: Bot) :
BotNetworkHandler<TIMBotNetworkHandler.BotSocketAdapter>, PacketHandlerList() { BotNetworkHandler<TIMBotNetworkHandler.BotSocketAdapter>, PacketHandlerList() {
override val coroutineContext: CoroutineContext = override val coroutineContext: CoroutineContext =
coroutineContext + NetworkDispatcher + CoroutineExceptionHandler { _, e -> coroutineContext + NetworkDispatcher + CoroutineExceptionHandler { _, e ->
bot.logger.error("An exception was thrown in a coroutine under TIMBotNetworkHandler", e) bot.logger.error("An exception was thrown in a coroutine under TIMBotNetworkHandler", e)
} + SupervisorJob() } + supervisor
override lateinit var socket: BotSocketAdapter override lateinit var socket: BotSocketAdapter
...@@ -70,7 +71,11 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -70,7 +71,11 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
return withContext(this.coroutineContext) { return withContext(this.coroutineContext) {
TIMProtocol.SERVER_IP.forEach { ip -> TIMProtocol.SERVER_IP.forEach { ip ->
bot.logger.info("Connecting server $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() loginResult = CompletableDeferred()
...@@ -139,9 +144,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -139,9 +144,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
try { try {
channel.read(buffer)// JVM: withContext(IO) channel.read(buffer)// JVM: withContext(IO)
} catch (e: ClosedChannelException) { } catch (e: ClosedChannelException) {
withContext(userContext) { close()
close()
}
return return
} catch (e: ReadPacketInternalException) { } catch (e: ReadPacketInternalException) {
bot.logger.error("Socket channel read failed: ${e.message}") bot.logger.error("Socket channel read failed: ${e.message}")
...@@ -278,11 +281,17 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -278,11 +281,17 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
try { try {
built.readAvailable(buffer) built.readAvailable(buffer)
val shouldBeSent = buffer.readRemaining 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) { } 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) bot.reinitializeNetworkHandler(configuration, e)
} }
return@withContext return@withContext
...@@ -513,7 +522,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -513,7 +522,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
HeartbeatPacket( HeartbeatPacket(
bot.qqAccount, bot.qqAccount,
sessionKey sessionKey
).sendAndExpectAsync<HeartbeatPacketResponse>().join() ).sendAndExpect<HeartbeatPacketResponse>()
} == null) { } == null) {
bot.logger.warning("Heartbeat timed out") bot.logger.warning("Heartbeat timed out")
bot.reinitializeNetworkHandler(configuration, HeartbeatTimeoutException()) bot.reinitializeNetworkHandler(configuration, HeartbeatTimeoutException())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment