Skip to content

Commit

Permalink
Force halt system to avoid some magic errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Karlatemp committed Jun 4, 2022
1 parent 12d46d7 commit 11f50c6
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ internal fun startupConsoleThread() {
} catch (e: CancellationException) {
return@launch
} catch (e: UserInterruptException) {
BuiltInCommands.StopCommand.run { ConsoleCommandSender.handle() }
signalHandler("INT")
return@launch
} catch (eof: EndOfFileException) {
consoleLogger.warning("Closing input service...")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,18 @@ object MiraiConsoleTerminalLoader {
startAsDaemon()
try {
runBlocking {
MiraiConsole.job.invokeOnCompletion {
Thread.sleep(1000) // 保证错误信息打印完全
exitProcess(0)
MiraiConsole.job.invokeOnCompletion { err ->
if (err != null) {
Thread.sleep(1000) // 保证错误信息打印完全
}
}
MiraiConsole.job.join()
}
} catch (e: CancellationException) {
// ignored
}
// Avoid plugin started some non-daemon threads
exitProcessAndForceHalt(0)
}

@ConsoleTerminalExperimentalApi
Expand Down Expand Up @@ -207,7 +210,8 @@ private fun initSignalHandler(): (String) -> Unit {
MiraiConsole.job.join()

delay(15000)
exitProcess(-5) // Force kill process if plugins started non-daemon threads
// Force kill process if plugins started non-daemon threads
exitProcessAndForceHalt(-5)
}
}
}
Expand All @@ -220,6 +224,38 @@ internal fun registerSignalHandler() {
shutdownSignals.forEach { reg(it) }
}

internal fun exitProcessAndForceHalt(code: Int): Nothing {
MiraiConsole.mainLogger.debug { "[exitProcessAndForceHalt] called with code $code" }

val exitFuncName = arrayOf("exit", "halt")
val shutdownClasses = arrayOf("java.lang.System", "java.lang.Runtime", "java.lang.Shutdown")
val isShutdowning = Thread.getAllStackTraces().asSequence().flatMap {
it.value.asSequence()
}.any { stackTrace ->
stackTrace.className in shutdownClasses && stackTrace.methodName in exitFuncName
}
MiraiConsole.mainLogger.debug { "[exitProcessAndForceHalt] isShutdowning = $isShutdowning" }

val task = Runnable {
Thread.sleep(15000L)
runCatching { net.mamoe.mirai.console.internal.shutdown.ShutdownDaemon.dumpCrashReport(true) }
val fc = when (code) {
0 -> 5784171
else -> code
}

MiraiConsole.mainLogger.debug { "[exitProcessAndForceHalt] timed out, force halt with code $fc" }
Runtime.getRuntime().halt(fc)
}
if (isShutdowning) {
task.run()
error("Runtime.halt returned normally, while it was supposed to halt JVM.")
} else {
Thread(task, "Mirai Console Force Halt Daemon").start()
exitProcess(code)
}
}

internal fun overrideSTD(terminal: MiraiConsoleImplementation) {
if (ConsoleTerminalSettings.noConsole) {
SystemOutputPrintStream // Avoid StackOverflowError when launch with no console mode
Expand Down

0 comments on commit 11f50c6

Please sign in to comment.