Deadlock during content completion
Deadlock while editing SDF file.
jstack does not detect a deadlock, but the thread stacks do not change over time. No cpu is used.Spoofax: 0.5.3.3
Eclipse: 3.5.2Stack trace:
Submitted by Nathan Bruning on 17 September 2010 at 12:50
http://pastebin.com/Wy5jkhBr
Issue Log
Problematic threads:
“Worker-41” prio=10 tid=0x00007f89002c1000 nid=0xeca waiting for monitor entry [0x00007f88e58f2000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.eclipse.jface.text.source.AnnotationMap.containsKey(AnnotationMap.java:91)
- waiting to lock <0x00007f898b496498> (a java.lang.Object)
at org.eclipse.jface.text.source.AnnotationModel.addAnnotation(AnnotationModel.java:437)
at org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel.addMarkerAnnotation(AbstractMarkerAnnotationModel.java:228)
at org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel.update(ResourceMarkerAnnotationModel.java:102)
at org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel$ResourceChangeListener.resourceChanged(ResourceMarkerAnnotationModel.java:56)
at org.eclipse.core.internal.events.NotificationManager$2.run(NotificationManager.java:291)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.NotificationManager.notify(NotificationManager.java:285)
at org.eclipse.core.internal.events.NotificationManager.broadcastChanges(NotificationManager.java:149)
at org.eclipse.core.internal.resources.Workspace.broadcastPostChange(Workspace.java:313)
at org.eclipse.core.internal.resources.Workspace.endOperation(Workspace.java:1022)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1809)
at org.strategoxt.imp.runtime.parser.ast.AstMessageHandler.runInWorkspace(AstMessageHandler.java:493)
at org.strategoxt.imp.runtime.parser.ast.AstMessageHandler.commitAllChanges(AstMessageHandler.java:290)
at org.strategoxt.imp.runtime.services.StrategoObserver.presentToUser(StrategoObserver.java:384)
at org.strategoxt.imp.runtime.services.StrategoObserver.update(StrategoObserver.java:305)
at org.strategoxt.imp.runtime.services.StrategoObserverUpdateJob.analyze(StrategoObserverUpdateJob.java:30)
at org.strategoxt.imp.runtime.services.StrategoAnalysisQueue$UpdateJob.run(StrategoAnalysisQueue.java:80)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)“main” prio=10 tid=0x0000000041c48800 nid=0x8ff in Object.wait() [0x00007f899611b000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at org.eclipse.core.internal.jobs.Semaphore.acquire(Semaphore.java:38)
- locked <0x00007f897555ba70> (a org.eclipse.core.internal.jobs.Semaphore)
at org.eclipse.core.internal.jobs.OrderedLock.doAcquire(OrderedLock.java:168)
at org.eclipse.core.internal.jobs.OrderedLock.acquire(OrderedLock.java:105)
at org.eclipse.core.internal.jobs.OrderedLock.acquire(OrderedLock.java:82)
at org.eclipse.core.internal.resources.WorkManager.checkIn(WorkManager.java:118)
at org.eclipse.core.internal.resources.Workspace.prepareOperation(Workspace.java:1747)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1795)
at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:118)
- locked <0x00007f897555b9b8> (a org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation)
at org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner.run(WorkspaceOperationRunner.java:75)
at org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner.run(WorkspaceOperationRunner.java:65)
at org.eclipse.ui.editors.text.TextFileDocumentProvider.executeOperation(TextFileDocumentProvider.java:456)
at org.eclipse.ui.editors.text.TextFileDocumentProvider.validateState(TextFileDocumentProvider.java:1074)
at org.eclipse.ui.texteditor.AbstractTextEditor.validateState(AbstractTextEditor.java:4834)
at org.eclipse.ui.texteditor.AbstractTextEditor.doSave(AbstractTextEditor.java:4734)
at org.eclipse.imp.editor.UniversalEditor.doSave(UniversalEditor.java:1933)
at org.eclipse.ui.texteditor.AbstractTextEditor$TextEditorSavable.doSave(AbstractTextEditor.java:7067)
at org.eclipse.ui.Saveable.doSave(Saveable.java:214)
at org.eclipse.ui.internal.SaveableHelper.doSaveModel(SaveableHelper.java:346)
at org.eclipse.ui.internal.SaveableHelper$3.run(SaveableHelper.java:193)
at org.eclipse.ui.internal.SaveableHelper$5.run(SaveableHelper.java:274)
at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
at org.eclipse.jface.window.ApplicationWindow$1.run(ApplicationWindow.java:759)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.jface.window.ApplicationWindow.run(ApplicationWindow.java:756)
at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2579)
at org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:282)
at org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:261)
at org.eclipse.ui.internal.SaveableHelper.saveModels(SaveableHelper.java:204)
at org.eclipse.ui.internal.SaveableHelper.savePart(SaveableHelper.java:144)
at org.eclipse.ui.internal.EditorManager.savePart(EditorManager.java:1357)
at org.eclipse.ui.internal.WorkbenchPage.savePart(WorkbenchPage.java:3328)
at org.eclipse.ui.internal.WorkbenchPage.saveEditor(WorkbenchPage.java:3341)
at org.eclipse.ui.internal.SaveAction.run(SaveAction.java:76)
at org.eclipse.jface.action.Action.runWithEvent(Action.java:498)
at org.eclipse.ui.commands.ActionHandler.execute(ActionHandler.java:185)
at org.eclipse.ui.internal.handlers.LegacyHandlerWrapper.execute(LegacyHandlerWrapper.java:109)
at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:470)
at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:824)
at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:880)
at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:569)
at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:510)
at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:125)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1467)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1175)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1200)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1185)
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1212)
at org.eclipse.swt.widgets.Widget.gtk_key_press_event(Widget.java:706)
at org.eclipse.swt.widgets.Control.gtk_key_press_event(Control.java:2837)
at org.eclipse.swt.widgets.Composite.gtk_key_press_event(Composite.java:703)
at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1570)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4594)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4191)
at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:7603)
at org.eclipse.swt.widgets.Display.eventProc(Display.java:1185)
at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:1860)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3110)
at org.strategoxt.imp.runtime.SWTSafeLock.lock(SWTSafeLock.java:42)
at org.strategoxt.imp.runtime.services.ContentProposer$1Runner.run(ContentProposer.java:249)
at org.strategoxt.imp.runtime.services.ContentProposer.invokeCompletionFunction(ContentProposer.java:273)
at org.strategoxt.imp.runtime.services.ContentProposer.getContentProposals(ContentProposer.java:131)
at org.strategoxt.imp.runtime.dynamicloading.DynamicContentProposer.getContentProposals(DynamicContentProposer.java:19)
at org.eclipse.imp.editor.internal.CompletionProcessor.computeCompletionProposals(CompletionProcessor.java:53)
at org.eclipse.jface.text.contentassist.ContentAssistant.computeCompletionProposals(ContentAssistant.java:1832)
at org.eclipse.jface.text.contentassist.CompletionProposalPopup.computeProposals(CompletionProposalPopup.java:556)
at org.eclipse.jface.text.contentassist.CompletionProposalPopup.access$16(CompletionProposalPopup.java:553)
at org.eclipse.jface.text.contentassist.CompletionProposalPopup$2.run(CompletionProposalPopup.java:488)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.jface.text.contentassist.CompletionProposalPopup.showProposals(CompletionProposalPopup.java:482)
at org.eclipse.jface.text.contentassist.ContentAssistant.showPossibleCompletions(ContentAssistant.java:1660)
at org.eclipse.jface.text.source.SourceViewer.doOperation(SourceViewer.java:835)
at org.eclipse.jface.text.source.projection.ProjectionViewer.doOperation(ProjectionViewer.java:1533)
at org.eclipse.imp.editor.StructuredSourceViewer.doOperation(StructuredSourceViewer.java:140)
at org.strategoxt.imp.runtime.services.ContentProposerListener.textChanged(ContentProposerListener.java:63)
at org.eclipse.jface.text.TextViewer.updateTextListeners(TextViewer.java:2806)
at org.eclipse.jface.text.TextViewer$VisibleDocumentListener.documentChanged(TextViewer.java:401)
at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged2(AbstractDocument.java:739)
at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged(AbstractDocument.java:712)
at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged(AbstractDocument.java:697)
at org.eclipse.jface.text.AbstractDocument.fireDocumentChanged(AbstractDocument.java:762)
at org.eclipse.jface.text.projection.ProjectionDocument.fireDocumentChanged(ProjectionDocument.java:778)
at org.eclipse.jface.text.projection.ProjectionDocument.masterDocumentChanged(ProjectionDocument.java:747)
at org.eclipse.jface.text.projection.ProjectionDocumentManager.fireDocumentEvent(ProjectionDocumentManager.java:123)
at org.eclipse.jface.text.projection.ProjectionDocumentManager.documentChanged(ProjectionDocumentManager.java:131)
at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged2(AbstractDocument.java:739)
at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged(AbstractDocument.java:712)
at org.eclipse.jface.text.AbstractDocument.doFireDocumentChanged(AbstractDocument.java:697)
at org.eclipse.jface.text.AbstractDocument.fireDocumentChanged(AbstractDocument.java:762)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1157)
at org.eclipse.core.internal.filebuffers.SynchronizableDocument.replace(SynchronizableDocument.java:195)
- locked <0x00007f898b496498> (a java.lang.Object)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1176)
at org.eclipse.core.internal.filebuffers.SynchronizableDocument.replace(SynchronizableDocument.java:181)
- locked <0x00007f898b496498> (a java.lang.Object)
at org.strategoxt.imp.runtime.services.AutoEditStrategy.insertClosingFence(AutoEditStrategy.java:218)
at org.strategoxt.imp.runtime.services.AutoEditStrategy.verifyKey(AutoEditStrategy.java:116)
at org.strategoxt.imp.runtime.dynamicloading.DynamicAutoEditStrategy.verifyKey(DynamicAutoEditStrategy.java:36)
at org.eclipse.jface.text.TextViewer$VerifyKeyListenersManager.verifyKey(TextViewer.java:489)
at org.eclipse.swt.custom.StyledTextListener.handleEvent(StyledTextListener.java:62)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1176)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1200)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1185)
at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1025)
at org.eclipse.swt.custom.StyledText.handleKeyDown(StyledText.java:5840)
at org.eclipse.swt.custom.StyledText$7.handleEvent(StyledText.java:5542)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1176)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1200)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1185)
at org.eclipse.swt.widgets.Widget.sendIMKeyEvent(Widget.java:1262)
at org.eclipse.swt.widgets.Control.gtk_commit(Control.java:2658)
at org.eclipse.swt.widgets.Canvas.gtk_commit(Canvas.java:163)
at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1560)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4594)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4191)
at org.eclipse.swt.internal.gtk.OS._gtk_im_context_filter_keypress(Native Method)
at org.eclipse.swt.internal.gtk.OS.gtk_im_context_filter_keypress(OS.java:7002)
at org.eclipse.swt.widgets.Control.filterKey(Control.java:2083)
at org.eclipse.swt.widgets.Control.gtk_key_press_event(Control.java:2830)
at org.eclipse.swt.widgets.Composite.gtk_key_press_event(Composite.java:703)
at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1570)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4594)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4191)
at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:7603)
at org.eclipse.swt.widgets.Display.eventProc(Display.java:1185)
at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:1860)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3110)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2405)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2369)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514)
at org.eclipse.equinox.launcher.Main.run(Main.java:1311)
at org.eclipse.equinox.launcher.Main.main(Main.java:1287)Analysis: a workspace worker thread is waiting for a lock
0x00007...
to add annotations. The main thread already had that lock and was doing content completion. It tried to acquire theEnvironment
lock, but then got tired waiting and started processing the event loop (SWTSafeLock.lock()
). Then, of course, it wanted a workspace lock, resulting in a deadlock.I’m not sure what to do about this one. The
SWTSafeLock.lock()
behavior is relatively new, but is actually designed to avoid deadlocks by running the GUI event loop that can only run in the main thread. That way it avoids GUI operations vs.SWTSafeLock
deadlocks. The only real solution seems to be to not run content completion in the main thread, but we can’t do that. We also can’t fix the SWT threading model. What remains is not running the event loop in the case of content completion. Depending on how common this problem is, that may be better, but it risks the GUI vs.SWTSafeLock
deadlock.
I think I had this issue too, although I don’t remember what I was doing at the time. In my case, jstack did detect the deadlock. I was using Eclipse 3.6.0 and Spoofax/IMP 0.5.2.93
Tobi: if you find more deadlocks please post a new issue for them. Mostly because of SWT we ran into a number of them before (mostly reported by Nathan and almost all fixed by now). Collecting more issues with stack traces would be useful to prevent remaining deadlocks.
The following issues provide more details about a way to reproduce this issue: Spoofax/260, Spoofax/329.
Some interesting new information:
The deadlock I am observing (Spoofax/329) does not seem to happen if I don’t define a completion trigger, i.e. it works fine for ctrl+space based completion.
I noticed in my traces that while the SWTSafeLock is trying to acquire the parseLock, it dispatches window messages, including keypresses, which trigger completion again, so a ContentProposer lower on the stack tries to get the SWTSafeLock again, which dispatches window messages, including keypresses, etc. In the trace in Spoofax/329 you see about 5 times the same pattern.
With some more debugging I figured that what actually happens is that occasionally (well, quite often) a content completion attempt does not ever finish. According to traces it remains stuck running the event loop in
controller.getParseLock().lock();
(ContentProposer.java:216), while occasionally (every 50 ms) trying to acquire the parseLock. Which for some reason apparently never succeeds. Often (always?) this is accompanied by a never-disappearing “Analyzing updates to …” progress indicator. Deadlock with working event loop? (i.e. the event loop in SWTSafeLock)So I performed one attempt at solving this deadlock by explicitly blocking reentrancy of
ContentProposerListener.textChanged
. This got rid of the hidden deadlock but often resulted in a detected deadlock between the background parser and the content proposer. I attempted to solve this by delaying the background parse intextChanged
if content completion was to be skipped because it was a reentrant call totextChanged
. Not sure it’s still possible to follow this explanation, but maybe the changes I made are clearer (sorry for the whitespace changes):
Index: src/org/strategoxt/imp/runtime/dynamicloading/ContentProposerFactory.java— src/org/strategoxt/imp/runtime/dynamicloading/ContentProposerFactory.java (revision 21739)
+++ src/org/strategoxt/imp/runtime/dynamicloading/ContentProposerFactory.java (working copy)
@@ -67,18 +67,18 @@
String[] keywords = completionKeywords.toArray(new String[0]);registerListener(descriptor, controller);
+
return new ContentProposer(feedback, completionFunction, identifierLexical, keywords, templates);
}private static void registerListener(Descriptor descriptor, SGLRParseController controller) throws BadDescriptorException {
+
try {
UniversalEditor editor = controller.getEditor().getEditor();
ISourceViewer viewer = editor.getServiceControllerManager().getSourceViewer();
Set triggers = readTriggers(descriptor);
- ContentProposerListener.register(triggers, viewer);
+ ContentProposerListener.register(triggers, viewer, controller);
} catch (RuntimeException e) {
Environment.logWarning(“Exception while trying to register content proposer listener”, e);
}
Index: src/org/strategoxt/imp/runtime/services/ContentProposerListener.java— src/org/strategoxt/imp/runtime/services/ContentProposerListener.java (revision 21739)
+++ src/org/strategoxt/imp/runtime/services/ContentProposerListener.java (working copy)
@@ -11,35 +11,41 @@
import org.eclipse.jface.text.source.ISourceViewer;
import org.strategoxt.imp.runtime.Environment;
import org.strategoxt.imp.runtime.WeakWeakMap;
+import org.strategoxt.imp.runtime.parser.SGLRParseController;/**
* Activates the content proposer based on text events.
- *
+ *
* @author Lennart Kats
*/
public class ContentProposerListener implements ITextListener {
-
+
private static final WeakWeakMap<ISourceViewer, ContentProposerListener> asyncListeners =
new WeakWeakMap<ISourceViewer, ContentProposerListener>();
-
+
private final Set patterns;
-
+
private final ISourceViewer viewer;
-
- private ContentProposerListener(Set patterns, ISourceViewer viewer) {
+
+ private final SGLRParseController controller;
+
+ private boolean inTextChanged = false;
+
+ private ContentProposerListener(Set patterns, ISourceViewer viewer, SGLRParseController controller) {
this.patterns = patterns;
this.viewer = viewer;
+ this.controller = controller;
}
- public static void register(Set triggers, ISourceViewer viewer) {
- public static void register(Set triggers, ISourceViewer viewer, SGLRParseController controller) {
synchronized (asyncListeners) {
ContentProposerListener oldListener = asyncListeners.remove(viewer);
if (oldListener != null)
viewer.removeTextListener(oldListener);+
if (viewer instanceof ITextOperationTarget) {
if (!triggers.isEmpty()) {
- ContentProposerListener listener = new ContentProposerListener(triggers, viewer);
+ ContentProposerListener listener = new ContentProposerListener(triggers, viewer, controller);
viewer.addTextListener(listener);
asyncListeners.put(viewer, listener);
}
@@ -50,6 +56,12 @@
}public void textChanged(TextEvent event) {
- if (inTextChanged) {
- controller.scheduleParserUpdate(4000, true); // cancel current parse
- return;
- }
- inTextChanged = true;
+
try {
boolean keyPressEvent = AutoEditStrategy.pollJustProcessedKeyEvent();
boolean insertionEvent = ContentProposal.pollJustApplied();
@@ -66,9 +78,11 @@
Environment.logException(“Exception when checking for content proposal triggers”, e);
} catch (RuntimeException e) {
Environment.logException(“Exception when checking for content proposal triggers”, e);- } finally {
- inTextChanged = false;
}
}+
private boolean matchesPatterns(IDocument document, int offset) throws BadLocationException {
for (Pattern pattern : patterns) {
boolean foundNewLine = false;This change does certainly not fully solve all deadlocks: at least once I still triggered a deadlock of background parser and content completion (could it be these acquire environment lock and parserLock in a different order?), but overall this patch changes content completion from nearly unusable on my setup to very usable, and I didn’t notice any bad effects yet.
PS: if it’s ok to commit it as experiment then just let me know (it’s only tested on Windows Vista). Not really used yet to the amount of experimental stuff that does/doesn’t go in trunk :)
@Tobi:
Alright, sounds like a nice improvement there. I say commit it.
As for ordering of locks, I don’t know about that particular case. But maybe you can add some assertions to validate the locking order? (Always develop with assertions enabled!)
As for development in the trunk, that’s fine, really. Usually changes aren’t really at the heart of the Spoofax runtime, like this one, but for most things rapid integration into the trunk works better than maintaining a private branch for several months ;) (Just be sure you enable assertions, that’s one of the main things we rely for catching regressions in the runtime plugin…) And if there’s really risky stuff, I’ll take that into consideration before/when making a new stable release.
Ok, that is clear, thanks.
I tested my “fix” a bit more though and concluded that it really isn’t good enough yet; I think the only thing it really does is remove the possibility for multiple consecutive 30s lockups in SWTSafeLock (i.e. when the first SWTSafeLock handles an event, which triggers completion, which ends up waiting 30s in SWTSafeLock again).
The first SWTSafeLock still never acquires the lock, which results in the completion trigger simply not working anymore after the first 30s lockup…
I’m pretty confident now though that the root of the problem lies with
marker.setAttributes(signature.getAttributes(), signature.getValues());
(AstMessageHandler.java) wanting to take an Eclipse lock while the parseLock is locked, and content completion runs while the Eclipse lock is taken, and wants to have the parseLock.I think it can be solved by moving marker refreshing stuff out of the parseLock scope, but I don’t know yet how to do that without risking race conditions.
Here are relevant snippets of the traces I see everytime that support this:
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x176f5b08> (a java.util.concurrent.locks.ReentrantLock$FairSync)
at java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireNanos(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireNanos(Unknown Source)
at java.util.concurrent.locks.ReentrantLock.tryLock(Unknown Source)
at org.strategoxt.imp.runtime.SWTSafeLock.lock(SWTSafeLock.java:41)
at org.strategoxt.imp.runtime.DebugSWTSafeLock.lock(DebugSWTSafeLock.java:17)
at org.strategoxt.imp.runtime.services.ContentProposer.parse(ContentProposer.java:216)
…
at org.eclipse.core.internal.filebuffers.SynchronizableDocument.replace(SynchronizableDocument.java:195)
- locked <0x17700908> (a java.lang.Object)
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1210)
at org.eclipse.core.internal.filebuffers.SynchronizableDocument.replace(SynchronizableDocument.java:181)
- locked <0x17700908> (a java.lang.Object)
at org.eclipse.jface.text.DefaultDocumentAdapter.replaceTextRange(DefaultDocumentAdapter.java:248)
…=> So 0x176f5b08 is the parseLock and 0x17700908 is the “Eclipse lock”.
So this thread (the main thread) got the “Eclipse lock” and is trying to get the parseLock.
“Worker-11” prio=6 tid=0x5c470c00 nid=0x17a0 waiting for monitor entry [0x5be7f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.eclipse.jface.text.source.AnnotationMap.keySetIterator(AnnotationMap.java:82)
- waiting to lock <0x17700908> (a java.lang.Object)
at org.eclipse.jface.text.source.AnnotationModel.getAnnotationIterator(AnnotationModel.java:783)
…
at org.eclipse.core.internal.resources.Marker.setAttributes(Marker.java:287)
at org.strategoxt.imp.runtime.parser.ast.AstMessageHandler.addMarker(AstMessageHandler.java:151)
at org.strategoxt.imp.runtime.parser.ParseErrorHandler$3.run(ParseErrorHandler.java:534)
at org.strategoxt.imp.runtime.parser.ParseErrorHandler.processErrorReportsQueue(ParseErrorHandler.java:250)
at org.strategoxt.imp.runtime.parser.ParseErrorHandler.commitMultiErrorLineAdditions(ParseErrorHandler.java:184)
at org.strategoxt.imp.runtime.parser.SGLRParseController.onParseCompleted(SGLRParseController.java:413)
at org.strategoxt.imp.runtime.parser.SGLRParseController.parse(SGLRParseController.java:323)
at org.strategoxt.imp.runtime.parser.SGLRParseController.parse(SGLRParseController.java:1)
at org.strategoxt.imp.runtime.dynamicloading.DynamicParseController.parse(DynamicParseController.java:166)
at org.eclipse.imp.editor.ParserScheduler.run(ParserScheduler.java:86)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)Locked ownable synchronizers:
- <0x176f5b08> (a java.util.concurrent.locks.ReentrantLock$FairSync)And this thread got the parseLock and is trying to acquire the “Eclipse lock”…
hopefully fixed marker-related deadlocks as off r21762
Log in to post comments