-
Notifications
You must be signed in to change notification settings - Fork 21
Deadlock with inner object class init #9312
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
Milestone
Comments
Imported From: https://issues.scala-lang.org/browse/SI-9312?orig=1 |
Does anyone have an opinion on if this is working as intended, or is a bug? |
liufengyun
added a commit
to scala/scala3
that referenced
this issue
Jun 16, 2023
The problem is illustrated by the example below: ``` Scala class Foo(val opposite: Foo) case object A extends Foo(B) // A -> B case object B extends Foo(A) // B -> A ``` The check aims to be simple for programmers to understand, expressive, fast, and sound. The check is centered around two design ideas: (1) initialization-time irrelevance; (2) partial ordering. The check enforces the principle of _initialization-time irrelevance_, which means that the time when a static object is initialized should not change program semantics. For that purpose, it enforces the following rule: > **The initialization of a static object should not directly or indirectly read or write mutable state owned by another static object**. This principle not only puts the initialization of static objects on a solid foundation but also avoids whole-program analysis. Partial ordering means that the initialization dependencies of static objects form a directed-acyclic graph (DAG). No cycles with length bigger than 1 allowed --- which might lead to deadlocks in the presence of concurrency and strong coupling & subtle contracts between objects. Related Issues: #16152 #9176 #11262 scala/bug#9312 scala/bug#9115 scala/bug#9261 scala/bug#5366 scala/bug#9360
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When the following program is run, the threads end up in a deadlock.
The deadlock happens because the Child classes are initialized before the Parent. This leads to the following chain of actions:
cinit
, which calls the constructorinit
)val parent
val parent
, but as the class Parent is being inited by thread 1, it waitsval children
, but as the Child2 class is being initied by thread2, it waitsFor me as a programmer, when looking at the syntax, I would expect
Parent.Child1
to mean that we take a reference toParent
, which has a field calledChild1
containing the reference to the singleton objectChild1
. This would ensure that Parent1 is initialized before Child2 can be used. Ofcourse what really happens is that a reference toParent.Child1
just uses theParent1.MODULE$
to get the reference without botherParent
at all. Thus to me this is a bug/design failure in how scala handles inner objects.The text was updated successfully, but these errors were encountered: