[LL FIR] KT-58257 Fix session project leak in invokeLater lambda
- The lambda passed to `invokeLater` in `LLFirSession.invalidate` might survive beyond project disposal (especially in tests), so me must not capture a hard reference to the session that can leak its `project`.
This commit is contained in:
committed by
Space Team
parent
bb92d19b47
commit
edadfd0daa
+19
-7
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
|
||||
@@ -58,8 +59,12 @@ abstract class LLFirSession(
|
||||
"Outside a write action, a session may only be invalidated directly when FIR guards are turned off."
|
||||
}
|
||||
|
||||
// The lambda passed to `invokeLater` might survive beyond project disposal (especially in tests), so me must not capture a hard
|
||||
// reference to `this` that can leak `project`. A weak reference is appropriate because we do not need to invalidate the session
|
||||
// when it has already been collected.
|
||||
val weakSession = WeakReference(this)
|
||||
application.invokeLater(
|
||||
{ application.runWriteAction { invalidateInWriteAction() } },
|
||||
{ weakSession.invalidateIfAlive() },
|
||||
|
||||
// `ModalityState.any()` can be used because session invalidation does not modify PSI, VFS, or the project model.
|
||||
ModalityState.any(),
|
||||
@@ -67,12 +72,6 @@ abstract class LLFirSession(
|
||||
}
|
||||
}
|
||||
|
||||
private fun invalidateInWriteAction() {
|
||||
if (!isValid) return
|
||||
|
||||
LLFirSessionInvalidationService.getInstance(project).invalidate(ktModule)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [ModificationTracker] which tracks the validity of this session via [isValid].
|
||||
*/
|
||||
@@ -93,6 +92,19 @@ abstract class LLFirSession(
|
||||
}
|
||||
}
|
||||
|
||||
private fun LLFirSession.invalidateInWriteAction() {
|
||||
if (!isValid) return
|
||||
|
||||
LLFirSessionInvalidationService.getInstance(project).invalidate(ktModule)
|
||||
}
|
||||
|
||||
private fun WeakReference<LLFirSession>.invalidateIfAlive() = ApplicationManager.getApplication().runWriteAction {
|
||||
val session = get() ?: return@runWriteAction
|
||||
if (session.project.isDisposed) return@runWriteAction
|
||||
|
||||
session.invalidateInWriteAction()
|
||||
}
|
||||
|
||||
abstract class LLFirModuleSession(
|
||||
ktModule: KtModule,
|
||||
builtinTypes: BuiltinTypes,
|
||||
|
||||
Reference in New Issue
Block a user