Skip to content

Commit af21bdc

Browse files
committed
Sporadic "Widget is disposed" exception in ToolBarManagerRenderer
In case the toolbar item is contributed via an extension point, it might happen that the corresponding widget is disposed, immediately after creation. To avoid any errors further down the invocation chain, the call to createWidget() must then return null, rather than the invalid widget. One use-case where this might happen is if the handler bound to this toolbar item tries to access the workbench window. If the window hasn't been created yet, this can force a recreation of the toolbar, disposing the current widget in the process. See the following commits for similar problems: - 228b669 - e4d8434
1 parent 35844b5 commit af21bdc

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarManagerRenderer.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2009, 2020 IBM Corporation and others.
2+
* Copyright (c) 2009, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -429,13 +429,17 @@ public Object createWidget(final MUIElement element, Object parent) {
429429
IEclipseContext parentContext = getContextForParent(element);
430430

431431
CSSRenderingUtils cssUtils = parentContext.get(CSSRenderingUtils.class);
432-
if (cssUtils != null) {
432+
if (cssUtils != null && !newTB.isDisposed()) {
433433
MUIElement modelElement = (MUIElement) newTB.getData(AbstractPartRenderer.OWNING_ME);
434434
boolean draggable = ((modelElement != null) && (modelElement.getTags().contains(IPresentationEngine.DRAGGABLE)));
435435
renderedCtrl = cssUtils.frameMeIfPossible(newTB, null, vertical, draggable);
436436
}
437437
}
438438

439+
if (renderedCtrl.isDisposed()) {
440+
return null;
441+
}
442+
439443
return renderedCtrl;
440444
}
441445

tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarManagerRendererTest.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2019, 2020 Rolf Theunissen and others.
2+
* Copyright (c) 2019, 2025 Rolf Theunissen and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -21,15 +21,21 @@
2121
import static org.junit.Assert.assertTrue;
2222

2323
import jakarta.inject.Inject;
24+
import java.util.ArrayList;
2425
import java.util.Arrays;
2526
import java.util.List;
27+
import org.eclipse.core.runtime.ILogListener;
28+
import org.eclipse.core.runtime.Platform;
29+
import org.eclipse.e4.core.services.events.IEventBroker;
2630
import org.eclipse.e4.ui.model.application.MApplication;
2731
import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
2832
import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
2933
import org.eclipse.e4.ui.model.application.ui.menu.MDirectToolItem;
3034
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
35+
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
3136
import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
3237
import org.eclipse.e4.ui.tests.rules.WorkbenchContextRule;
38+
import org.eclipse.e4.ui.workbench.UIEvents;
3339
import org.eclipse.e4.ui.workbench.modeling.EModelService;
3440
import org.eclipse.emf.common.util.ECollections;
3541
import org.eclipse.jface.action.Action;
@@ -38,6 +44,7 @@
3844
import org.junit.Before;
3945
import org.junit.Rule;
4046
import org.junit.Test;
47+
import org.osgi.service.event.EventHandler;
4148

4249
public class ToolBarManagerRendererTest {
4350

@@ -50,6 +57,10 @@ public class ToolBarManagerRendererTest {
5057
@Inject
5158
private MApplication application;
5259

60+
@Inject
61+
private IEventBroker eventBroker;
62+
63+
private String toolBarId;
5364
private MToolBar toolBar;
5465
private MTrimmedWindow window;
5566

@@ -61,7 +72,9 @@ public void setUp() throws Exception {
6172
MTrimBar trimBar = ems.createModelElement(MTrimBar.class);
6273
window.getTrimBars().add(trimBar);
6374

75+
toolBarId = "ToolBarManagerRendererTest.toolBar";
6476
toolBar = ems.createModelElement(MToolBar.class);
77+
toolBar.setElementId(toolBarId);
6578
trimBar.getChildren().add(toolBar);
6679
}
6780

@@ -119,6 +132,38 @@ public void testMToolItem_toBeRendered() {
119132
assertTrue(tbm.getItems()[0].isVisible());
120133
}
121134

135+
@Test
136+
public void testMToolBarContribution_toBeRendered() {
137+
List<String> errors = new ArrayList<>();
138+
139+
EventHandler eventHandler = event -> {
140+
if (UIEvents.isADD(event)) {
141+
MToolBar toolbar = (MToolBar) event.getProperty(UIEvents.EventTags.ELEMENT);
142+
toolbar.setToBeRendered(false);
143+
}
144+
};
145+
146+
ILogListener logListener = (status, plugin) -> errors.add(plugin + ":" + status);
147+
148+
try {
149+
Platform.addLogListener(logListener);
150+
eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN, eventHandler);
151+
152+
MToolBarContribution toolContribution = ems.createModelElement(MToolBarContribution.class);
153+
toolContribution.setParentId(toolBarId);
154+
toolContribution.getChildren().add(ems.createModelElement(MDirectToolItem.class));
155+
application.getToolBarContributions().add(toolContribution);
156+
157+
contextRule.createAndRunWorkbench(window);
158+
159+
assertNull(toolBar.getRenderer());
160+
assertTrue("Error(s) occurred while rendering toolbar: " + errors, errors.isEmpty());
161+
} finally {
162+
eventBroker.unsubscribe(eventHandler);
163+
Platform.removeLogListener(logListener);
164+
}
165+
}
166+
122167
@Test
123168
public void testDynamicItem_AddOne() {
124169
contextRule.createAndRunWorkbench(window);

0 commit comments

Comments
 (0)