-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix deadlock in lazy intialization of CoreBTypes #19297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix deadlock in lazy intialization of CoreBTypes #19297
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will fix the deadlock, indeed. However, it can introduce other issues. If two threads try access the same @threadUnsafe lazy val
, even if the initialization code is protected, the assignment to the field and the bitmap will not be protected. Although unlikely, this can lead to NPEs if another thread sees the updated bitmap while not seeing the updated actual value. More likely: two threads accessing two different lazy vals of the same object can concurrently try to update the same bitmap, leading to corruption.
Conclusion: @threadUnsafe lazy val
s are thread-unsafe no matter how thread-safe their user-written right-hand-side is.
Usage of
@threadUnsafe lazy val
s makes semantics ofCoreBTypes
initialisation more aligned with Scala 2 backend (threadUnsafe lazy vals is almost identical with Scala2 lazy val)
That is not true. Scala 2 lazy val
s are thread-safe. They just don't use the same mechanism as Scala 3.
Thank you @sjrd! In such case probably we could port the Scala 2 |
Ah yes, that seems to be what we need. |
Replaced with #19298 |
…9298) Replaces #19297 and fixes #19293 The deadlocks are now fixed by introduction of `PostProcessorFrontendAccess.Lazy[T]` container for which initialization is synchronized with the frontend Context, while providing a thread-safe access lacking in original solution. It now also audits where the unrestricted access to context was used and replaces these usages with safer access. Reverts #19292
…ala#19298) Replaces scala#19297 and fixes scala#19293 The deadlocks are now fixed by introduction of `PostProcessorFrontendAccess.Lazy[T]` container for which initialization is synchronized with the frontend Context, while providing a thread-safe access lacking in original solution. It now also audits where the unrestricted access to context was used and replaces these usages with safer access. Reverts scala#19292
…9298) Replaces #19297 and fixes #19293 The deadlocks are now fixed by introduction of `PostProcessorFrontendAccess.Lazy[T]` container for which initialization is synchronized with the frontend Context, while providing a thread-safe access lacking in original solution. It now also audits where the unrestricted access to context was used and replaces these usages with safer access. Reverts #19292 [Cherry-picked 33bdaac][modified]
Fixes #19293 caused by double synchronisation of lazy val initialisation. When
PostProcessor
thread tried to accessCoreBTypesFromSymbols.jliLambdaMetaFactoryAltMetafactoryHandle
inBackendUtils.collectSerializableLambdas
it could have one the data race for initialisation of lazy val with the main GenBCode thread, but it could have failed the synchronisation race withfrontendSynch
leading to deadlock.To fix this issue we use
@threadUnsafe lazy val
so the synchronisation is only based on thefrontendSynch
lock.Usage of
@threadUnsafe lazy val
s makes semantics ofCoreBTypes
initialisation more aligned with Scala 2 backend (threadUnsafe lazy vals is almost identical with Scala2 lazy val)Alternative solution to this issue is to create a PostProcessor/BackendUtils local
jliLambdaMetaFactoryAltMetafactoryHandle
instance using mangled Strings with descriptor which would not use anySymbol
s orContext
, but it seems be more error-prone in the long term maintenance.