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.2

Stack trace:
http://pastebin.com/Wy5jkhBr

Submitted by Nathan Bruning on 17 September 2010 at 12:50

On 18 September 2010 at 14:17 Lennart Kats commented:

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 the Environment 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.


On 23 September 2010 at 14:35 Tobi Vollebregt commented:

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

http://pastebin.com/NfMpba9Q


On 23 September 2010 at 15:06 Lennart Kats commented:

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.


On 29 September 2010 at 10:59 Lennart Kats commented:

The following issues provide more details about a way to reproduce this issue: Spoofax/260, Spoofax/329.


On 25 January 2011 at 16:42 Tobi Vollebregt commented:

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 in textChanged if content completion was to be skipped because it was a reentrant call to textChanged. 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 :)


On 25 January 2011 at 17:02 Lennart Kats commented:

@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!)


On 25 January 2011 at 17:11 Lennart Kats commented:

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.


On 27 January 2011 at 11:30 Tobi Vollebregt commented:

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”…


On 30 January 2011 at 16:03 Tobi Vollebregt closed this issue.

On 30 January 2011 at 16:03 Tobi Vollebregt commented:

hopefully fixed marker-related deadlocks as off r21762


On 30 January 2011 at 16:03 Tobi Vollebregt tagged @tvo

On 30 January 2011 at 16:03 Tobi Vollebregt removed tag !tvo

On 23 March 2011 at 14:56 Tobi Vollebregt tagged completion

On 31 March 2011 at 10:27 Lennart Kats removed tag 1.3

On 31 March 2011 at 10:27 Lennart Kats tagged 1.0

On 22 February 2012 at 17:20 Lennart Kats removed tag rfc

Log in to post comments