Bug 379093 - NPE in PositionManager.managePosition(..)
Summary: NPE in PositionManager.managePosition(..)
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Text (show other bugs)
Version: 3.8   Edit
Hardware: PC Windows 7
: P3 major (vote)
Target Milestone: 3.8 RC1   Edit
Assignee: Markus Keller CLA
QA Contact:
URL:
Whiteboard:
Keywords: greatbug
Depends on:
Blocks:
 
Reported: 2012-05-10 05:47 EDT by Markus Keller CLA
Modified: 2012-05-11 04:29 EDT (History)
2 users (show)

See Also:
daniel_megert: review+


Attachments
Fix (845 bytes, patch)
2012-05-10 10:31 EDT, Markus Keller CLA
daniel_megert: review+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Keller CLA 2012-05-10 05:47:50 EDT
eclipse.buildId=I20120502-2000
java.fullversion=JRE 1.7.0 IBM J9 2.6 Windows 7 x86-32 20110810_88604 (JIT enabled, AOT enabled)

NPE in PositionManager.managePosition(..). Consequence is that syntax highlighting in the editor is screwed and more exceptions follow when I close the editor.

I can currently reproduce this in my host workbench when I reproduce bug 378948 in the runtime. In the host, I have an exception breakpoint on NullPointerException and all editors closed. When I reproduce the bug in the runtime, the breakpoint is hit. I press F8, and the breakpoint is hit a second time. This second time, org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheEntry is opened and the exceptions are thrown.

I've seen this once or twice before, but I could never reproduce so far. Investigating.

Error
Thu May 10 11:34:47 CEST 2012
An internal error has occurred.

java.lang.NullPointerException
	at org.eclipse.jface.text.PaintManager$PositionManager.managePosition(PaintManager.java:150)
	at org.eclipse.jface.text.source.MatchingCharacterPainter.paint(MatchingCharacterPainter.java:419)
	at org.eclipse.jface.text.source.MatchingCharacterPainter$TextListener.textChanged(MatchingCharacterPainter.java:494)
	at org.eclipse.jface.text.TextViewer.updateTextListeners(TextViewer.java:2830)
	at org.eclipse.jface.text.TextViewer.invalidateTextPresentation(TextViewer.java:3450)
	at org.eclipse.jface.text.TextViewer.initializeWidgetContents(TextViewer.java:3497)
	at org.eclipse.jface.text.TextViewer.setVisibleDocument(TextViewer.java:3536)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.setVisibleDocument(ProjectionViewer.java:716)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer.setVisibleDocument(JavaSourceViewer.java:683)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.executeReplaceVisibleDocument(ProjectionViewer.java:777)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.replaceVisibleDocument(ProjectionViewer.java:765)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.reinitializeProjection(ProjectionViewer.java:1245)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.catchupWithProjectionAnnotationModel(ProjectionViewer.java:959)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.processCatchupRequest(ProjectionViewer.java:877)
	at org.eclipse.jface.text.source.projection.ProjectionViewer$AnnotationModelListener.processModelChanged(ProjectionViewer.java:122)
	at org.eclipse.jface.text.source.projection.ProjectionViewer$AnnotationModelListener.modelChanged(ProjectionViewer.java:114)
	at org.eclipse.jface.text.source.AnnotationModel.fireModelChanged(AnnotationModel.java:613)
	at org.eclipse.jface.text.source.AnnotationModel$InternalModelListener.modelChanged(AnnotationModel.java:262)
	at org.eclipse.jface.text.source.AnnotationModel.fireModelChanged(AnnotationModel.java:613)
	at org.eclipse.jface.text.source.AnnotationModel.fireModelChanged(AnnotationModel.java:579)
	at org.eclipse.jface.text.source.projection.ProjectionAnnotationModel.modifyAnnotations(ProjectionAnnotationModel.java:184)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider.update(DefaultJavaFoldingStructureProvider.java:952)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider.initialize(DefaultJavaFoldingStructureProvider.java:829)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider.handleProjectionEnabled(DefaultJavaFoldingStructureProvider.java:800)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider$ProjectionListener.projectionEnabled(DefaultJavaFoldingStructureProvider.java:681)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.fireProjectionEnabled(ProjectionViewer.java:487)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.enableProjection(ProjectionViewer.java:535)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer.setVisibleDocument(JavaSourceViewer.java:676)
	at org.eclipse.jface.text.TextViewer.setDocument(TextViewer.java:2938)
	at org.eclipse.jface.text.source.SourceViewer.setDocument(SourceViewer.java:642)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.setDocument(ProjectionViewer.java:374)
	at org.eclipse.jface.text.source.SourceViewer.setDocument(SourceViewer.java:590)
	at org.eclipse.ui.texteditor.AbstractTextEditor.initializeSourceViewer(AbstractTextEditor.java:4039)
	at org.eclipse.ui.texteditor.AbstractTextEditor.doSetInput(AbstractTextEditor.java:4227)
	at org.eclipse.ui.texteditor.StatusTextEditor.doSetInput(StatusTextEditor.java:237)
	at org.eclipse.ui.texteditor.AbstractDecoratedTextEditor.doSetInput(AbstractDecoratedTextEditor.java:1481)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.internalDoSetInput(JavaEditor.java:2584)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.doSetInput(JavaEditor.java:2571)
	at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor.doSetInput(CompilationUnitEditor.java:1395)
	at org.eclipse.ui.texteditor.AbstractTextEditor.setInputWithNotify(AbstractTextEditor.java:4286)
	at org.eclipse.ui.texteditor.AbstractTextEditor.setInput(AbstractTextEditor.java:4308)
	at org.eclipse.ui.internal.EditorReference.setInput(EditorReference.java:522)
	at org.eclipse.ui.internal.WorkbenchPage.reuseEditor(WorkbenchPage.java:2748)
	at org.eclipse.debug.internal.ui.sourcelookup.SourceLookupFacility.openEditor(SourceLookupFacility.java:280)
	at org.eclipse.debug.internal.ui.sourcelookup.SourceLookupFacility.display(SourceLookupFacility.java:219)
	at org.eclipse.debug.ui.DebugUITools.displaySource(DebugUITools.java:994)
	at org.eclipse.debug.internal.ui.elements.adapters.StackFrameSourceDisplayAdapter$SourceDisplayJob.runInUIThread(StackFrameSourceDisplayAdapter.java:157)
	at org.eclipse.ui.progress.UIJob$1.run(UIJob.java:95)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4144)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3761)
...

This is followed by an SWTException wrapping this NPE:

Caused by: java.lang.NullPointerException
	at org.eclipse.jface.text.PaintManager$PositionManager.managePosition(PaintManager.java:150)
	at org.eclipse.jface.text.CursorLinePainter.paint(CursorLinePainter.java:233)
	at org.eclipse.jface.text.PaintManager.paint(PaintManager.java:299)
	at org.eclipse.jface.text.PaintManager.access$1(PaintManager.java:297)
	at org.eclipse.jface.text.PaintManager$1.run(PaintManager.java:354)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
	... 23 more

And as last:

org.eclipse.jface.text.BadPositionCategoryException
	at org.eclipse.jface.text.AbstractDocument.addPosition(AbstractDocument.java:362)
	at org.eclipse.core.internal.filebuffers.SynchronizableDocument.addPosition(SynchronizableDocument.java:236)
	at org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingPresenter.updatePresentation(SemanticHighlightingPresenter.java:414)
	at org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingPresenter$1.run(SemanticHighlightingPresenter.java:347)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4144)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3761)
...
Comment 1 Markus Keller CLA 2012-05-10 05:49:50 EDT
Exceptions after closing the editor:

java.lang.NullPointerException
	at org.eclipse.jface.text.PaintManager$PositionManager.unmanagePosition(PaintManager.java:163)
	at org.eclipse.jface.text.source.MatchingCharacterPainter.deactivate(MatchingCharacterPainter.java:192)
	at org.eclipse.jface.text.PaintManager.inputDocumentAboutToBeChanged(PaintManager.java:366)
	at org.eclipse.jface.text.TextViewer.fireInputDocumentAboutToBeChanged(TextViewer.java:2877)
	at org.eclipse.jface.text.TextViewer.setDocument(TextViewer.java:2933)
	at org.eclipse.jface.text.source.SourceViewer.setDocument(SourceViewer.java:642)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.setDocument(ProjectionViewer.java:374)
	at org.eclipse.jface.text.source.SourceViewer.setDocument(SourceViewer.java:576)
	at org.eclipse.jface.text.TextViewer.handleDispose(TextViewer.java:1899)
	at org.eclipse.jface.text.source.SourceViewer.handleDispose(SourceViewer.java:775)
	at org.eclipse.jface.text.source.projection.ProjectionViewer.handleDispose(ProjectionViewer.java:1336)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer.handleDispose(JavaSourceViewer.java:502)
	at org.eclipse.jface.text.TextViewer$2.widgetDisposed(TextViewer.java:1806)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:123)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1062)
	at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:774)
	at org.eclipse.swt.custom.StyledText.handleDispose(StyledText.java:5804)
	at org.eclipse.swt.custom.StyledText$7.handleEvent(StyledText.java:5628)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1058)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:808)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Canvas.releaseChildren(Canvas.java:167)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Widget.dispose(Widget.java:446)
	at org.eclipse.ui.internal.PartPane.dispose(PartPane.java:182)
	at org.eclipse.ui.internal.WorkbenchPartReference.dispose(WorkbenchPartReference.java:681)
	at org.eclipse.ui.internal.WorkbenchPage.disposePart(WorkbenchPage.java:1801)
	at org.eclipse.ui.internal.WorkbenchPage.handleDeferredEvents(WorkbenchPage.java:1505)
	at org.eclipse.ui.internal.WorkbenchPage.deferUpdates(WorkbenchPage.java:1489)
	at org.eclipse.ui.internal.WorkbenchPage.closeEditors(WorkbenchPage.java:1463)
	at org.eclipse.ui.internal.WorkbenchPage.closeEditor(WorkbenchPage.java:1518)
	at org.eclipse.ui.internal.EditorPane.doHide(EditorPane.java:61)
	at org.eclipse.ui.internal.PartStack.close(PartStack.java:537)
	at org.eclipse.ui.internal.EditorStack.close(EditorStack.java:206)
	at org.eclipse.ui.internal.PartStack$1.close(PartStack.java:120)
	at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation$1.handleEvent(TabbedStackPresentation.java:83)
	at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.fireEvent(AbstractTabFolder.java:269)
	at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.fireEvent(AbstractTabFolder.java:278)
	at org.eclipse.ui.internal.presentations.defaultpresentation.DefaultTabFolder.access$1(DefaultTabFolder.java:1)
	at org.eclipse.ui.internal.presentations.defaultpresentation.DefaultTabFolder$1.closeButtonPressed(DefaultTabFolder.java:71)
	at org.eclipse.ui.internal.presentations.PaneFolder.notifyCloseListeners(PaneFolder.java:631)
	at org.eclipse.ui.internal.presentations.PaneFolder$3.close(PaneFolder.java:206)
	at org.eclipse.swt.custom.CTabFolder.onMouse(CTabFolder.java:1599)
	at org.eclipse.swt.custom.CTabFolder$1.handleEvent(CTabFolder.java:261)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4169)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3758)
...

Followed by:

org.eclipse.jface.text.BadPositionCategoryException
	at org.eclipse.jface.text.AbstractDocument.removePositionCategory(AbstractDocument.java:1138)
	at org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingPresenter.releaseDocument(SemanticHighlightingPresenter.java:761)
	at org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingPresenter.uninstall(SemanticHighlightingPresenter.java:667)
	at org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingManager.disable(SemanticHighlightingManager.java:414)
	at org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingManager.uninstall(SemanticHighlightingManager.java:389)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.uninstallSemanticHighlighting(JavaEditor.java:3584)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.dispose(JavaEditor.java:2654)
	at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor.dispose(CompilationUnitEditor.java:1496)
	at org.eclipse.ui.internal.WorkbenchPartReference.doDisposePart(WorkbenchPartReference.java:737)
	at org.eclipse.ui.internal.EditorReference.doDisposePart(EditorReference.java:327)
	at org.eclipse.ui.internal.WorkbenchPartReference.dispose(WorkbenchPartReference.java:684)
	at org.eclipse.ui.internal.WorkbenchPage.disposePart(WorkbenchPage.java:1801)
	at org.eclipse.ui.internal.WorkbenchPage.handleDeferredEvents(WorkbenchPage.java:1505)
	at org.eclipse.ui.internal.WorkbenchPage.deferUpdates(WorkbenchPage.java:1489)
	at org.eclipse.ui.internal.WorkbenchPage.closeEditors(WorkbenchPage.java:1463)
	at org.eclipse.ui.internal.WorkbenchPage.closeEditor(WorkbenchPage.java:1518)
	at org.eclipse.ui.internal.EditorPane.doHide(EditorPane.java:61)
	at org.eclipse.ui.internal.PartStack.close(PartStack.java:537)
	at org.eclipse.ui.internal.EditorStack.close(EditorStack.java:206)
	at org.eclipse.ui.internal.PartStack$1.close(PartStack.java:120)
	at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation$1.handleEvent(TabbedStackPresentation.java:83)
	at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.fireEvent(AbstractTabFolder.java:269)
	at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.fireEvent(AbstractTabFolder.java:278)
	at org.eclipse.ui.internal.presentations.defaultpresentation.DefaultTabFolder.access$1(DefaultTabFolder.java:1)
	at org.eclipse.ui.internal.presentations.defaultpresentation.DefaultTabFolder$1.closeButtonPressed(DefaultTabFolder.java:71)
	at org.eclipse.ui.internal.presentations.PaneFolder.notifyCloseListeners(PaneFolder.java:631)
	at org.eclipse.ui.internal.presentations.PaneFolder$3.close(PaneFolder.java:206)
	at org.eclipse.swt.custom.CTabFolder.onMouse(CTabFolder.java:1599)
	at org.eclipse.swt.custom.CTabFolder$1.handleEvent(CTabFolder.java:261)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4169)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3758)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:27
...
Comment 2 Markus Keller CLA 2012-05-10 06:04:27 EDT
Problem seems to be somewhere in the editor reuse code: 

...
WorkbenchPage.reuseEditor(IReusableEditor, IEditorInput) line: 2748	
SourceLookupFacility.openEditor(ISourceLookupResult, IWorkbenchPage) line: 280	
SourceLookupFacility.display(ISourceLookupResult, IWorkbenchPage) line: 219	
DebugUITools.displaySource(ISourceLookupResult, IWorkbenchPage) line: 994	
StackFrameSourceDisplayAdapter$SourceDisplayJob.runInUIThread(IProgressMonitor) line: 157	
...
Comment 3 Markus Keller CLA 2012-05-10 10:31:30 EDT
Created attachment 215403 [details]
Fix

The bug is only reproducible with "Enclosing brackets" highlighting enabled. 

Problem is in MatchingCharacterPainter.TextListener: The listener does nothing on #inputDocumentAboutToBeChanged(..) and is then in a bad state when #textChanged(..) is called while MatchingCharacterPainter#fDocument still refers to the old document. The problem is not the first #textChanged(..) callback, but a later one that is triggered by the DefaultJavaFoldingStructureProvider.

I have trouble finding a simpler setup to reproduce. The hard part is to find documents where MatchingCharacterPainter#paint(int) gets a 'selection' for which 'pair' is eventually set to a non-null region. In that case, fIsActive is false, so the last branch of the #paint(int) method is executed -- but at that point, the fPaintPositionManager's fDocument is null.

The fix is trivial: We just have to do fDocument= null; in #inputDocumentAboutToBeChanged(..). This is safe since fDocument is allowed to be null and #paint(int) performs a quick exit in that case.
Comment 4 Dani Megert CLA 2012-05-10 10:45:43 EDT
Comment on attachment 215403 [details]
Fix

The fix is good and simply applies a common pattern.

Discussed with Markus: 'fDocumentChanged' does not need to be set, because it's not a threading issue and it suffices to set it in 'inputDocumentChanged(...)' only.
Comment 6 Dani Megert CLA 2012-05-11 04:29:20 EDT
Verified in I20120510-2100 through code inspection.