Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 356692 - [xtend] deadlock in org.eclipse.xtend.typesystem.emf.ui.EmfToolsPlugin.start
Summary: [xtend] deadlock in org.eclipse.xtend.typesystem.emf.ui.EmfToolsPlugin.start
Status: CLOSED FIXED
Alias: None
Product: M2T
Classification: Modeling
Component: Xpand (show other bugs)
Version: 2.0.0   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Karsten Thoms CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on: 268516 289266 415664
Blocks:
  Show dependency tree
 
Reported: 2011-09-04 18:48 EDT by Michael Scharf CLA
Modified: 2017-10-31 11:24 EDT (History)
3 users (show)

See Also:
karsten.thoms: luna+


Attachments
full stack dump (37.24 KB, text/plain)
2011-09-04 18:48 EDT, Michael Scharf CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Scharf CLA 2011-09-04 18:48:45 EDT
Created attachment 202727 [details]
full stack dump

I cannot start eclipse anymore on my workspace, because I get the following deadlock:

"Worker-9" prio=6 tid=0x4cfcd400 nid=0x1194 in Object.wait() [0x5024e000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x1dc673c8> (a org.eclipse.jdt.internal.core.JavaModelManager)
	at org.eclipse.jdt.core.JavaCore.initializeAfterLoad(JavaCore.java:3552)
	- locked <0x1dc673c8> (a org.eclipse.jdt.internal.core.JavaModelManager)
	at org.eclipse.xtend.typesystem.emf.ui.EmfToolsPlugin.start(EmfToolsPlugin.java:146)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
	at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
....

"Worker-9" prio=6 tid=0x4cfcd400 nid=0x1194 in Object.wait() [0x5024e000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x1dc673c8> (a org.eclipse.jdt.internal.core.JavaModelManager)
	at org.eclipse.jdt.core.JavaCore.initializeAfterLoad(JavaCore.java:3552)
	- locked <0x1dc673c8> (a org.eclipse.jdt.internal.core.JavaModelManager)
	at org.eclipse.xtend.typesystem.emf.ui.EmfToolsPlugin.start(EmfToolsPlugin.java:146)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
	at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
Comment 1 Michael Scharf CLA 2011-09-04 18:49:52 EDT
OOPS, paste error. The second stack should have been:

"main" prio=6 tid=0x003a7400 nid=0x1850 in Object.wait() [0x00a0e000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x1e0f0c18> (a org.eclipse.core.internal.jobs.Semaphore)
	at org.eclipse.core.internal.jobs.Semaphore.acquire(Semaphore.java:39)
	- locked <0x1e0f0c18> (a org.eclipse.core.internal.jobs.Semaphore)
	at org.eclipse.core.internal.jobs.OrderedLock.doAcquire(OrderedLock.java:176)
	at org.eclipse.core.internal.jobs.OrderedLock.acquire(OrderedLock.java:110)
	at org.eclipse.core.internal.jobs.OrderedLock.acquire(OrderedLock.java:84)
	at org.eclipse.core.internal.resources.WorkManager.checkIn(WorkManager.java:119)
	at org.eclipse.core.internal.resources.Workspace.prepareOperation(Workspace.java:2282)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2339)
	at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:793)
	at org.eclipse.jdt.internal.core.JavaModelManager$11.run(JavaModelManager.java:2793)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2344)
	at org.eclipse.jdt.internal.core.JavaModelManager.initializeAllContainers(JavaModelManager.java:2809)
	at org.eclipse.jdt.internal.core.JavaModelManager.getClasspathContainer(JavaModelManager.java:1872)
	at org.eclipse.jdt.core.JavaCore.getClasspathContainer(JavaCore.java:2785)
	at org.eclipse.jdt.internal.core.JavaProject.resolveClasspath(JavaProject.java:2674)
	at org.eclipse.jdt.internal.core.JavaProject.resolveClasspath(JavaProject.java:2838)
	at org.eclipse.jdt.internal.core.JavaProject.getResolvedClasspath(JavaProject.java:1943)
	at org.eclipse.jdt.internal.core.JavaProject.buildStructure(JavaProject.java:461)
	at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:258)
	at org.eclipse.jdt.internal.core.Openable.openAncestors(Openable.java:504)
	at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:240)
	at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:518)
	at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:255)
	at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:241)
	at org.eclipse.jdt.internal.core.PackageFragmentRoot.getKind(PackageFragmentRoot.java:477)
	at org.eclipse.jdt.internal.core.PackageFragment.getKind(PackageFragment.java:290)
	at org.eclipse.jdt.internal.core.PackageFragment.validateExistence(PackageFragment.java:506)
	at org.eclipse.jdt.internal.core.Openable.exists(Openable.java:206)
	at org.eclipse.jdt.internal.core.PackageFragment.exists(PackageFragment.java:174)
	at org.eclipse.jdt.internal.ui.workingsets.JavaWorkingSetUpdater.checkElementExistence(JavaWorkingSetUpdater.java:230)
	at org.eclipse.jdt.internal.ui.workingsets.JavaWorkingSetUpdater.add(JavaWorkingSetUpdater.java:83)
	at org.eclipse.ui.internal.AbstractWorkingSetManager$11.run(AbstractWorkingSetManager.java:707)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.ui.internal.AbstractWorkingSetManager$10.runInUIThread(AbstractWorkingSetManager.java:703)
Comment 2 Karsten Thoms CLA 2013-08-02 11:43:37 EDT
Also reported from another project. We have to carefully evaluate how it can be assured that the necessary initialization happens after JDT was initialized without calling JavaCore.initializeAfterLoad().
Comment 3 Karsten Thoms CLA 2013-08-02 11:50:29 EDT
The call was introduced by the fix of Bug#268516, which indicated a similar problem. It seems that only the probability of a deadlock was lowered, but the root cause still exists.
Comment 4 Karsten Thoms CLA 2013-08-07 07:47:14 EDT
Had a discussion via phone with Ed Merks about this topic. One problem is that this issue is hard to reproduce, so that it is hard to tell if the approaches taken would really solve the problem.

We think that the initialization code in EmfToolsPlugin#start() has to be executed in a seperate job. During the initialization, calls to JavaCore could cause deadlock situations while JDT is being initialized. Especially the call to JavaCore#initializeAfterLoad() seems to be invalid here, and is just a workaround identified to lower the probability of deadlocks. As the documentation of this method says, the method might be called within a background thread. But durinf start within the thread that executes start() this is invalid.

The method getProjectAnalyzer() should be synchronized, since it might be called by different threads in unlikely situations, which might cause troubles. It is expected that the synchronization overhead does not matter.

Before actually changing the code I will try to reproduce the situation in the debugger. Ed suggested to set a breakpoint in initializeAfterLoad() which suspends the whole VM, then stop on first call and let all threads except the one run again until the breakpoint is hit again. When starting all threads again, a deadlock situation should be reproducable.
Comment 5 Karsten Thoms CLA 2013-08-08 08:10:22 EDT
I could not reproduce the deadlock situation. The two calls to JavaCore#initializeAfterLoad() were executed always after each other, not concurrently.

I have now evaluated the mentioned approach. The initialization code is put into a job with Workspace Root scheduling rule. The job itself is expected to run fast, so it does not block other jobs for long. Mainly it iterates just over the projects and schedules other jobs (ProjectAnalyzer).

After changing it, I set breakpoints in the initialization code of the new Job and in JavaCore#initializeAfterLoad(). It could be seen during startup that now two threads were stopping. Both of them could be stepped through independently. This seems to cover the assumption that the two threads are not blocking each other on a lock.

It may be considered to change the scheduling rule for the ProjectAnalyzer from workspace root to the actual project it analyzes. It seems not necessary that project analyzation jobs are executed sequentially, they may execute in parallel.
Comment 6 Karsten Thoms CLA 2013-08-23 08:32:57 EDT
Could not reproduce a deadlock situation, and I do not see how it should occur now after the mentioned change. However, bug#415664 was opened since I think the builder logic needs some refactoring.
Comment 7 Eclipse Webmaster CLA 2017-10-31 11:24:53 EDT
Requested via bug 522520.

-M.