Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 324033 - NPE thrown when resetting perspective
Summary: NPE thrown when resetting perspective
Status: RESOLVED WORKSFORME
Alias: None
Product: e4
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 1.0   Edit
Hardware: PC Linux-GTK
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2010-08-30 17:05 EDT by Remy Suen CLA
Modified: 2019-06-05 07:36 EDT (History)
0 users

See Also:


Attachments
PartRenderingEngine tests patch v1 (2.56 KB, patch)
2010-08-30 17:59 EDT, Remy Suen CLA
no flags Details | Diff
Prevent *all* 'createGui' action while processing 'removeGui' (3.15 KB, patch)
2010-08-31 14:50 EDT, Eric Moffatt CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Remy Suen CLA 2010-08-30 17:05:25 EDT
It seems to me as though the part in question was never actually disposed properly.

1. Window > Reset Perspective
2. An NPE is logged.

java.lang.NullPointerException
	at org.eclipse.e4.ui.workbench.renderers.swt.ContributedPartRenderer.createWidget(ContributedPartRenderer.java:51)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createWidget(PartRenderingEngine.java:578)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:420)
	at org.eclipse.e4.ui.workbench.renderers.swt.ElementReferenceRenderer.createWidget(ElementReferenceRenderer.java:69)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createWidget(PartRenderingEngine.java:578)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:420)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:496)
	at org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer.showTab(StackRenderer.java:512)
	at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer$1.handleEvent(LazyStackRenderer.java:75)
	at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:41)
	at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:188)
	at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:198)
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
	at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:149)
	at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:139)
	at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78)
	at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39)
	at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:73)
	at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:58)
	at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:380)
	at org.eclipse.e4.ui.model.application.ui.impl.ElementContainerImpl.setSelectedElement(ElementContainerImpl.java:159)
	at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer.postProcess(LazyStackRenderer.java:112)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:436)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:496)
	at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:58)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:432)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:496)
	at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:58)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:432)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:496)
	at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:58)
	at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveRenderer.processContents(PerspectiveRenderer.java:59)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:432)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:496)
	at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveStackRenderer.showTab(PerspectiveStackRenderer.java:103)
	at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer$1.handleEvent(LazyStackRenderer.java:75)
	at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:41)
	at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:188)
	at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:198)
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
	at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:149)
	at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:139)
	at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78)
	at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39)
	at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:73)
	at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:58)
	at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:380)
	at org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveStackImpl.setSelectedElement(PerspectiveStackImpl.java:134)
	at org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveStackImpl.setSelectedElement(PerspectiveStackImpl.java:1)
	at org.eclipse.ui.internal.WorkbenchPage.setPerspective(WorkbenchPage.java:2327)
	at org.eclipse.ui.internal.WorkbenchPage.resetPerspective(WorkbenchPage.java:2152)
	at org.eclipse.ui.internal.ResetPerspectiveAction.run(ResetPerspectiveAction.java:59)
	at org.eclipse.ui.internal.PerspectiveAction.run(PerspectiveAction.java:70)
	at org.eclipse.jface.action.Action.runWithEvent(Action.java:498)
Comment 1 Remy Suen CLA 2010-08-30 17:35:53 EDT
Because the StackRenderer forces the selection from the 'Declaration' view back to the 'Problems' view during the perspective's destruction process, we end up inadvertently rerendering the 'Problems' view a second time.

The view's widget is then disposed and unbound when the perspective's widget is destroyed but the rest of its information remains with the MPart (like its context). The context however is stale because it was parented off the perspective that was just destroyed, so we can't get anything useful out of it and end up with the NPE outlined in comment 0.

Thread [main] (Suspended (breakpoint at line 363 in PartRenderingEngine))	
	PartRenderingEngine.createGui(MUIElement, Object, IEclipseContext) line: 363	
	PartRenderingEngine.createGui(MUIElement) line: 496	
	StackRenderer.showTab(MUIElement) line: 512	
	LazyStackRenderer$1.handleEvent(Event) line: 75	
	UIEventHandler.handleEvent(Event) line: 41	
	EventHandlerWrapper.handleEvent(Event, Permission) line: 188	
	EventHandlerTracker.dispatchEvent(Object, Object, int, Object) line: 198	
	EventManager.dispatchEvent(Set, EventDispatcher, int, Object) line: 227	
	ListenerQueue.dispatchEventSynchronous(int, Object) line: 149	
	EventAdminImpl.dispatchEvent(Event, boolean) line: 139	
	EventAdminImpl.sendEvent(Event) line: 78	
	EventComponent.sendEvent(Event) line: 39	
	EventBroker.send(String, Object) line: 73	
	UIEventPublisher.notifyChanged(Notification) line: 58	
	PartStackImpl(BasicNotifierImpl).eNotify(Notification) line: 380	
	PartStackImpl(ElementContainerImpl<T>).setSelectedElement(T) line: 159	
	StackRenderer.hideChild(MElementContainer<MUIElement>, MUIElement) line: 421	
	PartRenderingEngine.removeGui(MUIElement) line: 523	
	PartRenderingEngine.removeGui(MUIElement) line: 535	
	PartRenderingEngine.removeGui(MUIElement) line: 535	
	PartRenderingEngine.removeGui(MUIElement) line: 535	
	PartRenderingEngine.removeGui(MUIElement) line: 535	
	PartRenderingEngine$1.handleEvent(Event) line: 129	
	UIEventHandler.handleEvent(Event) line: 41	
	EventHandlerWrapper.handleEvent(Event, Permission) line: 188	
	EventHandlerTracker.dispatchEvent(Object, Object, int, Object) line: 198	
	EventManager.dispatchEvent(Set, EventDispatcher, int, Object) line: 227	
	ListenerQueue.dispatchEventSynchronous(int, Object) line: 149	
	EventAdminImpl.dispatchEvent(Event, boolean) line: 139	
	EventAdminImpl.sendEvent(Event) line: 78	
	EventComponent.sendEvent(Event) line: 39	
	EventBroker.send(String, Object) line: 73	
	UIEventPublisher.notifyChanged(Notification) line: 58	
	PerspectiveImpl(BasicNotifierImpl).eNotify(Notification) line: 380	
	PerspectiveImpl(UIElementImpl).setToBeRendered(boolean) line: 267	
	ModelServiceImpl.removePerspectiveModel(MPerspective, MWindow) line: 615	
	WorkbenchPage.closePerspective(IPerspectiveDescriptor) line: 1052	
	WorkbenchPage.resetPerspective() line: 2150	
	ResetPerspectiveAction.run(IWorkbenchPage, IPerspectiveDescriptor) line: 59	
	ResetPerspectiveAction(PerspectiveAction).run() line: 70	
	ResetPerspectiveAction(Action).runWithEvent(Event) line: 498
Comment 2 Remy Suen CLA 2010-08-30 17:59:58 EDT
Created attachment 177794 [details]
PartRenderingEngine tests patch v1

The code path described by comment 1 is something that 'removeRoot' should be taking care of but it's not being handled because there are some renegade removeGui(MUIElement) calls to unrendered elements that's causing it to incorrectly record an element and subsequently never unset it because of the early return in the code.
Comment 3 Remy Suen CLA 2010-08-31 09:36:11 EDT
We should probably wrap the entire removeGui(MUIElement) call inside an ISafeRunnable (see bug 323014) to ensure that the field is always set/unset regardless of what ends up happening during the disposal process. This would be akin to using a try/finally block.
Comment 4 Eric Moffatt CLA 2010-08-31 14:50:39 EDT
Created attachment 177875 [details]
Prevent *all* 'createGui' action while processing 'removeGui'


This is basically caused by the StackRenderer trying to maintain a 'selectedElement' so when we call removeGui on the stack it now recurses, calling the stack renderer's 'hideChild' for all of its children, leading to its selecting a new tab and trying to render it.

For now I've simply wired off any attempt to do a 'createGui' while processing 'removeGui' but we should re-examine the StackRenderer's logic here, does it make sense for the renderer to 'auto-select' or should this be *only* under specific controller logic?
Comment 5 Eric Moffatt CLA 2010-08-31 14:53:46 EDT
Committed in >20100831. Applied both the test and fix patches.
Comment 6 Eclipse Genie CLA 2019-03-06 14:08:14 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 7 Lars Vogel CLA 2019-06-05 07:36:43 EDT
This is a mass change to close all e4 bugs marked with "stalebug" whiteboard.

If this bug is still valid, please reopen and remove the "stalebug" keyword.