From a41c2d759a480aea85c3e5e3f7b6719bb0a7a72b Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Mon, 29 Oct 2018 20:59:13 +0300 Subject: [PATCH] Avoid catching exceptions from workers in GradleKotlinCompilerRunner Exceptions were catched in `KotlinCompilerRunner.runCompiler`. When the method from superclass is not used in `GradleKotlinCompilerRunner`, the superclass does not make much sense anymore, so I turned it into util object. --- .../compilerRunner/KotlinCompilerRunner.kt | 144 ------------------ .../KotlinCompilerRunnerUtils.kt | 103 +++++++++++++ .../kotlin/compilerRunner/KotlinLogger.kt | 15 ++ .../compilerRunner/JpsKotlinCompilerRunner.kt | 20 ++- .../GradleKotlinCompilerRunner.kt | 12 +- 5 files changed, 138 insertions(+), 156 deletions(-) delete mode 100644 compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt create mode 100644 compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunnerUtils.kt create mode 100644 compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinLogger.kt diff --git a/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt deleted file mode 100644 index 03560bb0753..00000000000 --- a/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.compilerRunner - -import org.jetbrains.kotlin.cli.common.ExitCode -import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -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.DaemonReportMessage -import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets -import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient -import org.jetbrains.kotlin.daemon.common.* -import java.io.BufferedReader -import java.io.ByteArrayOutputStream -import java.io.File -import java.io.StringReader -import java.util.* -import java.util.concurrent.TimeUnit - -interface KotlinLogger { - fun error(msg: String) - fun warn(msg: String) - fun info(msg: String) - fun debug(msg: String) - - val isDebugEnabled: Boolean -} - -abstract class KotlinCompilerRunner { - protected val INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString() - - protected abstract val log: KotlinLogger - - protected open fun runCompiler( - compilerClassName: String, - compilerArgs: CommonCompilerArguments, - environment: Env - ) { - try { - compileWithDaemonOrFallback(compilerClassName, compilerArgs, environment) - } catch (e: Throwable) { - MessageCollectorUtil.reportException(environment.messageCollector, e) - reportInternalCompilerError(environment.messageCollector) - } - } - - protected abstract fun compileWithDaemonOrFallback( - compilerClassName: String, - compilerArgs: CommonCompilerArguments, - environment: Env - ) - - protected fun exitCodeFromProcessExitCode(code: Int): ExitCode = Companion.exitCodeFromProcessExitCode(log, code) - - companion object { - fun exitCodeFromProcessExitCode(log: KotlinLogger, code: Int): ExitCode { - val exitCode = ExitCode.values().find { it.code == code } - if (exitCode != null) return exitCode - - log.debug("Could not find exit code by value: $code") - return if (code == 0) ExitCode.OK else ExitCode.COMPILATION_ERROR - } - - @Synchronized - @JvmStatic - protected fun newDaemonConnection( - compilerId: CompilerId, - clientAliveFlagFile: File, - sessionAliveFlagFile: File, - messageCollector: MessageCollector, - isDebugEnabled: Boolean, - daemonOptions: DaemonOptions = configureDaemonOptions(), - additionalJvmParams: Array = arrayOf() - ): CompileServiceSession? { - val daemonJVMOptions = configureDaemonJVMOptions( - additionalParams = *additionalJvmParams, - inheritMemoryLimits = true, - inheritOtherJvmOptions = false, - inheritAdditionalProperties = true - ) - - val daemonReportMessages = ArrayList() - val daemonReportingTargets = DaemonReportingTargets(messages = daemonReportMessages) - - val profiler = if (daemonOptions.reportPerf) WallAndThreadAndMemoryTotalProfiler(withGC = false) else DummyProfiler() - - val connection = profiler.withMeasure(null) { - KotlinCompilerClient.connectAndLease( - compilerId, - clientAliveFlagFile, - daemonJVMOptions, - daemonOptions, - daemonReportingTargets, - autostart = true, - leaseSession = true, - sessionAliveFlagFile = sessionAliveFlagFile - ) - } - - if (connection == null || isDebugEnabled) { - for (message in daemonReportMessages) { - val severity = when (message.category) { - DaemonReportCategory.DEBUG -> CompilerMessageSeverity.INFO - DaemonReportCategory.INFO -> CompilerMessageSeverity.INFO - DaemonReportCategory.EXCEPTION -> CompilerMessageSeverity.EXCEPTION - } - messageCollector.report(severity, message.message) - } - } - - fun reportTotalAndThreadPerf( - message: String, daemonOptions: DaemonOptions, messageCollector: MessageCollector, profiler: Profiler - ) { - if (daemonOptions.reportPerf) { - fun Long.ms() = TimeUnit.NANOSECONDS.toMillis(this) - val counters = profiler.getTotalCounters() - messageCollector.report( - CompilerMessageSeverity.INFO, "PERF: $message ${counters.time.ms()} ms, thread ${counters.threadTime.ms()}" - ) - } - } - - reportTotalAndThreadPerf("Daemon connect", daemonOptions, MessageCollector.NONE, profiler) - return connection - } - } -} - diff --git a/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunnerUtils.kt b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunnerUtils.kt new file mode 100644 index 00000000000..deb698eee13 --- /dev/null +++ b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunnerUtils.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.compilerRunner + +import org.jetbrains.kotlin.cli.common.ExitCode +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import org.jetbrains.kotlin.daemon.client.CompileServiceSession +import org.jetbrains.kotlin.daemon.client.DaemonReportMessage +import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets +import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient +import org.jetbrains.kotlin.daemon.common.* +import java.io.File +import java.util.* +import java.util.concurrent.TimeUnit + +object KotlinCompilerRunnerUtils { + fun exitCodeFromProcessExitCode(log: KotlinLogger, code: Int): ExitCode { + val exitCode = ExitCode.values().find { it.code == code } + if (exitCode != null) return exitCode + + log.debug("Could not find exit code by value: $code") + return if (code == 0) ExitCode.OK else ExitCode.COMPILATION_ERROR + } + + @Synchronized + @JvmStatic + fun newDaemonConnection( + compilerId: CompilerId, + clientAliveFlagFile: File, + sessionAliveFlagFile: File, + messageCollector: MessageCollector, + isDebugEnabled: Boolean, + daemonOptions: DaemonOptions = configureDaemonOptions(), + additionalJvmParams: Array = arrayOf() + ): CompileServiceSession? { + val daemonJVMOptions = configureDaemonJVMOptions( + additionalParams = *additionalJvmParams, + inheritMemoryLimits = true, + inheritOtherJvmOptions = false, + inheritAdditionalProperties = true + ) + + val daemonReportMessages = ArrayList() + val daemonReportingTargets = DaemonReportingTargets(messages = daemonReportMessages) + + val profiler = if (daemonOptions.reportPerf) WallAndThreadAndMemoryTotalProfiler(withGC = false) else DummyProfiler() + + val connection = profiler.withMeasure(null) { + KotlinCompilerClient.connectAndLease( + compilerId, + clientAliveFlagFile, + daemonJVMOptions, + daemonOptions, + daemonReportingTargets, + autostart = true, + leaseSession = true, + sessionAliveFlagFile = sessionAliveFlagFile + ) + } + + if (connection == null || isDebugEnabled) { + for (message in daemonReportMessages) { + val severity = when (message.category) { + DaemonReportCategory.DEBUG -> CompilerMessageSeverity.INFO + DaemonReportCategory.INFO -> CompilerMessageSeverity.INFO + DaemonReportCategory.EXCEPTION -> CompilerMessageSeverity.EXCEPTION + } + messageCollector.report(severity, message.message) + } + } + + fun reportTotalAndThreadPerf( + message: String, daemonOptions: DaemonOptions, messageCollector: MessageCollector, profiler: Profiler + ) { + if (daemonOptions.reportPerf) { + fun Long.ms() = TimeUnit.NANOSECONDS.toMillis(this) + val counters = profiler.getTotalCounters() + messageCollector.report( + CompilerMessageSeverity.INFO, "PERF: $message ${counters.time.ms()} ms, thread ${counters.threadTime.ms()}" + ) + } + } + + reportTotalAndThreadPerf("Daemon connect", daemonOptions, MessageCollector.NONE, profiler) + return connection + } +} + diff --git a/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinLogger.kt b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinLogger.kt new file mode 100644 index 00000000000..d70ec3c1b24 --- /dev/null +++ b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinLogger.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.compilerRunner + +interface KotlinLogger { + fun error(msg: String) + fun warn(msg: String) + fun info(msg: String) + fun debug(msg: String) + + val isDebugEnabled: Boolean +} \ No newline at end of file diff --git a/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/JpsKotlinCompilerRunner.kt b/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/JpsKotlinCompilerRunner.kt index ad01c5fbd7d..4d8cc2b9566 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/JpsKotlinCompilerRunner.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/JpsKotlinCompilerRunner.kt @@ -21,6 +21,7 @@ import org.jetbrains.jps.api.GlobalOptions import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY import org.jetbrains.kotlin.cli.common.arguments.* +import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil import org.jetbrains.kotlin.config.CompilerSettings import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.config.additionalArgumentsAsList @@ -32,8 +33,8 @@ import java.io.ByteArrayOutputStream import java.io.File import java.io.PrintStream -class JpsKotlinCompilerRunner : KotlinCompilerRunner() { - override val log: KotlinLogger = JpsKotlinLogger(KotlinBuilder.LOG) +class JpsKotlinCompilerRunner { + private val log: KotlinLogger = JpsKotlinLogger(KotlinBuilder.LOG) private var compilerSettings: CompilerSettings? = null @@ -153,7 +154,7 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner() { } } - override fun compileWithDaemonOrFallback( + private fun compileWithDaemonOrFallback( compilerClassName: String, compilerArgs: CommonCompilerArguments, environment: JpsCompilerEnvironment @@ -166,6 +167,15 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner() { ) } + private fun runCompiler(compilerClassName: String, compilerArgs: CommonCompilerArguments, environment: JpsCompilerEnvironment) { + try { + compileWithDaemonOrFallback(compilerClassName, compilerArgs, environment) + } catch (e: Throwable) { + MessageCollectorUtil.reportException(environment.messageCollector, e) + reportInternalCompilerError(environment.messageCollector) + } + } + private fun compileWithDaemon( compilerClassName: String, compilerArgs: CommonCompilerArguments, @@ -311,7 +321,7 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner() { } private fun getReturnCodeFromObject(rc: Any?): String = when { - rc == null -> INTERNAL_ERROR + rc == null -> ExitCode.INTERNAL_ERROR.toString() ExitCode::class.java.name == rc::class.java.name -> rc.toString() else -> throw IllegalStateException("Unexpected return: " + rc) } @@ -333,7 +343,7 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner() { environment.withProgressReporter { progress -> progress.progress("connecting to daemon") - newDaemonConnection( + KotlinCompilerRunnerUtils.newDaemonConnection( compilerId, clientFlagFile, sessionFlagFile, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index 1f199c39c3b..df9cf629ff6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -50,9 +50,7 @@ const val COULD_NOT_CONNECT_TO_DAEMON_MESSAGE = "Could not connect to Kotlin com internal fun kotlinCompilerExecutionStrategy(): String = System.getProperty(KOTLIN_COMPILER_EXECUTION_STRATEGY_PROPERTY) ?: DAEMON_EXECUTION_STRATEGY -internal open class GradleCompilerRunner(protected val project: Project) : KotlinCompilerRunner() { - override val log = GradleKotlinLogger(project.logger) - +internal open class GradleCompilerRunner(protected val project: Project) { fun runJvmCompiler( sourcesToCompile: List, commonSources: List, @@ -106,7 +104,7 @@ internal open class GradleCompilerRunner(protected val project: Project) : Kotli return runCompiler(KotlinCompilerClass.METADATA, args, environment) } - override fun runCompiler( + private fun runCompiler( compilerClassName: String, compilerArgs: CommonCompilerArguments, environment: GradleCompilerEnvironment @@ -118,10 +116,10 @@ internal open class GradleCompilerRunner(protected val project: Project) : Kotli ) compilerArgs.version = false } - super.runCompiler(compilerClassName, compilerArgs, environment) + compileWithDaemonOrFallback(compilerClassName, compilerArgs, environment) } - override fun compileWithDaemonOrFallback( + protected open fun compileWithDaemonOrFallback( compilerClassName: String, compilerArgs: CommonCompilerArguments, environment: GradleCompilerEnvironment @@ -148,7 +146,7 @@ internal open class GradleCompilerRunner(protected val project: Project) : Kotli isDebugEnabled: Boolean ): CompileServiceSession? { val compilerId = CompilerId.makeCompilerId(compilerFullClasspath) - return newDaemonConnection( + return KotlinCompilerRunnerUtils.newDaemonConnection( compilerId, clientIsAliveFlagFile, sessionIsAliveFlagFile, messageCollector = messageCollector, isDebugEnabled = isDebugEnabled