Bug 552849 - ChainCompletionProposalComputer runs forever in 3 threads without any UI hint
Summary: ChainCompletionProposalComputer runs forever in 3 threads without any UI hint
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.14   Edit
Hardware: All All
: P3 major (vote)
Target Milestone: 4.14 M3   Edit
Assignee: Roland Grunberg CLA
QA Contact: Roland Grunberg CLA
URL:
Whiteboard:
Keywords: regression
Depends on:
Blocks: 549753
  Show dependency tree
 
Reported: 2019-11-08 10:50 EST by Andrey Loskutov CLA
Modified: 2019-11-20 12:13 EST (History)
1 user (show)

See Also:


Attachments
jstack dump with 3 content assist worker threads (28.55 KB, text/plain)
2019-11-08 10:50 EST, Andrey Loskutov CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrey Loskutov CLA 2019-11-08 10:50:56 EST
Created attachment 280578 [details]
jstack dump with 3 content assist worker threads

I've used but cancelled content assist popup in Java editor but that thing still run tasks on 3 threads (not Jobs, so not visible/stoppable by user!) in background even *minutes* after, with NO UI from content assist is shown at all.

Even closing all editors does not help, only restarting Eclipse.

I only noticed that because I have CPU monitor running and see if someone misbehaves.

Stack trace is attached (UI is idling, but I have 3 CPU cores fully loaded). This is a very bad regression.

"pool-7-thread-1" #6227 prio=5 os_prio=0 tid=0x00007ffd3b3b3800 nid=0x1511 waiting for monitor entry [0x00007ffe7abfd000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at org.eclipse.jdt.internal.core.JavaModelManager.getInfo(JavaModelManager.java:2179)
	- waiting to lock <0x00000003c2d7d2d8> (a org.eclipse.jdt.internal.core.JavaModelManager)
	at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:324)
	at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:312)
	at org.eclipse.jdt.internal.core.SourceType.getSuperclassTypeSignature(SourceType.java:513)
	at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.fieldCanBeSeenBy(ChainElementAnalyzer.java:377)
	at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.findFieldsAndMethods(ChainElementAnalyzer.java:125)
	at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.findVisibleInstanceFieldsAndRelevantInstanceMethods(ChainElementAnalyzer.java:96)
	at org.eclipse.jdt.internal.ui.text.ChainFinder.findAllFieldsAndMethods(ChainFinder.java:160)
	at org.eclipse.jdt.internal.ui.text.ChainFinder.searchDeeper(ChainFinder.java:146)
	at org.eclipse.jdt.internal.ui.text.ChainFinder.searchChainsForExpectedType(ChainFinder.java:80)
	at org.eclipse.jdt.internal.ui.text.ChainFinder.startChainSearch(ChainFinder.java:57)
	at org.eclipse.jdt.internal.ui.text.java.ChainCompletionProposalComputer.lambda$0(ChainCompletionProposalComputer.java:169)
	at org.eclipse.jdt.internal.ui.text.java.ChainCompletionProposalComputer$$Lambda$1865/1078124229.run(Unknown Source)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

JVMtop output:

JvmTop 0.9 - 16:40:17,  amd64, 16 cpus, Linux 3.10.0-86, load avg 2.39
 PID 24454: /data/eclipse4.14/eclipse//plugins/org.eclipse.equinox.launcher_1.5.600.v20191014-2022.jar 
 ARGS: -data /data/4x_platform_workspace -os linux -ws gtk -arch x86_64 -s[...]
 VMARGS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=804[...]
 VM: Oracle Corporation OpenJDK 64-Bit Server VM 1.8.0_232
 UP:  6:58m  #THR: 37   #THRPEAK: 92   #THRCREATED: 6321 USER: aloskuto    
 GC-Time:  0: 0m   #GC-Runs: 191       #TotalLoadedClasses: 26832   
 GC:  0.00% HEAP:5329m /14564m NONHEAP: 311m /  n/a

    TID NAME                                                                                 STATE      CPU    BLOCKEDBY 
   6231 pool-9-thread-1                                                                   RUNNABLE    18.73%       
        | at org.eclipse.jdt.internal.core.JavaModelManager.getInfo(JavaModelManager.java:2179)
        | at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:324)
        | at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:312)
        | at org.eclipse.jdt.internal.core.SourceType.getSuperclassTypeSignature(SourceType.java:513)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.fieldCanBeSeenBy(ChainElementAnalyzer.java:377)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.findFieldsAndMethods(ChainElementAnalyzer.java:125)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.findAllPublicStaticFieldsAndNonVoidNonPrimitiveStaticMethods(ChainElementAnalyzer.java:102)
        | at org.eclipse.jdt.internal.ui.text.ChainFinder.findAllFieldsAndMethods(ChainFinder.java:159)
        | at org.eclipse.jdt.internal.ui.text.ChainFinder.searchDeeper(ChainFinder.java:146)
   6227 pool-7-thread-1                                                                   RUNNABLE    18.80%       
        | at org.eclipse.jdt.internal.core.JavaModelManager.getInfo(JavaModelManager.java:2179)
        | at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:324)
        | at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:312)
        | at org.eclipse.jdt.internal.core.SourceType.getSuperclassTypeSignature(SourceType.java:513)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.fieldCanBeSeenBy(ChainElementAnalyzer.java:376)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.findFieldsAndMethods(ChainElementAnalyzer.java:125)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.findVisibleInstanceFieldsAndRelevantInstanceMethods(ChainElementAnalyzer.java:96)
        | at org.eclipse.jdt.internal.ui.text.ChainFinder.findAllFieldsAndMethods(ChainFinder.java:160)
        | at org.eclipse.jdt.internal.ui.text.ChainFinder.searchDeeper(ChainFinder.java:146)
   6229 pool-8-thread-1                                                                   RUNNABLE    18.76%       
        | at org.eclipse.jdt.internal.core.JavaModelManager.getInfo(JavaModelManager.java:2179)
        | at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:324)
        | at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:312)
        | at org.eclipse.jdt.internal.core.SourceType.getSuperclassTypeSignature(SourceType.java:513)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.fieldCanBeSeenBy(ChainElementAnalyzer.java:377)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.findFieldsAndMethods(ChainElementAnalyzer.java:125)
        | at org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.findAllPublicStaticFieldsAndNonVoidNonPrimitiveStaticMethods(ChainElementAnalyzer.java:102)
        | at org.eclipse.jdt.internal.ui.text.ChainFinder.findAllFieldsAndMethods(ChainFinder.java:159)
        | at org.eclipse.jdt.internal.ui.text.ChainFinder.searchDeeper(ChainFinder.java:146)
Comment 1 Andrey Loskutov CLA 2019-11-08 10:57:36 EST
Roland, could you please check this?
Could be a regression from bug 549753?
Comment 2 Andrey Loskutov CLA 2019-11-08 11:21:03 EST
"Kind of" steps to reproduce:

I was on patch https://git.eclipse.org/r/152336, precisely at https://git.eclipse.org/r/#/c/152336/1/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/AbstractLeakTest.java@184

The method body was empty and I've started to type (exact the case as below)

if(files.exists| <- content assist here

after that I've hit backspace few times to see what else files API offers, I see the 3 threads starts loading my CPU.

I've debugged this - it looks like the while() loop in org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.fieldCanBeSeenBy(IField, IType) has a bug.

I see that it all starts with invocationType = AbstractLeakTest
but then it switches currType all the time between 

org.eclipse.jdt.core.tests.junit.extension.TestCase and org.eclipse.test.performance.PerformanceTestCase

and none of them are equals to fb.getDeclaringType() which is ResourcePropertyTester.

Looks like logic in org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.getTypeFromSignature(IJavaProject, String, IType) is flawed.

The org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.getTypeFromSignature(IJavaProject, String, IType) is asked to check for QPerformanceTestCase; and QTestCase; type signatures, but because 

org.eclipse.jdt.core.tests.junit.extension.TestCase extends PerformanceTestCase 

PerformanceTestCase extends junit.framework.TestCase

we have nice cycle *without* package part!

The code in org.eclipse.jdt.internal.ui.text.ChainElementAnalyzer.fieldCanBeSeenBy(IField, IType) should not use currType.getSuperclassTypeSignature() for source types -the API says "The type signature may be either unresolved (for source types) or resolved (for binary types)".
Comment 3 Andrey Loskutov CLA 2019-11-08 11:31:48 EST
(In reply to Andrey Loskutov from comment #1)
> Could be a regression from bug 549753?

It is. Roland, can you please take this bug?
Comment 4 Roland Grunberg CLA 2019-11-08 13:56:23 EST
Thanks for the detailed description, though I am having some trouble reproducing using the eclipse/updates/I-builds as target platform and most of jdt.core checked out in a workspace.

Was this using an I-build, or 4.13 ? I noticed something similar (chain completion timed out, but thread kept going) and made a commit that seemed to have fixed it for 4.14 M1 ( https://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/commit/?id=c9286483734fc8d1d38ef00327958b915b2728e8 ). If this is an I-build, any ideas why the thread isn't getting shut down ?
Comment 5 Andrey Loskutov CLA 2019-11-08 14:14:52 EST
Sorry didn't mention this - I run latest nightly build.
Comment 6 Andrey Loskutov CLA 2019-11-08 14:16:34 EST
Sorry didn't mention this - I run latest nightly build.(In reply to Roland Grunberg from comment #4)
> If this is an I-build, any
> ideas why the thread isn't getting shut down ?

See comment 2. The while loop never ends.
Comment 7 Roland Grunberg CLA 2019-11-08 16:51:04 EST
Just to confirm, do you actually have source for junit.framework.TestCase checked out ?

In my case I just had it in my target platform, but that wouldn't reproduce as you can see from below :

Invocation Type org.eclipse.jdt.core.tests.builder.AbstractLeakTest
Resolving Superclass QBuilderTests;
Resolved to org.eclipse.jdt.core.tests.builder.BuilderTests
Resolving Superclass QTestCase;
Resolved to org.eclipse.jdt.core.tests.junit.extension.TestCase
Resolving Superclass QPerformanceTestCase;
Resolved to org.eclipse.test.performance.PerformanceTestCase
Resolving Superclass Ljunit.framework.TestCase;
Resolved to junit.framework.TestCase
Resolving Superclass Ljunit.framework.Assert;
Resolved to junit.framework.Assert
Resolving Superclass Ljava.lang.Object;
Resolved to java.lang.Object

Either way, I think a solution would be to avoid caching unresolved types (in typeCache) as this is likely what's causing the cycle.
Comment 8 Eclipse Genie CLA 2019-11-12 13:53:52 EST
New Gerrit change created: https://git.eclipse.org/r/152511
Comment 9 Roland Grunberg CLA 2019-11-12 13:57:50 EST
As a note, I was able to reproduce with a snippet but for me the infinite loop happened in ChainElementAnalyzer#isAssignmentCompatible(..) . It's the same idea though.
Comment 11 Roland Grunberg CLA 2019-11-13 15:01:53 EST
Marking as RESOLVED (FIXED). Note that I've added a testcase that would ensure this doesn't regress.
Comment 12 Roland Grunberg CLA 2019-11-20 12:13:27 EST
Verified for 4.14 M3 using I20191120-0840 build.

I've actually found a bug in the testcase itself, though it doesn't seem to affect the end result.