Use connect-and-lease when using daemon in JPS & Gradle

Relates to KT-15562 "Service is dying".

This commit includes multiple changes:
 1. JPS & Gradle daemon clients are refactored to use `connectAndLease` from `KotlinCompilerClient`.
 `connectAndLease` was introduced in previous commits
 2. `withKotlin` was removed because `connectAndLease` already covers retrying on connection error
 3. Gradle flag files creation is changed:
   * client-alive flag file lives as long as Gradle instance lives,
   * session-alive flag file lives until the end of a build.
This commit is contained in:
Alexey Tsvetkov
2017-02-22 07:57:47 +03:00
parent 9819de1abd
commit 9d95c841a6
9 changed files with 279 additions and 130 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.daemon.client.CompileServiceSession
import org.jetbrains.kotlin.daemon.client.CompilationServices
import org.jetbrains.kotlin.daemon.client.DaemonReportMessage
import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets
@@ -54,12 +55,16 @@ abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
protected abstract val log: KotlinLogger
class DaemonConnection(val daemon: CompileService?, val sessionId: Int = CompileService.NO_SESSION)
protected abstract fun getDaemonConnection(environment: Env): DaemonConnection
protected abstract fun getDaemonConnection(environment: Env): CompileServiceSession?
@Synchronized
protected fun newDaemonConnection(compilerId: CompilerId, flagFile: File, environment: Env, daemonOptions: DaemonOptions = configureDaemonOptions()): DaemonConnection {
protected fun newDaemonConnection(
compilerId: CompilerId,
clientAliveFlagFile: File,
sessionAliveFlagFile: File,
environment: Env,
daemonOptions: DaemonOptions = configureDaemonOptions()
): CompileServiceSession? {
val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritAdditionalProperties = true)
val daemonReportMessages = ArrayList<DaemonReportMessage>()
@@ -71,13 +76,19 @@ abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
val profiler = if (daemonOptions.reportPerf) WallAndThreadAndMemoryTotalProfiler(withGC = false) else DummyProfiler()
val connection = profiler.withMeasure(null) {
val daemon = KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, daemonReportingTargets, true, true)
DaemonConnection(daemon, daemon?.leaseCompileSession(flagFile.absolutePath)?.get() ?: CompileService.NO_SESSION)
KotlinCompilerClient.connectAndLease(compilerId,
clientAliveFlagFile,
daemonJVMOptions,
daemonOptions,
daemonReportingTargets,
autostart = true,
leaseSession = true,
sessionAliveFlagFile = sessionAliveFlagFile)
}
for (msg in daemonReportMessages) {
environment.messageCollector.report(CompilerMessageSeverity.INFO,
(if (msg.category == DaemonReportCategory.EXCEPTION && connection.daemon == null) "Falling back to compilation without daemon due to error: " else "") + msg.message,
(if (msg.category == DaemonReportCategory.EXCEPTION && connection == null) "Falling back to compilation without daemon due to error: " else "") + msg.message,
CompilerMessageLocation.NO_LOCATION)
}
@@ -141,37 +152,6 @@ abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
environment: Env
): ExitCode?
protected fun <T> withDaemon(environment: Env, retryOnConnectionError: Boolean, fn: (CompileService, sessionId: Int)->T): T? {
fun retryOrFalse(e: Exception): T? {
if (retryOnConnectionError) {
log.debug("retrying once on daemon connection error: ${e.message}")
return withDaemon(environment, retryOnConnectionError = false, fn = fn)
}
log.info("daemon connection error: ${e.message}")
return null
}
log.debug("Try to connect to daemon")
val connection = getDaemonConnection(environment)
if (connection.daemon != null) {
log.info("Connected to daemon")
try {
return fn(connection.daemon, connection.sessionId)
}
catch (e: java.rmi.ConnectException) {
return retryOrFalse(e)
}
catch (e: java.rmi.UnmarshalException) {
return retryOrFalse(e)
}
}
log.info("Daemon not found")
return null
}
protected fun exitCodeFromProcessExitCode(code: Int): ExitCode {
val exitCode = ExitCode.values().find { it.code == code }
if (exitCode != null) return exitCode