From 0794acbd0f43271c4ac01cb4862cd018069aa8a4 Mon Sep 17 00:00:00 2001 From: Ed Swartz Date: Mon, 29 Mar 2010 13:43:38 +0000 Subject: [PATCH] Fix problems accessing IExpressions2 outside executor thread (bug 306553) --- .../ui/viewmodel/DsfCastToTypeSupport.java | 48 ++++++++++++++++++- .../expression/ExpressionVMProvider.java | 29 ++++++++--- .../variable/VariableVMProvider.java | 26 ++++++++-- 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/DsfCastToTypeSupport.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/DsfCastToTypeSupport.java index a0b23a5566a..bb0285e1156 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/DsfCastToTypeSupport.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/DsfCastToTypeSupport.java @@ -13,10 +13,13 @@ package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ExecutionException; import org.eclipse.cdt.debug.core.model.ICastToArray; import org.eclipse.cdt.debug.core.model.ICastToType; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionChangedDMEvent; @@ -57,8 +60,51 @@ public class DsfCastToTypeSupport { this.memento = createCastedExpressionMemento(exprDMC); } + public class TestExpressions2Query extends Query { + + public TestExpressions2Query() { + super(); + } + + @Override + protected void execute(final DataRequestMonitor rm) { + /* + * We're in another dispatch, so we must guard against executor + * shutdown again. + */ + final DsfSession session = DsfSession.getSession( + dmvmProvider.getSession().getId()); + if (session == null) { + cancel(false); + rm.done(); + return; + } + + DsfServicesTracker tracker = new DsfServicesTracker( + DsfUIPlugin.getBundleContext(), dmvmProvider.getSession().getId()); + IExpressions2 expressions2 = tracker.getService(IExpressions2.class); + rm.setData(expressions2 != null); + rm.done(); + tracker.dispose(); + } + } + private boolean isValid() { - return (serviceTracker.getService(IExpressions2.class) != null && exprDMC != null); + TestExpressions2Query query = new TestExpressions2Query(); + dmvmProvider.getSession().getExecutor().execute(query); + + try { + /* + * Return value is irrelevant, any error would come through with an + * exception. + */ + return query.get(); + } catch (InterruptedException e) { + assert false; + return false; + } catch (ExecutionException e) { + return false; + } } private void throwIfNotValid() throws DebugException { diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java index 2b72628f2ac..cebf3137d1c 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java @@ -248,12 +248,10 @@ public class ExpressionVMProvider extends AbstractDMVMProvider VariableVMNode variableNode = new VariableVMNode(this, getSession(), syncvarDataAccess); addChildNodes(variableNode, new IExpressionVMNode[] {variableNode}); - /* Wire up the casting support if the IExpressions2 service is available. */ - DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId()); - IExpressions2 expressions2 = tracker.getService(IExpressions2.class); - if (expressions2 != null) { - variableNode.setCastToTypeSupport(new DsfCastToTypeSupport(getSession(), this, syncvarDataAccess)); - } + /* + * Hook up IExpressions2 if it exists. + */ + hookUpCastingSupport(syncvarDataAccess, variableNode); /* * Tell the expression node which sub-nodes it will directly support. It is very important @@ -273,6 +271,25 @@ public class ExpressionVMProvider extends AbstractDMVMProvider */ setRootNode(rootNode); } + + private void hookUpCastingSupport(final SyncVariableDataAccess syncvarDataAccess, + final VariableVMNode variableNode) { + try { + getSession().getExecutor().execute(new DsfRunnable() { + public void run() { + DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId()); + IExpressions2 expressions2 = tracker.getService(IExpressions2.class); + if (expressions2 != null) { + variableNode.setCastToTypeSupport(new DsfCastToTypeSupport( + getSession(), ExpressionVMProvider.this, syncvarDataAccess)); + } + tracker.dispose(); + } + }); + } catch (RejectedExecutionException e) { + // Session disposed, ignore. + } + } /** * Finds the expression node which can parse the given expression. This diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java index d80e7761dc1..90f0d771973 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java @@ -101,17 +101,33 @@ public class VariableVMProvider extends AbstractDMVMProvider addChildNodes(rootNode, new IVMNode[] { subExpressioNode }); // Wire up the casting support if the IExpressions2 service is available. - DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId()); - IExpressions2 expressions2 = tracker.getService(IExpressions2.class); - if (expressions2 != null) { - subExpressioNode.setCastToTypeSupport(new DsfCastToTypeSupport(getSession(), this, varAccess)); - } + hookUpCastingSupport(varAccess, subExpressioNode); // Configure the sub-expression node to be a child of itself. This way the content // provider will recursively drill-down the variable hierarchy. addChildNodes(subExpressioNode, new IVMNode[] { subExpressioNode }); } + private void hookUpCastingSupport(final SyncVariableDataAccess syncvarDataAccess, + final VariableVMNode variableNode) { + try { + getSession().getExecutor().execute(new DsfRunnable() { + public void run() { + DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId()); + IExpressions2 expressions2 = tracker.getService(IExpressions2.class); + if (expressions2 != null) { + variableNode.setCastToTypeSupport(new DsfCastToTypeSupport( + getSession(), VariableVMProvider.this, syncvarDataAccess)); + } + tracker.dispose(); + } + }); + } catch (RejectedExecutionException e) { + // Session disposed, ignore. + } + } + + @Override public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) { return new VariableColumnPresentation();