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:
Ilya Matveev
2020-06-25 17:59:47 +07:00
committed by GitHub
parent f939232996
commit 7a24e9ea0e
@@ -211,8 +211,6 @@ class DependencyProcessor(dependenciesRoot: File,
}
companion object {
private val lock = ReentrantLock()
val localKonanDir: File by lazy {
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 {
RandomAccessFile(lockFile, "rw").channel.lock().use {
resolvedDependencies.forEach { (dependency, candidate) ->
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)
fun run() {
// We need a lock that can be shared between different classloaders (KT-39781).
// TODO: Rework dependencies downloading to avoid storing the lock in the system properties.
val lock = System.getProperties().computeIfAbsent("kotlin.native.dependencies.lock") {
// String literals are internalized so we create a new instance to avoid synchronization on a shared object.
java.lang.String("lock")
}
synchronized(lock) {
RandomAccessFile(lockFile, "rw").channel.lock().use {
resolvedDependencies.forEach { (dependency, candidate) ->
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)
}
}
}
}