Improve logging on exceptions and correctly handle CancellationException when Bot.close is invoked.

This commit is contained in:
Him188 2021-06-08 12:18:31 +08:00
parent 3e8fc8e1ec
commit 54a78313c8
5 changed files with 17 additions and 5 deletions

View File

@ -39,6 +39,7 @@ import net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandlerFactory
import net.mamoe.mirai.internal.utils.subLogger
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.warning
import kotlin.contracts.contract
internal fun Bot.asQQAndroidBot(): QQAndroidBot {
@ -87,6 +88,7 @@ internal open class QQAndroidBot constructor(
val cause = new.getCause()
if (cause is NetworkException && cause.recoverable) {
eventDispatcher.broadcastAsync(BotOfflineEvent.Dropped(bot, new.getCause()))
logger.warning { "Connection lost. Attempting to reconnect..." }
} else {
eventDispatcher.broadcastAsync(BotOfflineEvent.Active(bot, new.getCause()))
}

View File

@ -75,6 +75,7 @@ internal open class EventDispatcherImpl(
event.broadcast()
}
} catch (e: Exception) {
if (e is CancellationException) return
if (logger.isEnabled) {
val msg = optimizeEventToString(event)
logger.error(IllegalStateException("Exception while broadcasting event '$msg'", e))

View File

@ -20,6 +20,7 @@ import net.mamoe.mirai.internal.network.component.ComponentStorage
import net.mamoe.mirai.internal.network.protocol.packet.*
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.cast
import kotlin.coroutines.cancellation.CancellationException
internal interface PacketHandler {
suspend fun handlePacket(incomingPacket: IncomingPacket)
@ -38,7 +39,8 @@ internal class PacketHandlerChain(
try {
instance.handlePacket(incomingPacket)
} catch (e: Throwable) {
throw ExceptionInPacketHandlerException(instance, e)
if (e is CancellationException) return
throw ExceptionInPacketHandlerException(instance, incomingPacket, e)
}
}
}
@ -46,8 +48,9 @@ internal class PacketHandlerChain(
internal data class ExceptionInPacketHandlerException(
val packetHandler: PacketHandler,
val incomingPacket: IncomingPacket,
override val cause: Throwable,
) : IllegalStateException("Exception in PacketHandler '$packetHandler'.")
) : IllegalStateException("Exception in PacketHandler '$packetHandler' for command '${incomingPacket.commandName}'.")
internal class LoggingPacketHandlerAdapter(
private val strategy: PacketLoggingStrategy,

View File

@ -22,6 +22,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.systemProp
import net.mamoe.mirai.utils.verbose
import kotlin.coroutines.cancellation.CancellationException
/**
* Implementation must be fast and non-blocking, throwing no exception.
@ -44,13 +45,14 @@ internal class PacketLoggingStrategyImpl(
override fun logReceived(logger: MiraiLogger, incomingPacket: IncomingPacket) {
incomingPacket.exception?.let {
logger.error(it)
if (it is CancellationException) return
logger.error("Exception in decoding packet.", it)
return
}
val packet = incomingPacket.data ?: return
if (!bot.logger.isEnabled && !logger.isEnabled) return
if (packet is ParseErrorPacket) {
packet.direction.getLogger(bot).error(packet.error)
packet.direction.getLogger(bot).error("Exception in parsing packet.", packet.error)
}
if (incomingPacket.data is MultiPacket<*>) {
for (d in incomingPacket.data) {

View File

@ -19,6 +19,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.utils.findCauseOrSelf
import net.mamoe.mirai.utils.hierarchicalName
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.cancellation.CancellationException
/**
* A proxy to [NetworkHandler] that delegates calls to instance returned by [NetworkHandlerSelector.awaitResumeInstance].
@ -49,7 +50,10 @@ internal class SelectorNetworkHandler(
private val scope = CoroutineScope(SupervisorJob(context.bot.coroutineContext[Job]))
private suspend inline fun instance(): NetworkHandler {
if (!scope.isActive) throw lastCancellationCause ?: error("SelectorNetworkHandler is already closed")
if (!scope.isActive) {
throw lastCancellationCause?.let(::CancellationException)
?: CancellationException("SelectorNetworkHandler is already closed")
}
return selector.awaitResumeInstance()
}