Use a system property to lock in the dependencies downloader (#4255)
Current implementation of synchronization in the dependencies downloader uses a static mutex and a file lock. It doesn't work if compiler instances are started in the same process but in different classloaders (see KT-39450). This patch works around this problem by using a system property instead of a static mutex for synchronization. Issue #KT-39450 fixed
This commit is contained in:
@@ -211,8 +211,6 @@ class DependencyProcessor(dependenciesRoot: File,
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val lock = ReentrantLock()
|
|
||||||
|
|
||||||
val localKonanDir: File by lazy {
|
val localKonanDir: File by lazy {
|
||||||
File(System.getenv("KONAN_DATA_DIR") ?: (System.getProperty("user.home") + File.separator + ".konan"))
|
File(System.getenv("KONAN_DATA_DIR") ?: (System.getProperty("user.home") + File.separator + ".konan"))
|
||||||
}
|
}
|
||||||
@@ -265,17 +263,25 @@ class DependencyProcessor(dependenciesRoot: File,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun run() = lock.withLock {
|
fun run() {
|
||||||
RandomAccessFile(lockFile, "rw").channel.lock().use {
|
// We need a lock that can be shared between different classloaders (KT-39781).
|
||||||
resolvedDependencies.forEach { (dependency, candidate) ->
|
// TODO: Rework dependencies downloading to avoid storing the lock in the system properties.
|
||||||
val baseUrl = when (candidate) {
|
val lock = System.getProperties().computeIfAbsent("kotlin.native.dependencies.lock") {
|
||||||
is DependencySource.Local -> null
|
// String literals are internalized so we create a new instance to avoid synchronization on a shared object.
|
||||||
DependencySource.Remote.Public -> dependenciesUrl
|
java.lang.String("lock")
|
||||||
DependencySource.Remote.Internal -> InternalServer.url
|
}
|
||||||
}
|
synchronized(lock) {
|
||||||
// TODO: consider using different caches for different remotes.
|
RandomAccessFile(lockFile, "rw").channel.lock().use {
|
||||||
if (baseUrl != null) {
|
resolvedDependencies.forEach { (dependency, candidate) ->
|
||||||
downloadDependency(dependency, baseUrl)
|
val baseUrl = when (candidate) {
|
||||||
|
is DependencySource.Local -> null
|
||||||
|
DependencySource.Remote.Public -> dependenciesUrl
|
||||||
|
DependencySource.Remote.Internal -> InternalServer.url
|
||||||
|
}
|
||||||
|
// TODO: consider using different caches for different remotes.
|
||||||
|
if (baseUrl != null) {
|
||||||
|
downloadDependency(dependency, baseUrl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user