[jira] [Comment Edited] (JDO-856) TCK hangs on query.conf

2026-01-12 Thread Jira


[ 
https://issues.apache.org/jira/browse/JDO-856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18048990#comment-18048990
 ] 

Tilmann Zäschke edited comment on JDO-856 at 1/12/26 11:08 PM:
---

Update: this branch contains a small(-ish) example that reproduces the problem: 
[GitHub link|https://github.com/tzaeschke/jdo-856-test]. The relevant test is 
{{{}MiniTest{}}}.


was (Author: tilmannz):
Update: this branch contains a small(-ish) example that reproduces the problem: 
[GitHub link|https://github.com/tzaeschke/jdo-856-test/tree/no-sample-query]. 
The relevant test is {{{}MiniTest{}}}.

> TCK hangs on query.conf
> ---
>
> Key: JDO-856
> URL: https://issues.apache.org/jira/browse/JDO-856
> Project: JDO
>  Issue Type: Bug
>  Components: tck
>Affects Versions: JDO 3.2.1
>Reporter: Tilmann Zäschke
>Priority: Major
> Attachments: tck-1-reduced.txt, tck-2-reduced.txt
>
>
> Running the TCK on my machine (windows 11, Java 1.8), consistently hangs in 
> query.conf.
> The tests do not hang on Ubuntu 22 on the same machine.
> The issue can be fixed by disabling some of the concurrent executions.
> Reproduce:
> {{mvn install -Djdo.tck.cfglist="query.conf"}}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)


[jira] [Comment Edited] (JDO-856) TCK hangs on query.conf

2026-01-06 Thread Michael Bouschen (Jira)


[ 
https://issues.apache.org/jira/browse/JDO-856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18048427#comment-18048427
 ] 

Michael Bouschen edited comment on JDO-856 at 1/6/26 7:18 PM:
--

+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:
{code:java}
protected void localSetUp() {
  addTearDownClass(CompanyModelReader.getTearDownClasses());
  loadAndPersistCompanyModel(getPM());
  QCompany.candidate();
  QDentalInsurance.candidate();
  QDepartment.candidate();
  QEmployee.candidate();
  QFullTimeEmployee.candidate();
  QInsurance.candidate();
  QMedicalInsurance.candidate();
  QMeetingRoom.candidate();
  QPerson.candidate();
  QProject.candidate();
}{code}
+*Proposed solutions*+

1) We could try to introduce some kind of locking, for example, all 
constructors could move their initialization (calling other constructors) into 
a synchronized block that synchronizes on a common object, for example on the 
ExpressionImpl.class object:
{code:java}
synchronized (ExpressionImpl.class) {
    // call other Q-classes here
}{code}
This would be relatively easy to implement, but would require (multiple) thread 
synchronization(s) whenever a Q-class is instantiated. This synchronized block 
would need to go into every constructor in the class hierarchy.

2) Another solution might be to have candidate() only return a simple instance 
of the desired class. The query engine would need to be modified to create/fill 
in Q-classes into fields on demand while traversing the query result. It is not 
clear whether this is possible and would require a significant refactoring.

 

 


was (Author: tilmannz):
+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:
{code:java}
protected void localSetUp() {
  addTearDownClass(CompanyModelReader.getTearDownClasses());
  loadAndPersistCompanyModel(getPM());
  QCompany.candidate();
  QDentalInsurance.candidate();
  QDepartment.candidate();
  QEmployee.candidate();
  QFullTimeEmployee.candidate();
  QInsurance.candidate();
  QMedicalInsurance.candidate();
  QMeetingRoom.candidate();
  QPerson.candidate();
  QProject.candida

[jira] [Comment Edited] (JDO-856) TCK hangs on query.conf

2026-01-06 Thread Michael Bouschen (Jira)


[ 
https://issues.apache.org/jira/browse/JDO-856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18048427#comment-18048427
 ] 

Michael Bouschen edited comment on JDO-856 at 1/6/26 7:17 PM:
--

+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:
{code:java}
protected void localSetUp() {
  addTearDownClass(CompanyModelReader.getTearDownClasses());
  loadAndPersistCompanyModel(getPM());
  QCompany.candidate();
  QDentalInsurance.candidate();
  QDepartment.candidate();
  QEmployee.candidate();
  QFullTimeEmployee.candidate();
  QInsurance.candidate();
  QMedicalInsurance.candidate();
  QMeetingRoom.candidate();
  QPerson.candidate();
  QProject.candidate();
}{code}
{{{}{}}}{+}*Proposed solutions*{+}

1) We could try to introduce some kind of locking, for example, all 
constructors could move their initialization (calling other constructors) into 
a synchronized block that synchronizes on a common object, for example on the 
ExpressionImpl.class object:
{code:java}
synchronized (ExpressionImpl.class) {
    // call other Q-classes here
}{code}
This would be relatively easy to implement, but would require (multiple) thread 
synchronization(s) whenever a Q-class is instantiated. This synchronized block 
would need to go into every constructor in the class hierarchy.

2) Another solution might be to have candidate() only return a simple instance 
of the desired class. The query engine would need to be modified to create/fill 
in Q-classes into fields on demand while traversing the query result. It is not 
clear whether this is possible and would require a significant refactoring.

 

 


was (Author: tilmannz):
+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:
{code:java}
protected void localSetUp() {
  addTearDownClass(CompanyModelReader.getTearDownClasses());
  loadAndPersistCompanyModel(getPM());
  QCompany.candidate();
  QDentalInsurance.candidate();
  QDepartment.candidate();
  QEmployee.candidate();
  QFullTimeEmployee.candidate();
  QInsurance.candidate();
  QMedicalInsurance.candidate();
  QMeetingRoom.candidate();
  QPerson.candidate();
  QPro

[jira] [Comment Edited] (JDO-856) TCK hangs on query.conf

2026-01-06 Thread Michael Bouschen (Jira)


[ 
https://issues.apache.org/jira/browse/JDO-856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18048427#comment-18048427
 ] 

Michael Bouschen edited comment on JDO-856 at 1/6/26 7:16 PM:
--

+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:
{code:java}
protected void localSetUp() {
  addTearDownClass(CompanyModelReader.getTearDownClasses());
  loadAndPersistCompanyModel(getPM());
  QCompany.candidate();
  QDentalInsurance.candidate();
  QDepartment.candidate();
  QEmployee.candidate();
  QFullTimeEmployee.candidate();
  QInsurance.candidate();
  QMedicalInsurance.candidate();
  QMeetingRoom.candidate();
  QPerson.candidate();
  QProject.candidate();
}{code}
{{{}{color:#cc7832}
{color}{}}}Proposed solutions

1) We could try to introduce some kind of locking, for example, all 
constructors could move their initialization (calling other constructors) into 
a synchronized block that synchronizes on a common object, for example on the 
ExpressionImpl.class object:


{code:java}
synchronized (ExpressionImpl.class) {
    // call other Q-classes here
}{code}
This would be relatively easy to implement, but would require (multiple) thread 
synchronization(s) whenever a Q-class is instantiated. This synchronized block 
would need to go into every constructor in the class hierarchy.

2) Another solution might be to have candidate() only return a simple instance 
of the desired class. The query engine would need to be modified to create/fill 
in Q-classes into fields on demand while traversing the query result. It is not 
clear whether this is possible and would require a significant refactoring.

 

 


was (Author: tilmannz):
+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:
{code:java}
protected void localSetUp() {
  addTearDownClass(CompanyModelReader.getTearDownClasses());
  loadAndPersistCompanyModel(getPM());
  QCompany.candidate();
  QDentalInsurance.candidate();
  QDepartment.candidate();
  QEmployee.candidate();
  QFullTimeEmployee.candidate();
  QInsurance.candidate();
  QMedicalInsurance.candidate();
  QMeetingRoom.candidate();
  QPerson.ca

[jira] [Comment Edited] (JDO-856) TCK hangs on query.conf

2026-01-06 Thread Michael Bouschen (Jira)


[ 
https://issues.apache.org/jira/browse/JDO-856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18048427#comment-18048427
 ] 

Michael Bouschen edited comment on JDO-856 at 1/6/26 7:14 PM:
--

+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:
{code:java}
protected void localSetUp() {
  addTearDownClass(CompanyModelReader.getTearDownClasses());
  loadAndPersistCompanyModel(getPM());
  QCompany.candidate();
  QDentalInsurance.candidate();
  QDepartment.candidate();
  QEmployee.candidate();
  QFullTimeEmployee.candidate();
  QInsurance.candidate();
  QMedicalInsurance.candidate();
  QMeetingRoom.candidate();
  QPerson.candidate();
  QProject.candidate();
}{code}
{{{color:#cc7832}
+*Proposed solutions*+

1) We could try to introduce some kind of locking, for example, all 
constructors could move their initialization (calling other constructors) into 
a synchronized block that synchronizes on a common object, for example on the 
ExpressionImpl.class object:

synchronized {color}(ExpressionImpl.{color:#cc7832}class{color}) {}}
{{{color:#9876aa}    // call other Q-classes here{color}}}
{{}}}

{{This would be relatively easy to implement, but would require (multiple) 
thread synchronization(s) whenever a Q-class is instantiated. This synchronized 
block would need to go into every constructor in the class hierarchy.}}

2) Another solution might be to have candidate() only return a simple instance 
of the desired class. The query engine would need to be modified to create/fill 
in Q-classes into fields on demand while traversing the query result. It is not 
clear whether this is possible and would require a significant refactoring.

 

 


was (Author: tilmannz):
+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:

{{{}{color:#cc7832}protected void {color}{color:#ffc66d}localSetUp{color}() 
{{}}}}}{}}}
{{  addTearDownClass(CompanyModelReader.getTearDownClasses()){color:#cc7832};
{color}{color:#cc7832}  
{color}loadAndPersistCompanyModel(getPM()){color:#cc7832};
{color}{color:#cc7832}  {color}QCompany.candidate(){color:#cc7832};
{color}{color:#cc783

[jira] [Comment Edited] (JDO-856) TCK hangs on query.conf

2026-01-04 Thread Jira


[ 
https://issues.apache.org/jira/browse/JDO-856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18048990#comment-18048990
 ] 

Tilmann Zäschke edited comment on JDO-856 at 1/4/26 7:21 PM:
-

Update: this branch contains a small(-ish) example that reproduces the problem: 
[GitHub link|https://github.com/tzaeschke/jdo-856-test/tree/no-sample-query]. 
The relevant test is {{{}MiniTest{}}}.


was (Author: tilmannz):
Update: this branch contains a small(-ish) example that reproduces the problem: 
[GitHub link|https://github.com/tzaeschke/jdo-856-test/branches]. The relevant 
test is {{{}MiniTest{}}}.

> TCK hangs on query.conf
> ---
>
> Key: JDO-856
> URL: https://issues.apache.org/jira/browse/JDO-856
> Project: JDO
>  Issue Type: Bug
>  Components: tck
>Affects Versions: JDO 3.2.1
>Reporter: Tilmann Zäschke
>Priority: Major
> Attachments: tck-1-reduced.txt, tck-2-reduced.txt
>
>
> Running the TCK on my machine (windows 11, Java 1.8), consistently hangs in 
> query.conf.
> The tests do not hang on Ubuntu 22 on the same machine.
> The issue can be fixed by disabling some of the concurrent executions.
> Reproduce:
> {{mvn install -Djdo.tck.cfglist="query.conf"}}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)


[jira] [Comment Edited] (JDO-856) TCK hangs on query.conf

2025-12-30 Thread Jira


[ 
https://issues.apache.org/jira/browse/JDO-856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18048427#comment-18048427
 ] 

Tilmann Zäschke edited comment on JDO-856 at 12/30/25 8:03 PM:
---

+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:

{{{}{color:#cc7832}protected void {color}{color:#ffc66d}localSetUp{color}() 
{{}}}}}{}}}
{{  addTearDownClass(CompanyModelReader.getTearDownClasses()){color:#cc7832};
{color}{color:#cc7832}  
{color}loadAndPersistCompanyModel(getPM()){color:#cc7832};
{color}{color:#cc7832}  {color}QCompany.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QDentalInsurance.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QDepartment.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QEmployee.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QFullTimeEmployee.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QInsurance.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QMedicalInsurance.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QMeetingRoom.candidate(){color:#cc7832};
{color}}}{{{color:#cc7832}  {color}QPerson.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QProject.candidate(){color:#cc7832};
{{}}}

+*Proposed solutions*+

1) We could try to introduce some kind of locking, for example, all 
constructors could move their initialization (calling other constructors) into 
a synchronized block that synchronizes on a common object, for example on the 
ExpressionImpl.class object:

synchronized {color}(ExpressionImpl.{color:#cc7832}class{color}) {}}
{{{color:#9876aa}    // call other Q-classes here{color}}}
{{}}}

{{This would be relatively easy to implement, but would require (multiple) 
thread synchronization(s) whenever a Q-class is instantiated. This synchronized 
block would need to go into every constructor in the class hierarchy.}}

2) Another solution might be to have candidate() only return a simple instance 
of the desired class. The query engine would need to be modified to create/fill 
in Q-classes into fields on demand while traversing the query result. It is not 
clear whether this is possible and would require a significant refactoring.

 

 


was (Author: tilmannz):
+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

[jira] [Comment Edited] (JDO-856) TCK hangs on query.conf

2025-12-30 Thread Jira


[ 
https://issues.apache.org/jira/browse/JDO-856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18048427#comment-18048427
 ] 

Tilmann Zäschke edited comment on JDO-856 at 12/30/25 8:02 PM:
---

+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
{{org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries}}
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A workaround is to perform static initialization before executing tests. As 
expected, the following changes (calling candidate() for each class) to the 
SampleReadQueries test fixes the problem:

{{{}{color:#cc7832}protected void {color}{color:#ffc66d}localSetUp{color}() 
{{}}}{{{}{}}}
{{  addTearDownClass(CompanyModelReader.getTearDownClasses()){color:#cc7832};
{color}{color:#cc7832}  
{color}loadAndPersistCompanyModel(getPM()){color:#cc7832};
{color}{color:#cc7832}  {color}QCompany.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QDentalInsurance.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QDepartment.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QEmployee.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QFullTimeEmployee.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QInsurance.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QMedicalInsurance.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QMeetingRoom.candidate(){color:#cc7832};
{color}}}{{{color:#cc7832}  {color}QPerson.candidate(){color:#cc7832};
{color}{color:#cc7832}  {color}QProject.candidate(){color:#cc7832};
{{}}}

+*Proposed solutions*+

1) We could try to introduce some kind of locking, for example, all 
constructors could move their initialization (calling other constructors) into 
a synchronized block that synchronizes on a common object, for example on the 
ExpressionImpl.class object:

synchronized {color}(ExpressionImpl.{color:#cc7832}class{color}) {}}
{{{color:#9876aa}    // call other Q-classes here{color}}}
{{}}}

{{This would be relatively easy to implement, but would require (multiple) 
thread synchronization(s) whenever a Q-class is instantiated. This synchronized 
block would need to go into every constructor in the class hierarchy.}}

2) Another solution might be to have candidate() only return a simple instance 
of the desired class. The query engine would need to be modified to create/fill 
in Q-classes into fields on demand while traversing the query result. It is not 
clear whether this is possible and would require a significant refactoring.

 

 


was (Author: tilmannz):
+*Summary*+

It appears that the initialization of Q-classes in the reference implementation 
is not thread-safe. 

Reproduce:
The likelihood of the problem occuring correlates with the number of CPU cores 
of the test environment.
On a is only reproducible on Multicore CPU. It is reliably reproducible on my 
AMD Ryzen 7 7700 (8 cores / 16 Threads).
The minimum configuration is running the following two tests, where it will 
hang indefinitely in the second test:
org.apache.jdo.tck.query.api.QueryExtentions \
org.apache.jdo.tck.query.api.SampleReadQueries
JUnit appears to be starting about 20 worker threads.

+*Analysis*+

I created stack trace dumps from two hanging runs, they are attached, see  
[^tck-1-reduced.txt] and [^tck-2-reduced.txt]. I removed all unrelated stack 
entries outside the calls to the test methods.
The stack traces show that 18 threads hang while trying to call the 
candidate(...) method of a Q class. Two threads hang inside the Q-classes, 
inside a chain of constructor calls, while calling the static initialization of 
another Q-class.

Static initialization of classes is implicitly synchronized on the class 
object. It appears that the concurrent calling of class initialization causes a 
dead-lock.

+*Workaround*+

A wor