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()
|
val oldProperties = setUpSystemProperties()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
+44
@@ -78,6 +78,50 @@ internal abstract class KotlinNativeToolRunner(
|
|||||||
override fun transformArgs(args: List<String>) = listOf(toolName) + args
|
override fun transformArgs(args: List<String>) = listOf(toolName) + args
|
||||||
|
|
||||||
final override fun getCustomJvmArgs() = project.jvmArgs
|
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. */
|
/** 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.
|
* Forces to run a compilation in a separate JVM.
|
||||||
*/
|
*/
|
||||||
val nativeDisableCompilerDaemon: Boolean?
|
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.
|
* 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"
|
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 =
|
operator fun invoke(project: Project): PropertiesProvider =
|
||||||
with(project.extensions.extraProperties) {
|
with(project.extensions.extraProperties) {
|
||||||
if (!has(CACHED_PROVIDER_EXT_NAME)) {
|
if (!has(CACHED_PROVIDER_EXT_NAME)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user