Bug 14109 - Deadlock between ProblemTreeViewer refresh and reconciler
Summary: Deadlock between ProblemTreeViewer refresh and reconciler
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 2.0 F3   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-04-18 10:25 EDT by Nick Edgar CLA
Modified: 2002-06-05 11:23 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nick Edgar CLA 2002-04-18 10:25:05 EDT
Build 20020416

While running a benchmark, we encountered a deadlock between a refresh of the 
ProblemTreeViewer (presumably for the packages view) and the reconciler.

We have not seen this occur in regular use, just when running the benchmark.

The benchmark does the following:
  - open workbench
  - close all open editors
  - create 100 .java files (opening them in editors)
  - exit
  - repeat
Note that the files are never deleted, so the packages view will get larger 
and larger.

It consistently deadlocks early on the 21st iteration on Windows (around 2000 
files), and at a different iteration on Linux.

There were 3 threads blocked, 2 of which were deadlocked.  The 3rd was waiting 
for one of the locks, but was not involved in the deadlocked.

Here are the threads, annotated with where the locks are obtained (see ***).  
Read them bottom up.  Note that the first two threads involve the same 
WorkingCopy.  The third thread is for a different WorkingCopy.

Note that it looks like the Java model cache is trying to remove a WorkingCopy 
which is still being used by the reconciler.  This may be another problem.

Thread [main] (Suspended)
        (*** attempt to obtain lock on WorkingCopy, id=93)
	org.eclipse.jdt.internal.core.ElementCache.close
(org.eclipse.jdt.internal.core.util.LRUCache$LRUCacheEntry) line: 38
	org.eclipse.jdt.internal.core.ElementCache
(org.eclipse.jdt.internal.core.OverflowingLRUCache).privateRemoveEntry
(org.eclipse.jdt.internal.core.util.LRUCache$LRUCacheEntry, boolean, boolean) 
line: 278
	org.eclipse.jdt.internal.core.ElementCache
(org.eclipse.jdt.internal.core.OverflowingLRUCache).makeSpace(int) line: 169
	org.eclipse.jdt.internal.core.ElementCache
(org.eclipse.jdt.internal.core.OverflowingLRUCache).put(java.lang.Object, 
java.lang.Object) line: 345
	org.eclipse.jdt.internal.core.JavaModelCache.putInfo
(org.eclipse.jdt.core.IJavaElement, java.lang.Object) line: 136
	org.eclipse.jdt.internal.core.JavaModelManager.putInfo
(org.eclipse.jdt.core.IJavaElement, java.lang.Object) line: 948
	org.eclipse.jdt.internal.core.CompilationUnit.generateInfos
(org.eclipse.jdt.internal.core.OpenableElementInfo, 
org.eclipse.core.runtime.IProgressMonitor, java.util.Map, 
org.eclipse.core.resources.IResource) line: 295
	org.eclipse.jdt.internal.core.CompilationUnit.buildStructure
(org.eclipse.jdt.internal.core.OpenableElementInfo, 
org.eclipse.core.runtime.IProgressMonitor) line: 68
	org.eclipse.jdt.internal.core.CompilationUnit
(org.eclipse.jdt.internal.core.Openable).openWhenClosed
(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.jdt.core.IBuffer) 
line: 394
	org.eclipse.jdt.internal.core.CompilationUnit
(org.eclipse.jdt.internal.core.JavaElement).openHierarchy() line: 497
        (*** lock obtained on JavaModelManager)
	org.eclipse.jdt.internal.core.CompilationUnit
(org.eclipse.jdt.internal.core.JavaElement).getElementInfo() line: 287
	org.eclipse.jdt.internal.core.CompilationUnit.getSourceRange() line: 
512
	org.eclipse.jdt.internal.ui.viewsupport.ErrorTickAdornmentProvider.comp
uteAdornmentFlags(java.lang.Object) line: 60
	org.eclipse.jdt.internal.ui.viewsupport.StandardJavaUILabelProvider
(org.eclipse.jdt.internal.ui.viewsupport.JavaUILabelProvider).getImage
(java.lang.Object) line: 82
	org.eclipse.jface.viewers.DecoratingLabelProvider.getImage
(java.lang.Object) line: 65
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.StructuredViewer).getLabel(java.lang.Object, 
org.eclipse.jface.viewers.ILabelProvider) line: 1089
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.TreeViewer).doUpdateItem
(org.eclipse.swt.widgets.Item, java.lang.Object) line: 88
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.AbstractTreeViewer).doUpdateItem
(org.eclipse.swt.widgets.Widget, java.lang.Object, boolean) line: 352
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.StructuredViewer).updateItem
(org.eclipse.swt.widgets.Widget, java.lang.Object) line: 1044
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.AbstractTreeViewer).internalRefresh
(org.eclipse.swt.widgets.Widget, java.lang.Object, boolean) line: 846
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.AbstractTreeViewer).internalRefresh
(org.eclipse.swt.widgets.Widget, java.lang.Object, boolean) line: 860
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.AbstractTreeViewer).internalRefresh
(java.lang.Object) line: 829
	org.eclipse.jface.viewers.StructuredViewer$1.run() line: 676
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.StructuredViewer).preservingSelection
(java.lang.Runnable) line: 616
	org.eclipse.jdt.internal.ui.viewsupport.ProblemTreeViewer
(org.eclipse.jface.viewers.StructuredViewer).refresh(java.lang.Object) line: 
674
	org.eclipse.jdt.ui.JavaElementContentProvider$2.run() line: 255
	org.eclipse.swt.widgets.RunnableLock.run() line: 29
	org.eclipse.ui.internal.UISynchronizer
(org.eclipse.swt.widgets.Synchronizer).runAsyncMessages() line: 93
	org.eclipse.swt.widgets.Display.runAsyncMessages() line: 1389
	org.eclipse.swt.widgets.Display.readAndDispatch() line: 1211
	org.eclipse.benchmarks.startupshutdown.BenchmarkWorkbench.clearEventLoo
p() line: 77
	org.eclipse.benchmarks.startupshutdown.BenchmarkWorkbench.create100Clas
ses() line: 150
	org.eclipse.benchmarks.startupshutdown.BenchmarkWorkbench.runProc(int) 
line: 116
	org.eclipse.benchmarks.startupshutdown.BenchmarkWorkbench.runEventLoop
() line: 62
	org.eclipse.benchmarks.startupshutdown.BenchmarkWorkbench
(org.eclipse.ui.internal.Workbench).run(java.lang.Object) line: 819
	org.eclipse.core.internal.boot.InternalBootLoader.run
(java.lang.String, java.net.URL, java.lang.String, java.lang.String[]) line: 
777
	org.eclipse.core.boot.BootLoader.run(java.lang.String, java.net.URL, 
java.lang.String, java.lang.String[]) line: 319
	java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) 
line: not available [native method]
	org.eclipse.core.launcher.Main.basicRun(java.lang.String[]) line: 190
	org.eclipse.core.launcher.Main.run(java.lang.String[]) line: 549
	org.eclipse.core.launcher.Main.main(java.lang.String[]) line: 390

Thread [org.eclipse.jface.text.reconciler.MonoReconciler] (Suspended)
        (*** attempt to obtain lock on JavaModelManager)
	org.eclipse.jdt.internal.core.SourceType
(org.eclipse.jdt.internal.core.JavaElement).getElementInfo() line: 284
	org.eclipse.jdt.internal.core.JavaElementDeltaBuilder.recordNewPosition
s(org.eclipse.jdt.core.IJavaElement, int) line: 395
	org.eclipse.jdt.internal.core.JavaElementDeltaBuilder.recordNewPosition
s(org.eclipse.jdt.core.IJavaElement, int) line: 404
	org.eclipse.jdt.internal.core.JavaElementDeltaBuilder.buildDeltas() 
line: 125
	org.eclipse.jdt.internal.core.WorkingCopy.reconcile() line: 333
        (*** lock obtained on WorkingCopy id=93)
	org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile
() line: 62
	org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile
(org.eclipse.jface.text.IRegion) line: 80
	org.eclipse.jface.text.reconciler.MonoReconciler.process
(org.eclipse.jface.text.reconciler.DirtyRegion) line: 66
	org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.r
un() line: 153

Thread [org.eclipse.jface.text.reconciler.MonoReconciler] (Suspended)
        (*** attempt to obtain lock on JavaModelManager)
	org.eclipse.jdt.internal.core.WorkingCopy
(org.eclipse.jdt.internal.core.JavaElement).getElementInfo() line: 284
	org.eclipse.jdt.internal.core.JavaElementDeltaBuilder.recordNewPosition
s(org.eclipse.jdt.core.IJavaElement, int) line: 395
	org.eclipse.jdt.internal.core.JavaElementDeltaBuilder.buildDeltas() 
line: 125
	org.eclipse.jdt.internal.core.WorkingCopy.reconcile() line: 333
        (*** lock obtained on WorkingCopy id=150)
	org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile
() line: 62
	org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile
(org.eclipse.jface.text.IRegion) line: 80
	org.eclipse.jface.text.reconciler.MonoReconciler.process
(org.eclipse.jface.text.reconciler.DirtyRegion) line: 66
	org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.r
un() line: 153
Comment 1 Nick Edgar CLA 2002-04-18 10:30:52 EDT
One possible fix would be for JavaReconcilingStrategy.reconcile() to obtain a 
lock on the JavaModelManager before the lock on the working copy.
If a lock on the JavaModelManager is always obtained first, there seems to be 
little need for locking on the working copy (although you'd still want to 
synchronize on the manager in the same places as currently done for the 
working copies).
This solution may limit concurrency, but is probably the safest approach.
Comment 2 Philipe Mulet CLA 2002-06-05 06:37:25 EDT
Problem should still be around.

Why is the reconciling strategy taking a lock on the working copy ? 

Now, given this is a public object, we might want to avoid also synchronizing 
internally onto it...
Comment 3 Philipe Mulet CLA 2002-06-05 07:12:20 EDT
There is no point for us locking on the working copy before flushing it, indeed 
the internal cache removal is done by Openable#close which is synchronized 
already on the model manager.

Removing this unnecessary lock. Same pattern was found onto the BufferCache.
Comment 4 Philipe Mulet CLA 2002-06-05 11:23:47 EDT
Fixed - will need JDT/UI to verify symptoms are gone