Skip to content

Commit db5af16

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 db5af16

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

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

+6-2
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 != null && 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

+51-1
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,23 +21,31 @@
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;
3642
import org.eclipse.jface.action.ActionContributionItem;
3743
import org.eclipse.jface.action.ToolBarManager;
44+
import org.eclipse.swt.SWTException;
3845
import org.junit.Before;
3946
import org.junit.Rule;
4047
import org.junit.Test;
48+
import org.osgi.service.event.EventHandler;
4149

4250
public class ToolBarManagerRendererTest {
4351

@@ -50,6 +58,10 @@ public class ToolBarManagerRendererTest {
5058
@Inject
5159
private MApplication application;
5260

61+
@Inject
62+
private IEventBroker eventBroker;
63+
64+
private String toolBarId;
5365
private MToolBar toolBar;
5466
private MTrimmedWindow window;
5567

@@ -61,7 +73,9 @@ public void setUp() throws Exception {
6173
MTrimBar trimBar = ems.createModelElement(MTrimBar.class);
6274
window.getTrimBars().add(trimBar);
6375

76+
toolBarId = "ToolBarManagerRendererTest.toolBar";
6477
toolBar = ems.createModelElement(MToolBar.class);
78+
toolBar.setElementId(toolBarId);
6579
trimBar.getChildren().add(toolBar);
6680
}
6781

@@ -119,6 +133,42 @@ public void testMToolItem_toBeRendered() {
119133
assertTrue(tbm.getItems()[0].isVisible());
120134
}
121135

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

0 commit comments

Comments
 (0)