Race condition in Mark Occurrences
It looks like the global index caching in Mark Occurrences can lead to requests being executed in an outdated compiler. The `index` has a compiler instance as field, but that can become outdated if the presentation compiler has been restarted in the mean time.
It should be easy to check if the compiler is up-to-date inside `getCachedIndex`:
It should be easy to check if the compiler is up-to-date inside `getCachedIndex`:
def getCachedIndex(lastModified: Long): Option[MarkOccurrencesIndex] = indexCache match {
case Some(TimestampedIndex(`lastModified`, index)) => Some(index) // check that the compiler is the same!
case _ => None
}
java.lang.AssertionError: assertion failed: Race condition detected: You are running a presentation compiler method outside the PC thread.[phase: <no phase>] Please file a ticket with the current stack trace at https://www.assembla.com/spaces/scala-ide/support/tickets
at scala.Predef$.assert(Predef.scala:179)
at scala.tools.nsc.Global.assert(Global.scala:238)
at scala.tools.nsc.interactive.Global.assertCorrectThread(Global.scala:448)
at scala.reflect.internal.Symbols$Symbol.rawInfo(Symbols.scala:1288)
at scala.reflect.internal.Symbols$Symbol.flatOwnerInfo(Symbols.scala:1964)
at scala.reflect.internal.Symbols$Symbol.companionClass(Symbols.scala:1925)
at scala.reflect.internal.Symbols$TermSymbol.companionSymbol(Symbols.scala:2402)
at scala.tools.refactoring.analysis.DependentSymbolExpanders$Companion$class.expand(SymbolExpanders.scala:65)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$$anon$1.scala$tools$refactoring$analysis$DependentSymbolExpanders$LazyValAccessor$$super$expand(GlobalIndexes.scala:24)
at scala.tools.refactoring.analysis.DependentSymbolExpanders$LazyValAccessor$class.expand(SymbolExpanders.scala:74)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$$anon$1.scala$tools$refactoring$analysis$DependentSymbolExpanders$OverridesInClassHierarchy$$super$expand(GlobalIndexes.scala:24)
at scala.tools.refactoring.analysis.DependentSymbolExpanders$OverridesInClassHierarchy$class.expand(SymbolExpanders.scala:82)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$$anon$1.scala$tools$refactoring$analysis$DependentSymbolExpanders$SameSymbolPosition$$super$expand(GlobalIndexes.scala:24)
at scala.tools.refactoring.analysis.DependentSymbolExpanders$SameSymbolPosition$class.expand(SymbolExpanders.scala:133)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$$anon$1.expand(GlobalIndexes.scala:24)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$$anonfun$expandSymbols$1$1.apply(GlobalIndexes.scala:66)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$$anonfun$expandSymbols$1$1.apply(GlobalIndexes.scala:66)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.List.foreach(List.scala:309)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$class.expandSymbols$1(GlobalIndexes.scala:66)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$class.expandSymbol(GlobalIndexes.scala:69)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$$anon$1.expandSymbol(GlobalIndexes.scala:24)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$class.occurences(GlobalIndexes.scala:73)
at scala.tools.refactoring.analysis.GlobalIndexes$GlobalIndex$$anon$1.occurences(GlobalIndexes.scala:24)
at scala.tools.refactoring.implementations.MarkOccurrences.scala$tools$refactoring$implementations$MarkOccurrences$$occurrencesForSymbol$1(MarkOccurrences.scala:23)
at scala.tools.refactoring.implementations.MarkOccurrences$$anonfun$2.apply(MarkOccurrences.scala:66)
at scala.tools.refactoring.implementations.MarkOccurrences$$anonfun$2.apply(MarkOccurrences.scala:32)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.List.foreach(List.scala:309)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at scala.tools.refactoring.implementations.MarkOccurrences.occurrencesOf(MarkOccurrences.scala:32)
at scala.tools.eclipse.markoccurrences.ScalaOccurrencesFinder$$anonfun$findOccurrences$1$$anonfun$apply$4.apply(ScalaOccurrencesFinder.scala:62)
at scala.tools.eclipse.markoccurrences.ScalaOccurrencesFinder$$anonfun$findOccurrences$1$$anonfun$apply$4.apply(ScalaOccurrencesFinder.scala:60)
at scala.tools.nsc.util.InterruptReq.execute(InterruptReq.scala:26)
at scala.tools.nsc.interactive.Global.pollForWork(Global.scala:336)
at scala.tools.nsc.interactive.PresentationCompilerThread.run(PresentationCompilerThread.scala:22)
Leave a comment
on 2012-11-01 09:49 *
By Iulian Dragos
Description changed from It looks like the global in... to It looks like the global in...
Shoudl we look at this by Helium or M3?
on 2012-11-26 13:22 *
By Mirco Dotta
Yep, this is reallhy annoying, I'm hitting it all the times.
The temporary fix is a one-liner. I'll look into it (invalidate the cache more often).
(In scala-ide:f20d25fc0c9bfa719e7617349736f25bd5c5becf) Don't reuse a MarkOccurrences index if the global instance is not current anymore.
Cached indexes may survive longer than a presentation compiler (for instance, when compiler settings are
changed the presentation compiler restarts). This leads to wrong accesses to a "dead" compiler while using
the index.
Also switched to a weak reference in the cache. If there are many editors open, this can lead to
significant memory consumption (especially when the compiler is out-dated). Note that this is not
a memory leak, in the sense it won't grow unboundedly. As an optimization, we prefer to recompute
the index if the VM decides it needed to collect the index, instead of holding large chunks of
heap in the hope that it will still be useful.
Fixed #1001303.
Branch: master
Cached indexes may survive longer than a presentation compiler (for instance, when compiler settings are
changed the presentation compiler restarts). This leads to wrong accesses to a "dead" compiler while using
the index.
Also switched to a weak reference in the cache. If there are many editors open, this can lead to
significant memory consumption (especially when the compiler is out-dated). Note that this is not
a memory leak, in the sense it won't grow unboundedly. As an optimization, we prefer to recompute
the index if the VM decides it needed to collect the index, instead of holding large chunks of
heap in the hope that it will still be useful.
Fixed #1001303.
Branch: master