Skip to content

Commit

Permalink
Ensure CoroutineScope.cancel() working; rename to shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
Karlatemp committed May 29, 2022
1 parent 6a06248 commit 1bdbf1c
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 9 deletions.
2 changes: 1 addition & 1 deletion mirai-console/backend/mirai-console/src/MiraiConsole.kt
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public interface MiraiConsole : CoroutineScope {
*/
@ConsoleExperimentalApi
@JvmStatic
public fun shutdownConsole() {
public fun shutdown() {
val consoleJob = job
if (!consoleJob.isActive) return
@OptIn(DelicateCoroutinesApi::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,8 @@ public interface MiraiConsoleImplementation : CoroutineScope {
internal suspend fun shutdown() {
val bridge = currentBridge ?: return
if (!bridge.isActive) return
if (!bridge.isShutdowning.compareAndSet(false, true)) return
bridge.shutdownDaemon.tryStart()

ShutdownDaemon.start()
Bot.instances.forEach { bot ->
lateinit var logger: MiraiLogger
kotlin.runCatching {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import net.mamoe.mirai.console.internal.logging.LoggerControllerImpl
import net.mamoe.mirai.console.internal.logging.MiraiConsoleLogger
import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl
import net.mamoe.mirai.console.internal.shutdown.ShutdownDaemon
import net.mamoe.mirai.console.internal.util.runIgnoreException
import net.mamoe.mirai.console.logging.LoggerController
import net.mamoe.mirai.console.permission.PermissionService
Expand Down Expand Up @@ -86,7 +87,7 @@ internal class MiraiConsoleImplementationBridge(

// used internally
val globalComponentStorage: GlobalComponentStorageImpl by lazy { GlobalComponentStorageImpl() }
val isShutdowning: AtomicBoolean = AtomicBoolean(false)
val shutdownDaemon = ShutdownDaemon.DaemonStarter(this)

// tentative workaround for https://github.com/mamoe/mirai/pull/1889#pullrequestreview-887903183
@Volatile
Expand Down Expand Up @@ -149,6 +150,7 @@ internal class MiraiConsoleImplementationBridge(
}

MiraiConsole.job.invokeOnCompletion {
shutdownDaemon.tryStart()
Bot.instances.forEach { kotlin.runCatching { it.close() }.exceptionOrNull()?.let(mainLogger::error) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@

package net.mamoe.mirai.console.internal.shutdown

import kotlinx.coroutines.*
import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
import net.mamoe.mirai.console.internal.pluginManagerImpl
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.description
import net.mamoe.mirai.utils.debug
import java.io.File
import java.io.FileDescriptor
import java.io.FileOutputStream
Expand All @@ -23,10 +26,25 @@ import java.time.Instant
import java.time.ZoneOffset
import java.util.*
import java.util.concurrent.ConcurrentLinkedDeque
import kotlin.concurrent.thread
import java.util.concurrent.Executors
import java.util.concurrent.ThreadFactory
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import kotlin.io.path.writeText

internal object ShutdownDaemon {
@Suppress("RemoveRedundantQualifierName")
internal class DaemonStarter(
private val consoleImplementationBridge: MiraiConsoleImplementationBridge
) {
private val started = AtomicBoolean(false)
fun tryStart() {
if (started.compareAndSet(false, true)) {
ShutdownDaemon.start(consoleImplementationBridge)
}
}
}

private object ThreadInfoJava9Access {
private val isDaemonM: Method?
private val getPriorityM: Method?
Expand Down Expand Up @@ -63,9 +81,30 @@ internal object ShutdownDaemon {
private val Thread.State.isWaiting: Boolean
get() = this == Thread.State.WAITING || this == Thread.State.TIMED_WAITING

fun start() {
@OptIn(DelicateCoroutinesApi::class)
private fun start(bridge: MiraiConsoleImplementationBridge) {
val crtThread = Thread.currentThread()
thread(name = "Mirai Console Shutdown Daemon", isDaemon = true) { listen(crtThread) }
val isConsoleRunning = AtomicBoolean(true)
// 1 thread to run main daemon
// 1 thread to listen console shutdown running
// 1 thread reserved
val executor = Executors.newFixedThreadPool(3, object : ThreadFactory {
private val counter = AtomicInteger(0)
override fun newThread(r: Runnable): Thread {
return Thread(r, "Mirai Console Shutdown Daemon #" + counter.getAndIncrement()).also {
it.isDaemon = true
}
}
})
executor.execute {
listen(crtThread, isConsoleRunning)
executor.shutdown()
}
GlobalScope.launch(executor.asCoroutineDispatcher()) {
bridge.coroutineContext.job.join()
isConsoleRunning.set(false)
}
bridge.mainLogger.debug { "SHUTDOWN DAEMON STARTED........." }
}

@Suppress("MemberVisibilityCanBePrivate")
Expand Down Expand Up @@ -217,10 +256,10 @@ internal object ShutdownDaemon {
}
}

private fun listen(thread: Thread) {
private fun listen(thread: Thread, consoleRunning: AtomicBoolean) {
val startTime = System.currentTimeMillis()
val timeout = 1000L * 60
while (thread.isAlive) {
while (consoleRunning.get()) {
val crtTime = System.currentTimeMillis()
if (crtTime - startTime >= timeout) {
kotlin.runCatching {
Expand Down

0 comments on commit 1bdbf1c

Please sign in to comment.