From cc04b72dfd6182d5a6859e2b4b0fff72ec23291a Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 31 May 2018 12:53:10 +0300 Subject: [PATCH] Protect access to SLRUCache for scripts with a lock --- .../idea/caches/resolve/KotlinCacheServiceImpl.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt index bbe82bea9c4..57ca2a1db1e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt @@ -186,6 +186,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { val specialModuleInfo = files.map(KtFile::getModuleInfo).toSet().single() val sdk = specialModuleInfo.sdk val settings = PlatformAnalysisSettings(targetPlatform, sdk, specialModuleInfo.supportsAdditionalBuiltInsMembers()) + // File copies are created during completion and receive correct modification events through POM. // Dummy files created e.g. by J2K do not receive events. val filesModificationTracker = if (files.all { it.originalFile != it }) { @@ -343,7 +344,6 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { false ) - private val specialFileCachesLock = Any() private val specialFilesCacheProvider = CachedValueProvider { // NOTE: computations inside createFacadeForFilesWithSpecialModuleInfo depend on project root structure // so we additionally drop the whole slru cache on change @@ -357,10 +357,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } private fun getFacadeForSpecialFiles(files: Set): ProjectResolutionFacade { - val cachedValue = synchronized(specialFileCachesLock) { + val cachedValue: SLRUCache, ProjectResolutionFacade> = synchronized(specialFilesCacheProvider) { CachedValuesManager.getManager(project).getCachedValue(project, specialFilesCacheProvider) } // In Upsource, we create multiple instances of KotlinCacheService, which all access the same CachedValue instance (UP-8046) + // This is so because class name of provider is used as a key when fetching cached value, see CachedValueManager.getKeyForClass. // To avoid race conditions, we can't use the local lock to access the cached value contents. synchronized(cachedValue) { return cachedValue.get(files) @@ -379,7 +380,13 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } private fun getFacadeForScripts(files: Set): ProjectResolutionFacade { - return CachedValuesManager.getManager(project).getCachedValue(project, scriptsCacheProvider).get(files) + val cachedValue: SLRUCache, ProjectResolutionFacade> = synchronized(scriptsCacheProvider) { + CachedValuesManager.getManager(project).getCachedValue(project, scriptsCacheProvider) + } + + synchronized(cachedValue) { + return cachedValue.get(files) + } } private fun getFacadeToAnalyzeFiles(files: Collection): ResolutionFacade {