Skip to content
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

(apparent) Deadlock caused by RefreshDSLDJob #1066

Closed
mauromol opened this issue Mar 25, 2020 · 7 comments
Closed

(apparent) Deadlock caused by RefreshDSLDJob #1066

mauromol opened this issue Mar 25, 2020 · 7 comments
Assignees
Labels
Milestone

Comments

@mauromol
Copy link

When editing facelets (JSF .xhtml files), my Eclipse IDE UI often freezes for dozen seconds, if not even minutes. Today it seemed to be hung for so long that I thought it was a deadlock.
I decided to took a thread dump and discovered that the cause of this was a search probably triggered for EL expressions that was triggering the DSDLStoreManager that was in turn waiting for something to complete, probably the RefreshDSLDJob job.

After some minutes, the IDE UI was responsive again, but this problem is really frustrating and hurts productivity a lot.

Please note that DSL support in classpath is disabled for this project. I don't use DSLs, so these "refreshing DSLD" jobs that often show up are somewhat irritating, especially when they hang the IDE like in this case. Is there a way to shut down this DSLD thing completely? What is needed for? I only have Gradle build files in my projects, for which support in the editor is very limited anyway.

Please note that my CPU was not very busy while this apparent deadlock was "running", so it's not quite clear to me why this job takes so much time.

Here is a thread dump:

threaddump-1585131180093.tdump.txt

@eric-milles
Copy link
Member

eric-milles commented Mar 25, 2020

I will have a look. Would it be possible for you to provide a minimal project setup that still runs into this issue?

You can completely disable DSLD support in your workspace preferences:
image

Or you can add this to your eclipse.ini vmargs section: "-Dgreclipse.dsld.disabled=true". I use the former for my PDE workspace and the latter for compiler unit tests.

You can also go the nuclear route and remove the DSLD bundle entirely from your installation. It is entirely optional and is loosely coupled through eclipse's extension mechanisms.

@eric-milles
Copy link
Member

So your UI is freezing up while trying to display hover information. Groovy is a search participant and tries to do its part to answer a search request. While trying to understand a GroovyCompilationUnit (groovy source of some kind) it is waiting for DLSDTypeLookup to be ready. As you mentioned, the RefreshDSLDJob is running in another thread and is waiting to get the package fragment roots (libraries and source folders) of the project.

I think the request for package fragment roots is more expensive in your environment due to LSP latencies. I will do a little more looking to understand the refresh interval and why the library info is slow or delayed.

	at org.codehaus.groovy.eclipse.dsl.DSLDStoreManager.waitForFinish(DSLDStoreManager.java:103)
	- locked <0x0000000700b14608> (a org.codehaus.groovy.eclipse.dsl.DSLDStoreManager)
	at org.codehaus.groovy.eclipse.dsl.DSLDStoreManager.ensureInitialized(DSLDStoreManager.java:93)
	at org.codehaus.groovy.eclipse.dsl.lookup.DSLDTypeLookup.initialize(DSLDTypeLookup.java:67)
	at org.eclipse.jdt.groovy.search.TypeInferencingVisitorWithRequestor.visitCompilationUnit(TypeInferencingVisitorWithRequestor.java:244)
	at org.codehaus.jdt.groovy.integration.internal.GroovyLanguageSupport.maybePerformDelegatedSearch(GroovyLanguageSupport.java:327)
	at org.codehaus.jdt.groovy.integration.LanguageSupportFactory.maybePerformDelegatedSearch(LanguageSupportFactory.java:118)
	at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1280)
	at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1398)
	at org.eclipse.jdt.internal.core.search.matching.MatchLocator.locateMatches(MatchLocator.java:1517)
	at org.eclipse.jdt.internal.core.search.JavaSearchParticipant.locateMatches(JavaSearchParticipant.java:112)
	at org.eclipse.jdt.internal.core.search.BasicSearchEngine.findMatches(BasicSearchEngine.java:250)
	at org.eclipse.jdt.internal.core.search.BasicSearchEngine.search(BasicSearchEngine.java:595)
	at org.eclipse.jdt.core.search.SearchEngine.search(SearchEngine.java:677)
	at org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.findAnnotatedComponents(AnnotationJSFAppConfigProvider.java:132)
	at org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.discoverFacesConfig(AnnotationJSFAppConfigProvider.java:110)
	at org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.getFacesConfigModel(AnnotationJSFAppConfigProvider.java:76)
	- locked <0x0000000702b00ac0> (a org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider)
	at org.eclipse.jst.jsf.core.jsfappconfig.internal.AbstractJSFAppConfigManager$6.run(AbstractJSFAppConfigManager.java:293)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
	at org.eclipse.jst.jsf.core.jsfappconfig.internal.AbstractJSFAppConfigManager.getFacesConfigModels(AbstractJSFAppConfigManager.java:286)
	at org.eclipse.jst.jsf.core.jsfappconfig.JSFAppConfigManager.getFacesConfigModels(JSFAppConfigManager.java:88)
	at org.eclipse.jst.jsf.core.jsfappconfig.internal.AbstractJSFAppConfigManager.getApplications(AbstractJSFAppConfigManager.java:483)
	at org.eclipse.jst.jsf.core.jsfappconfig.JSFAppConfigManager.getApplications(JSFAppConfigManager.java:112)
	at org.eclipse.jst.jsf.core.jsfappconfig.internal.JSFAppConfigManagerFactory.createNewInstance(JSFAppConfigManagerFactory.java:78)
	at org.eclipse.jst.jsf.core.jsfappconfig.internal.JSFAppConfigManagerFactory.createNewInstance(JSFAppConfigManagerFactory.java:1)
	at org.eclipse.jst.jsf.common.internal.resource.ResourceSingletonObjectManager.getInstance(ResourceSingletonObjectManager.java:92)
	- locked <0x0000000702b00ad8> (a org.eclipse.jst.jsf.core.jsfappconfig.internal.JSFAppConfigManagerFactory)
	at org.eclipse.jst.jsf.core.jsfappconfig.internal.JSFAppConfigManagerFactory.getJSFAppConfigManagerInstance(JSFAppConfigManagerFactory.java:53)
	at org.eclipse.jst.jsf.designtime.internal.symbols.ConfigBasedDTVariableResolver.retrieveDecorativeVariableResolvers(ConfigBasedDTVariableResolver.java:120)
	at org.eclipse.jst.jsf.designtime.internal.symbols.ConfigBasedDTVariableResolver.resolveVariable(ConfigBasedDTVariableResolver.java:96)
	at org.eclipse.jst.jsf.designtime.resolver.SymbolContextResolver.getVariable(SymbolContextResolver.java:63)
	at org.eclipse.jst.jsf.core.internal.contentassist.el.SymbolResolveUtil.getSymbolForVariable(SymbolResolveUtil.java:58)
	at org.eclipse.jst.jsf.core.internal.contentassist.el.ContentAssistParser$PrefixVisitor.getSymbolInfo(ContentAssistParser.java:184)
	at org.eclipse.jst.jsf.core.internal.contentassist.el.ContentAssistParser.getSymbolInfo(ContentAssistParser.java:85)
	at org.eclipse.jst.jsf.ui.internal.jspeditor.JSPSourceUtil.determineSymbolInfo(JSPSourceUtil.java:105)
	at org.eclipse.jst.jsf.ui.internal.jspeditor.JSFELHover.getHoverRegion(JSFELHover.java:67)
	at org.eclipse.jst.jsf.ui.internal.jspeditor.JSFELHover.getHoverRegion(JSFELHover.java:52)
	at org.eclipse.jst.jsf.facelet.ui.internal.hover.FaceletHover.getHoverRegion(FaceletHover.java:88)
	at org.eclipse.wst.sse.ui.internal.taginfo.BestMatchHover.getHoverRegion(BestMatchHover.java:185)
	at org.eclipse.jface.text.TextViewerHoverManager.computeInformation(TextViewerHoverManager.java:142)
	at org.eclipse.jface.text.AbstractInformationControlManager.doShowInformation(AbstractInformationControlManager.java:1101)
"Worker-36: Refresh DSLD scripts" #2829 prio=5 os_prio=0 tid=0x00007ff5c821e000 nid=0x4347 in Object.wait() [0x00007ff5babc7000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at org.eclipse.core.internal.jobs.ThreadJob.waitForRun(ThreadJob.java:316)
	- locked <0x00000006d5cc27e8> (a java.lang.Object)
	at org.eclipse.core.internal.jobs.ThreadJob.joinRun(ThreadJob.java:205)
	at org.eclipse.core.internal.jobs.ImplicitJobs.begin(ImplicitJobs.java:95)
	at org.eclipse.core.internal.jobs.JobManager.beginRule(JobManager.java:298)
	at org.eclipse.core.internal.resources.WorkManager.checkIn(WorkManager.java:124)
	at org.eclipse.core.internal.resources.Workspace.prepareOperation(Workspace.java:2242)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2287)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2317)
	at org.codehaus.groovy.eclipse.dsl.RefreshDSLDJob$DSLDResourceVisitor.getFragmentRoots(RefreshDSLDJob.java:358)
	at org.codehaus.groovy.eclipse.dsl.RefreshDSLDJob$DSLDResourceVisitor.findDSLDsInLibraries(RefreshDSLDJob.java:263)
	at org.codehaus.groovy.eclipse.dsl.RefreshDSLDJob$DSLDResourceVisitor.findFiles(RefreshDSLDJob.java:250)
	at org.codehaus.groovy.eclipse.dsl.RefreshDSLDJob.refreshProject(RefreshDSLDJob.java:182)
	at org.codehaus.groovy.eclipse.dsl.RefreshDSLDJob.run(RefreshDSLDJob.java:123)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

@mauromol
Copy link
Author

Thanks, I didn't know about the ability to disable DSLD support at workspace level, I don't think I need it (I just use Groovy besides Java in my Java and Dynamic Web Projects).
So by now I'll follow this road.

Would it be possible for you to provide a minimal project setup that still runs into this issue?

Unfortunately I don't think I would be able to do so: it's a huge (proprietary) project, with 3 Dynamic Web Projects and one Utility Module. 2 out of 3 Dynamic Web Projects use JSF/Prime Faces. I wouldn't even know which parts of the codebase would be actually needed to reproduce :-(
Also, the problem is not easy to reproduce, it just happens "randomly", since it's a concurrency problem, and perhaps it only happens as long as the DSLD cache is not yet ready.

@eric-milles
Copy link
Member

Here is the code for getting project classpath (so DSLDs can be scanned for). It has a bit of a sordid history:

        /**
         * Get all package fragment roots in a safe way so that concurrent modifications aren't thrown (GRECLIPSE-1284).
         */
        private IPackageFragmentRoot[] getFragmentRoots(final IProgressMonitor monitor) throws JavaModelException {
            final IPackageFragmentRoot[][] roots = new IPackageFragmentRoot[1][];
            try {
                ResourcesPlugin.getWorkspace().run(pm -> {
                    roots[0] = JavaCore.create(project).getAllPackageFragmentRoots();
                }, getSchedulingRule(), IWorkspace.AVOID_UPDATE, monitor);
            } catch (CoreException e) {
                if (e.getStatus().getCode()  == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) {
                    // ignore...project was deleted
                } else {
                    GroovyDSLCoreActivator.logException(e);
                }
            }
            return roots[0] != null ? roots[0] : new IPackageFragmentRoot[0];
        }

        private ISchedulingRule getSchedulingRule() {
            IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace().getRuleFactory();
            // FIXADE Arrrrgh...we need to grab a build rule here.  Looks like a classpath container refresh
            // will grab the rule of projects that are contained in the container.
            /*return new MultiRule(new ISchedulingRule[] {
                // use project modification rule as this is needed to create the .classpath file if it doesn't exist yet, or to update project references
                ruleFactory.modifyRule(this.project.getProject()),

                // and external project modification rule in case the external folders are modified
                ruleFactory.modifyRule(JavaModelManager.getExternalManager().getExternalFoldersProject())
            });*/
            return ruleFactory.buildRule();
        }

@eric-milles
Copy link
Member

eric-milles commented Mar 25, 2020

IWorkspaceRunnable instances that are used to run stuff asynchronously are managed so that only one is running for a given scheduling rule. LSP4e uses them to update markers (seen in your thread dump): https://git.eclipse.org/r/plugins/gitiles/lsp4e/lsp4e/+/master/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java#141

You could file a bug with lsp4e as well. If they changed "run(runnable, ...)" to "run(runnable, resource, IWorkspace.AVOID_UPDATE, ...)", it would reduce the scope of their job.

@eric-milles
Copy link
Member

ready to test

@mauromol
Copy link
Author

I installed 3.7.0.v202003252328-e1912 and re-enabled DSLD support in my workspace, I'll let you know how it goes, thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants