Skip to content

Commit

Permalink
[core] Handle TimeoutCancellationException when resuming connection. Fix
Browse files Browse the repository at this point in the history
 #2504, fix #2488 (#2505)

* #2504,#2488 handle TimeoutCancellationException when resuming connection

* Remove unnecessary code and fix wording

* Use yield() instead of delay

* Use yield() instead of delay
  • Loading branch information
sandtechnology authored Feb 19, 2023
1 parent 38e03fd commit f4667fe
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ internal abstract class AbstractKeepAliveNetworkHandlerSelector<H : NetworkHandl
// 不可挽救
exceptionCollector.throwLast()
}
} catch (e: TimeoutCancellationException) {
logIfEnabled { "... failed with TimeoutCancellationException: $e" }
exceptionCollector.collect(e)
close(e) // close H
logIfEnabled { "CLOSED instance" }
// 发包超时 可挽救
return false
} catch (e: Throwable) {
// 不可挽救
logIfEnabled { "... failed with unexpected: $e" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
package net.mamoe.mirai.internal.network.impl.common

import io.ktor.utils.io.errors.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.*
import net.mamoe.mirai.internal.BotAccount
import net.mamoe.mirai.internal.MockConfiguration
import net.mamoe.mirai.internal.QQAndroidBot
Expand All @@ -30,6 +29,7 @@ import net.mamoe.mirai.internal.network.handler.selector.KeepAliveNetworkHandler
import net.mamoe.mirai.internal.network.handler.selector.NetworkChannelException
import net.mamoe.mirai.internal.network.handler.selector.SelectorNetworkHandler
import net.mamoe.mirai.internal.network.handler.selectorLogger
import net.mamoe.mirai.internal.network.impl.HeartbeatFailedException
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
import net.mamoe.mirai.internal.test.runBlockingUnit
import net.mamoe.mirai.network.CustomLoginFailedException
Expand Down Expand Up @@ -91,6 +91,19 @@ internal class CommonNHBotNormalLoginTest : AbstractCommonNHTest() {
assertState(NetworkHandler.State.CLOSED)
}

// #1963
@Test
fun `test first login failure with internally handled exceptions3`() = runBlockingUnit {
setSsoProcessor {
//Throw TimeoutCancellationException
withTimeout(1) {
delay(1000)
}
}
assertFailsWith<TimeoutCancellationException>("test TimeoutCancellationException") { bot.login() }
assertState(NetworkHandler.State.CLOSED)
}

// 经过 #1963 考虑后在初次登录遇到任何错误都终止并传递异常
// @Test
// fun `test network broken`() = runBlockingUnit {
Expand All @@ -113,9 +126,36 @@ internal class CommonNHBotNormalLoginTest : AbstractCommonNHTest() {
bot.network.close(StatSvc.ReqMSFOffline.MsfOfflineToken(0, 0, 0))

eventDispatcher.joinBroadcast()
delay(1000L) // auto resume in BotOfflineEventMonitor
yield() // auto resume in BotOfflineEventMonitor
eventDispatcher.joinBroadcast()

assertState(NetworkHandler.State.OK)
}

// #2504, #2488
@Test
fun `test resume failed with TimeoutCancellationException`() = runBlockingUnit {
var first = true
var failCount = 3
setSsoProcessor {
if (first) {
first = false
} else {
if (failCount > 0) {
failCount--
//Throw TimeoutCancellationException
withTimeout(1) {
delay(1000)
}
}
}
}
bot.login()
bot.network.close(HeartbeatFailedException("Heartbeat Timeout", RuntimeException("Timeout stub"), true))
eventDispatcher.joinBroadcast()
yield() // auto resume in BotOfflineEventMonitor
eventDispatcher.joinBroadcast()
assertState(NetworkHandler.State.OK)
}

}

0 comments on commit f4667fe

Please sign in to comment.