diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/DaemonParams.kt b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/DaemonParams.kt index e41ee889db8..8722653b84f 100644 --- a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/DaemonParams.kt +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/DaemonParams.kt @@ -39,6 +39,7 @@ public val COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY: String = "kotlin.daemon.cl public val COMPILE_DAEMON_LOG_PATH_PROPERTY: String = "kotlin.daemon.log.path" public val COMPILE_DAEMON_REPORT_PERF_PROPERTY: String = "kotlin.daemon.perf" public val COMPILE_DAEMON_VERBOSE_REPORT_PROPERTY: String = "kotlin.daemon.verbose" +public val COMPILE_DAEMON_FORCE_SHUTDOWN_PROPERTY: String = "kotlin.daemon.force.shutdown" public val COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX: String = "--daemon-" public val COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY: String = "kotlin.daemon.startup.timeout" public val COMPILE_DAEMON_DEFAULT_FILES_PREFIX: String = "kotlin-daemon" @@ -304,6 +305,7 @@ public fun configureDaemonJVMOptions(opts: DaemonJVMOptions, inheritMemoryLimits System.getProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)?.let { opts.jvmParams.add("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"$it\"" ) } opts.jvmParams.addAll(additionalParams) + System.getProperty(COMPILE_DAEMON_FORCE_SHUTDOWN_PROPERTY)?.let { opts.jvmParams.add(COMPILE_DAEMON_FORCE_SHUTDOWN_PROPERTY) } return opts } diff --git a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt index 9090dd20de8..5f5460ac45b 100644 --- a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt +++ b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt @@ -27,12 +27,15 @@ import java.io.PrintStream import java.rmi.NoSuchObjectException import java.rmi.registry.Registry import java.rmi.server.UnicastRemoteObject +import java.util.* import java.util.concurrent.TimeUnit import java.util.concurrent.locks.ReentrantReadWriteLock import java.util.logging.Logger import kotlin.concurrent.read import kotlin.concurrent.write +import kotlin.concurrent.schedule +val DAEMON_SHUTDOWN_DELAY_MS = 1000L fun nowSeconds() = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()) @@ -46,7 +49,7 @@ class CompileServiceImpl( val selfCompilerId: CompilerId, val daemonOptions: DaemonOptions, port: Int -) : CompileService, UnicastRemoteObject() { +) : CompileService { // RMI-exposed API @@ -60,6 +63,14 @@ class CompileServiceImpl( alive = false UnicastRemoteObject.unexportObject(this, true) log.info("Shutdown complete") + if (System.getProperty(COMPILE_DAEMON_FORCE_SHUTDOWN_PROPERTY) != null) { + // running a watcher thread that ensures that if the daemon is not exited normally (may be due to RMI leftovers), it's forced to exit + // the watcher is a daemon thread, meaning it should not prevent JVM to exit normally + Timer(true).schedule(DAEMON_SHUTDOWN_DELAY_MS) { + log.info("force JVM shutdown") + System.exit(0) + } + } } }