Gradle, native: Forbid parallel in-process compiler execution
After enabling the in-process compiler execution, we got several reports related to the race condition that takes place during system properties configuring (e.g. KT-37442, KT-37444, probably KT-37362). The right fix here is to get rid of using system properties at all. But it requires changes in many places of the K/N compiler and such a patch is not safe enough to include it into a bug-fix release. So it's decided to forbid parallel in-process compiler execution in 1.3.71 and 1.4-M2. Issue #KT-37565 Fixed Issue #KT-37696 Fixed Ported from: https://github.com/JetBrains/kotlin/commit/1c1b637cc46012a22867d8e653bb6d94ed6138ba https://github.com/JetBrains/kotlin/commit/2128d3dfe77db4e0a8450f4f943cbd13c2e5dd4d
This commit is contained in:
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.gradle
|
||||
|
||||
import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.junit.Test
|
||||
|
||||
class GeneralNativeIT : BaseGradleIT() {
|
||||
|
||||
@Test
|
||||
fun testParallelExecutionDetection(): Unit = with(transformProjectWithPluginsDsl("native-parallel")) {
|
||||
val compileTasks = arrayOf(":one:compileKotlinLinux", ":two:compileKotlinLinux")
|
||||
// Check that parallel in-process execution fails with the corresponding message.
|
||||
build(*compileTasks) {
|
||||
assertFailed()
|
||||
assertContains("Parallel in-process execution of the Kotlin/Native compiler detected.")
|
||||
}
|
||||
|
||||
// Parallel execution without daemon => ok.
|
||||
build("clean", *compileTasks, "-Pkotlin.native.disableCompilerDaemon=true") {
|
||||
assertSuccessful()
|
||||
assertTasksExecuted(*compileTasks)
|
||||
}
|
||||
|
||||
// org.gradle.parallel must be set in the properties file (not in command line).
|
||||
projectDir.resolve("gradle.properties").modify {
|
||||
it.replace("org.gradle.parallel=true", "org.gradle.parallel=false")
|
||||
}
|
||||
|
||||
// Sequential execution => ok.
|
||||
build("clean", *compileTasks) {
|
||||
assertSuccessful()
|
||||
assertTasksExecuted(*compileTasks)
|
||||
}
|
||||
|
||||
// Check for KT-37696.
|
||||
// Add an incorrect code to trigger compilation failure.
|
||||
projectDir.resolve("one/src/linuxMain/kotlin/main.kt").appendText("\nfun incorrect")
|
||||
gradleBuildScript("two").appendText("""
|
||||
|
||||
val compileKotlinLinux by tasks.getting
|
||||
compileKotlinLinux.mustRunAfter(":one:compileKotlinLinux")
|
||||
""".trimIndent())
|
||||
|
||||
build("clean", *compileTasks, "--continue") {
|
||||
assertFailed()
|
||||
assertTasksFailed(":one:compileKotlinLinux")
|
||||
assertTasksExecuted(":two:compileKotlinLinux")
|
||||
assertNotContains("Parallel in-process execution of the Kotlin/Native compiler detected.")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.multiplatform").version("<pluginMarkerVersion>").apply(false)
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.gradle.parallel=true
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.multiplatform")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
linuxX64("linux")
|
||||
|
||||
sourceSets["commonMain"].dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
fun main() {
|
||||
println(42)
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
include(":one", ":two")
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.multiplatform")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
linuxX64("linux")
|
||||
|
||||
sourceSets["commonMain"].dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
fun main() {
|
||||
println(42)
|
||||
}
|
||||
+2
-1
@@ -90,7 +90,8 @@ internal abstract class KotlinToolRunner(
|
||||
}
|
||||
}
|
||||
|
||||
private fun runInProcess(args: List<String>) {
|
||||
// TODO: Make it private again once KT-37550 is fixed.
|
||||
protected open fun runInProcess(args: List<String>) {
|
||||
val oldProperties = setUpSystemProperties()
|
||||
|
||||
try {
|
||||
|
||||
+44
@@ -78,6 +78,50 @@ internal abstract class KotlinNativeToolRunner(
|
||||
override fun transformArgs(args: List<String>) = listOf(toolName) + args
|
||||
|
||||
final override fun getCustomJvmArgs() = project.jvmArgs
|
||||
|
||||
final override fun runInProcess(args: List<String>) {
|
||||
withParallelExecutionGuard {
|
||||
super.runInProcess(args)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove once KT-37550 is fixed
|
||||
private inline fun withParallelExecutionGuard(action: () -> Unit) {
|
||||
try {
|
||||
if (PropertiesProvider(project).nativeEnableParallelExecutionCheck) {
|
||||
System.getProperties().compute(PARALLEL_EXECUTION_GUARD_PROPERTY) { _, value ->
|
||||
check(value == null) { PARALLEL_EXECUTION_ERROR_MESSAGE }
|
||||
"true"
|
||||
}
|
||||
}
|
||||
|
||||
action()
|
||||
|
||||
} finally {
|
||||
if (PropertiesProvider(project).nativeEnableParallelExecutionCheck) {
|
||||
System.clearProperty(PARALLEL_EXECUTION_GUARD_PROPERTY)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PARALLEL_EXECUTION_GUARD_PROPERTY = "org.jetbrains.kotlin.native.compiler.running"
|
||||
|
||||
private val PARALLEL_EXECUTION_ERROR_MESSAGE = """
|
||||
Parallel in-process execution of the Kotlin/Native compiler detected.
|
||||
|
||||
At this moment the parallel execution of several compiler instances in the same process is not supported.
|
||||
To fix this, you can do one of the following things:
|
||||
|
||||
- Disable in-process execution. To do this, set '${PropertiesProvider.KOTLIN_NATIVE_DISABLE_COMPILER_DAEMON}=true' project property.
|
||||
|
||||
- Disable parallel task execution. To do this, set 'org.gradle.parallel=false' project property.
|
||||
|
||||
If you still want to run the compiler in-process in parallel, you may disable this check by setting project
|
||||
property '${PropertiesProvider.KOTLIN_NATIVE_ENABLE_PARALLEL_EXECUTION_CHECK}=false'. Note that in this case the compiler may fail.
|
||||
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
/** A common ancestor for all runners that run the cinterop tool. */
|
||||
|
||||
+10
-1
@@ -189,7 +189,11 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
* Forces to run a compilation in a separate JVM.
|
||||
*/
|
||||
val nativeDisableCompilerDaemon: Boolean?
|
||||
get() = booleanProperty("kotlin.native.disableCompilerDaemon")
|
||||
get() = booleanProperty(KOTLIN_NATIVE_DISABLE_COMPILER_DAEMON)
|
||||
|
||||
// TODO: Remove once KT-37550 is fixed
|
||||
val nativeEnableParallelExecutionCheck: Boolean
|
||||
get() = booleanProperty(KOTLIN_NATIVE_ENABLE_PARALLEL_EXECUTION_CHECK) ?: true
|
||||
|
||||
/**
|
||||
* Dependencies caching strategy. The default is static.
|
||||
@@ -238,6 +242,11 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
|
||||
private const val CACHED_PROVIDER_EXT_NAME = "kotlin.properties.provider"
|
||||
|
||||
internal const val KOTLIN_NATIVE_DISABLE_COMPILER_DAEMON = "kotlin.native.disableCompilerDaemon"
|
||||
|
||||
// TODO: Remove once KT-37550 is fixed
|
||||
internal const val KOTLIN_NATIVE_ENABLE_PARALLEL_EXECUTION_CHECK = "kotlin.native.enableParallelExecutionCheck"
|
||||
|
||||
operator fun invoke(project: Project): PropertiesProvider =
|
||||
with(project.extensions.extraProperties) {
|
||||
if (!has(CACHED_PROVIDER_EXT_NAME)) {
|
||||
|
||||
Reference in New Issue
Block a user