mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
[298909] - [launch] DSF suspend trigger susceptible to race conditions
This commit is contained in:
parent
47e8b801a0
commit
e31d06b003
10 changed files with 389 additions and 27 deletions
|
@ -345,5 +345,15 @@
|
||||||
id="org.eclipse.cdt.dsf.gdb.ui.GdbDebugTextHover">
|
id="org.eclipse.cdt.dsf.gdb.ui.GdbDebugTextHover">
|
||||||
</hover>
|
</hover>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.debug.ui.contextViewBindings">
|
||||||
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.debug.ui.debugModelContextBindings">
|
||||||
|
<modelContextBinding
|
||||||
|
contextId="org.eclipse.cdt.debug.ui.debugging"
|
||||||
|
debugModelId="org.eclipse.cdt.dsf.gdb">
|
||||||
|
</modelContextBinding>
|
||||||
|
</extension>
|
||||||
|
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -29,7 +29,6 @@ import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepIntoCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepOverCommand;
|
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepOverCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepReturnCommand;
|
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepReturnCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfSuspendCommand;
|
import org.eclipse.cdt.dsf.debug.ui.actions.DsfSuspendCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.contexts.DsfSuspendTrigger;
|
|
||||||
import org.eclipse.cdt.dsf.debug.ui.sourcelookup.DsfSourceDisplayAdapter;
|
import org.eclipse.cdt.dsf.debug.ui.sourcelookup.DsfSourceDisplayAdapter;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
|
import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.DefaultRefreshAllTarget;
|
import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.DefaultRefreshAllTarget;
|
||||||
|
@ -99,7 +98,7 @@ public class GdbAdapterFactory
|
||||||
final GdbConnectCommand fConnectCommand;
|
final GdbConnectCommand fConnectCommand;
|
||||||
final GdbDisconnectCommand fDisconnectCommand;
|
final GdbDisconnectCommand fDisconnectCommand;
|
||||||
final IDebugModelProvider fDebugModelProvider;
|
final IDebugModelProvider fDebugModelProvider;
|
||||||
final DsfSuspendTrigger fSuspendTrigger;
|
final GdbSuspendTrigger fSuspendTrigger;
|
||||||
final GdbSteppingModeTarget fSteppingModeTarget;
|
final GdbSteppingModeTarget fSteppingModeTarget;
|
||||||
final IModelSelectionPolicyFactory fModelSelectionPolicyFactory;
|
final IModelSelectionPolicyFactory fModelSelectionPolicyFactory;
|
||||||
final SteppingController fSteppingController;
|
final SteppingController fSteppingController;
|
||||||
|
@ -137,7 +136,7 @@ public class GdbAdapterFactory
|
||||||
fTerminateCommand = new DsfTerminateCommand(session);
|
fTerminateCommand = new DsfTerminateCommand(session);
|
||||||
fConnectCommand = new GdbConnectCommand(session);
|
fConnectCommand = new GdbConnectCommand(session);
|
||||||
fDisconnectCommand = new GdbDisconnectCommand(session);
|
fDisconnectCommand = new GdbDisconnectCommand(session);
|
||||||
fSuspendTrigger = new DsfSuspendTrigger(session, fLaunch);
|
fSuspendTrigger = new GdbSuspendTrigger(session, fLaunch);
|
||||||
fModelSelectionPolicyFactory = new DefaultDsfModelSelectionPolicyFactory();
|
fModelSelectionPolicyFactory = new DefaultDsfModelSelectionPolicyFactory();
|
||||||
fRefreshAllTarget = new DefaultRefreshAllTarget();
|
fRefreshAllTarget = new DefaultRefreshAllTarget();
|
||||||
fReverseToggleTarget = new GdbReverseToggleCommand(session);
|
fReverseToggleTarget = new GdbReverseToggleCommand(session);
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.internal.ui;
|
||||||
|
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
|
import org.eclipse.cdt.dsf.debug.ui.contexts.DsfSuspendTrigger;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class GdbSuspendTrigger extends DsfSuspendTrigger {
|
||||||
|
|
||||||
|
public GdbSuspendTrigger(DsfSession session, ILaunch launch) {
|
||||||
|
super(session, launch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void getLaunchTopContainers(final DataRequestMonitor<IContainerDMContext[]> rm) {
|
||||||
|
try {
|
||||||
|
getSession().getExecutor().execute(new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
IProcesses processService = getServicesTracker().getService(IProcesses.class);
|
||||||
|
ICommandControlService controlService = getServicesTracker().getService(ICommandControlService.class);
|
||||||
|
if (processService == null || controlService == null) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Not available", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
processService.getProcessesBeingDebugged(
|
||||||
|
controlService.getContext(),
|
||||||
|
new DataRequestMonitor<IDMContext[]>(ImmediateExecutor.getInstance(), rm) {
|
||||||
|
@Override
|
||||||
|
public void handleSuccess() {
|
||||||
|
IContainerDMContext[] containers = new IContainerDMContext[getData().length];
|
||||||
|
for (int i = 0; i < containers.length; i++) {
|
||||||
|
if (getData()[i] instanceof IContainerDMContext) {
|
||||||
|
containers[i] = (IContainerDMContext)getData()[i];
|
||||||
|
} else {
|
||||||
|
// By convention the processes should be containers, but the API
|
||||||
|
// does not enforce this.
|
||||||
|
assert false;
|
||||||
|
rm.setData(new IContainerDMContext[0]);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
rm.setData(containers);
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Not available", e)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,11 +13,19 @@ package org.eclipse.cdt.dsf.debug.ui.contexts;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
|
import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
|
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.ISafeRunnable;
|
import org.eclipse.core.runtime.ISafeRunnable;
|
||||||
|
@ -45,8 +53,9 @@ public class DsfSuspendTrigger implements ISuspendTrigger {
|
||||||
|
|
||||||
private final DsfSession fSession;
|
private final DsfSession fSession;
|
||||||
private final ILaunch fLaunch;
|
private final ILaunch fLaunch;
|
||||||
private boolean fDisposed = false;
|
private volatile boolean fDisposed = false;
|
||||||
private boolean fEventListenerRegisterd = false;
|
private boolean fEventListenerRegisterd = false;
|
||||||
|
private final DsfServicesTracker fServicesTracker;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
private final ListenerList fListeners = new ListenerList();
|
private final ListenerList fListeners = new ListenerList();
|
||||||
|
@ -55,6 +64,7 @@ public class DsfSuspendTrigger implements ISuspendTrigger {
|
||||||
public DsfSuspendTrigger(DsfSession session, ILaunch launch) {
|
public DsfSuspendTrigger(DsfSession session, ILaunch launch) {
|
||||||
fSession = session;
|
fSession = session;
|
||||||
fLaunch = launch;
|
fLaunch = launch;
|
||||||
|
fServicesTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), fSession.getId());
|
||||||
try {
|
try {
|
||||||
fSession.getExecutor().execute(new DsfRunnable() {
|
fSession.getExecutor().execute(new DsfRunnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -68,28 +78,93 @@ public class DsfSuspendTrigger implements ISuspendTrigger {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public void addSuspendTriggerListener(ISuspendTriggerListener listener) {
|
public void addSuspendTriggerListener(final ISuspendTriggerListener listener) {
|
||||||
if (fListeners != null) {
|
|
||||||
fListeners.add(listener);
|
fListeners.add(listener);
|
||||||
|
|
||||||
|
// Check if an execution context in the model is already suspended.
|
||||||
|
// If so notify the listener.
|
||||||
|
getIsLaunchSuspended(new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (!fDisposed && getData().booleanValue()) {
|
||||||
|
listener.suspended(fLaunch, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public void removeSuspendTriggerListener(ISuspendTriggerListener listener) {
|
public void removeSuspendTriggerListener(ISuspendTriggerListener listener) {
|
||||||
if (fListeners != null) {
|
|
||||||
fListeners.remove(listener);
|
fListeners.remove(listener);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@ThreadSafe
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (fEventListenerRegisterd) {
|
if (fEventListenerRegisterd) {
|
||||||
fSession.removeServiceEventListener(this);
|
fSession.removeServiceEventListener(this);
|
||||||
}
|
}
|
||||||
|
fServicesTracker.dispose();
|
||||||
fDisposed = true;
|
fDisposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
|
*/
|
||||||
@DsfServiceEventHandler
|
@DsfServiceEventHandler
|
||||||
public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
|
public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
|
||||||
|
fireSuspended(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
|
*/
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(DataModelInitializedEvent e) {
|
||||||
|
getIsLaunchSuspended(new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (!fDisposed && getData().booleanValue()) {
|
||||||
|
fireSuspended(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the services tracker used by the suspend trigger.
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
protected DsfServicesTracker getServicesTracker() {
|
||||||
|
return fServicesTracker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the launch for this suspend trigger.
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
@ThreadSafe
|
||||||
|
protected ILaunch getLaunch() {
|
||||||
|
return fLaunch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the DSF session for this suspend trigger.
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
@ThreadSafe
|
||||||
|
protected DsfSession getSession() {
|
||||||
|
return fSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the listeners that a suspend event was received.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
@ThreadSafe
|
||||||
|
protected void fireSuspended(final Object context) {
|
||||||
final Object[] listeners = fListeners.getListeners();
|
final Object[] listeners = fListeners.getListeners();
|
||||||
if (listeners.length != 0) {
|
if (listeners.length != 0) {
|
||||||
new Job("DSF Suspend Trigger Notify") { //$NON-NLS-1$
|
new Job("DSF Suspend Trigger Notify") { //$NON-NLS-1$
|
||||||
|
@ -104,7 +179,7 @@ public class DsfSuspendTrigger implements ISuspendTrigger {
|
||||||
final ISuspendTriggerListener listener = (ISuspendTriggerListener) listeners[i];
|
final ISuspendTriggerListener listener = (ISuspendTriggerListener) listeners[i];
|
||||||
SafeRunner.run(new ISafeRunnable() {
|
SafeRunner.run(new ISafeRunnable() {
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
listener.suspended(fLaunch, null);
|
listener.suspended(fLaunch, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleException(Throwable exception) {
|
public void handleException(Throwable exception) {
|
||||||
|
@ -120,4 +195,144 @@ public class DsfSuspendTrigger implements ISuspendTrigger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the top-level containers for this launch. This method should
|
||||||
|
* be overriden by specific debugger integrations.
|
||||||
|
* @param rm
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
@ThreadSafe
|
||||||
|
protected void getLaunchTopContainers(DataRequestMonitor<IContainerDMContext[]> rm) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given launch is currently suspended.
|
||||||
|
*
|
||||||
|
* @param rm Request monitor.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
@ThreadSafe
|
||||||
|
private void getIsLaunchSuspended(final DataRequestMonitor<Boolean> rm) {
|
||||||
|
getLaunchTopContainers(new DataRequestMonitor<IContainerDMContext[]>(fSession.getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
final CountingRequestMonitor crm = new CountingRequestMonitor(fSession.getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (rm.getData() == null) {
|
||||||
|
rm.setData(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
int count = 0;
|
||||||
|
for (final IContainerDMContext containerCtx : getData()) {
|
||||||
|
getIsContainerSuspended(containerCtx, new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), crm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (getData().booleanValue()) {
|
||||||
|
rm.setData(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
crm.done();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
crm.setDoneCount(count);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively checks if the given container or any of its execution
|
||||||
|
* contexts are suspended.
|
||||||
|
*
|
||||||
|
* @param container Container to check.
|
||||||
|
* @param rm Request monitor.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
@ConfinedToDsfExecutor("fSession.getExecutor()")
|
||||||
|
private void getIsContainerSuspended(final IContainerDMContext container, final DataRequestMonitor<Boolean> rm) {
|
||||||
|
// Check if run control service is still available.
|
||||||
|
IRunControl rc = fServicesTracker.getService(IRunControl.class);
|
||||||
|
if (rc == null) {
|
||||||
|
rm.setData(Boolean.FALSE);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if container is suspended. If so, stop searching.
|
||||||
|
if (rc.isSuspended(container)) {
|
||||||
|
rm.setData(Boolean.TRUE);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the execution contexts and check if any of them are suspended.
|
||||||
|
rc.getExecutionContexts(
|
||||||
|
container,
|
||||||
|
new DataRequestMonitor<IExecutionDMContext[]>(fSession.getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
// Check if run control service is still available.
|
||||||
|
IRunControl rc = fServicesTracker.getService(IRunControl.class);
|
||||||
|
if (rc == null) {
|
||||||
|
rm.setData(Boolean.FALSE);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any of the execution contexts are suspended, stop searching
|
||||||
|
boolean hasContainers = false;
|
||||||
|
for (IExecutionDMContext execCtx : getData()) {
|
||||||
|
if (rc.isSuspended(execCtx)) {
|
||||||
|
rm.setData(Boolean.TRUE);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hasContainers = hasContainers || execCtx instanceof IContainerDMContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any of the returned contexts were containers, check them recursively.
|
||||||
|
if (hasContainers) {
|
||||||
|
final CountingRequestMonitor crm = new CountingRequestMonitor(fSession.getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (rm.getData() == null) {
|
||||||
|
rm.setData(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
int count = 0;
|
||||||
|
for (IExecutionDMContext execCtx : getData()) {
|
||||||
|
if (execCtx instanceof IContainerDMContext) {
|
||||||
|
getIsContainerSuspended(
|
||||||
|
(IContainerDMContext)execCtx,
|
||||||
|
new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), crm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (getData().booleanValue()) {
|
||||||
|
rm.setData(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
crm.done();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crm.setDoneCount(count);
|
||||||
|
} else {
|
||||||
|
rm.setData(Boolean.FALSE);
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
point="org.eclipse.debug.ui.contextViewBindings">
|
point="org.eclipse.debug.ui.contextViewBindings">
|
||||||
<contextViewBinding
|
<contextViewBinding
|
||||||
contextId="org.eclipse.cdt.examples.dsf.pda.debugging"
|
contextId="org.eclipse.cdt.examples.dsf.pda.debugging"
|
||||||
viewId="org.eclipse.cdt.examples.dsf.pda.dataStackView"/>
|
viewId="org.eclipse.debug.ui.ExpressionView"/>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
||||||
<extension
|
<extension
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.examples.dsf.pda.ui;
|
||||||
|
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.ui.contexts.DsfSuspendTrigger;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.cdt.examples.dsf.pda.service.PDACommandControl;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class PDASuspendTrigger extends DsfSuspendTrigger {
|
||||||
|
|
||||||
|
public PDASuspendTrigger(DsfSession session, ILaunch launch) {
|
||||||
|
super(session, launch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void getLaunchTopContainers(final DataRequestMonitor<IContainerDMContext[]> rm) {
|
||||||
|
try {
|
||||||
|
getSession().getExecutor().execute(new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
PDACommandControl control =
|
||||||
|
getServicesTracker().getService(PDACommandControl.class);
|
||||||
|
if (control != null) {
|
||||||
|
rm.setData(new IContainerDMContext[] { control.getContext() });
|
||||||
|
} else {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, PDAUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Not available", null));
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, PDAUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Not available", e));
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,24 +10,19 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.examples.dsf.pda.ui;
|
package org.eclipse.cdt.examples.dsf.pda.ui;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfResumeCommand;
|
import org.eclipse.cdt.dsf.debug.ui.actions.DsfResumeCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepIntoCommand;
|
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepIntoCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepOverCommand;
|
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepOverCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepReturnCommand;
|
import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepReturnCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfSuspendCommand;
|
import org.eclipse.cdt.dsf.debug.ui.actions.DsfSuspendCommand;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.contexts.DsfSuspendTrigger;
|
|
||||||
import org.eclipse.cdt.dsf.debug.ui.sourcelookup.DsfSourceDisplayAdapter;
|
import org.eclipse.cdt.dsf.debug.ui.sourcelookup.DsfSourceDisplayAdapter;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
|
import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory;
|
import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.DefaultDsfSelectionPolicy;
|
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
|
||||||
import org.eclipse.cdt.examples.dsf.pda.PDAPlugin;
|
import org.eclipse.cdt.examples.dsf.pda.PDAPlugin;
|
||||||
import org.eclipse.cdt.examples.dsf.pda.launch.PDALaunch;
|
import org.eclipse.cdt.examples.dsf.pda.launch.PDALaunch;
|
||||||
import org.eclipse.cdt.examples.dsf.pda.ui.actions.PDATerminateCommand;
|
import org.eclipse.cdt.examples.dsf.pda.ui.actions.PDATerminateCommand;
|
||||||
import org.eclipse.cdt.examples.dsf.pda.ui.viewmodel.PDAVMAdapter;
|
import org.eclipse.cdt.examples.dsf.pda.ui.viewmodel.PDAVMAdapter;
|
||||||
import org.eclipse.debug.core.ILaunch;
|
|
||||||
import org.eclipse.debug.core.commands.IResumeHandler;
|
import org.eclipse.debug.core.commands.IResumeHandler;
|
||||||
import org.eclipse.debug.core.commands.IStepIntoHandler;
|
import org.eclipse.debug.core.commands.IStepIntoHandler;
|
||||||
import org.eclipse.debug.core.commands.IStepOverHandler;
|
import org.eclipse.debug.core.commands.IStepOverHandler;
|
||||||
|
@ -36,10 +31,7 @@ import org.eclipse.debug.core.commands.ISuspendHandler;
|
||||||
import org.eclipse.debug.core.commands.ITerminateHandler;
|
import org.eclipse.debug.core.commands.ITerminateHandler;
|
||||||
import org.eclipse.debug.core.model.IDebugModelProvider;
|
import org.eclipse.debug.core.model.IDebugModelProvider;
|
||||||
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
|
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
|
||||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy;
|
|
||||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicyFactory;
|
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicyFactory;
|
||||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
|
||||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
|
||||||
import org.eclipse.debug.ui.sourcelookup.ISourceDisplay;
|
import org.eclipse.debug.ui.sourcelookup.ISourceDisplay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,7 +51,7 @@ class SessionAdapterSet {
|
||||||
final DsfSuspendCommand fSuspendCommand;
|
final DsfSuspendCommand fSuspendCommand;
|
||||||
final DsfResumeCommand fResumeCommand;
|
final DsfResumeCommand fResumeCommand;
|
||||||
final PDATerminateCommand fTerminateCommand;
|
final PDATerminateCommand fTerminateCommand;
|
||||||
final DsfSuspendTrigger fSuspendTrigger;
|
final PDASuspendTrigger fSuspendTrigger;
|
||||||
|
|
||||||
// Adapters for integration with other UI actions
|
// Adapters for integration with other UI actions
|
||||||
final IDebugModelProvider fDebugModelProvider;
|
final IDebugModelProvider fDebugModelProvider;
|
||||||
|
@ -96,7 +88,7 @@ class SessionAdapterSet {
|
||||||
fSuspendCommand = new DsfSuspendCommand(session);
|
fSuspendCommand = new DsfSuspendCommand(session);
|
||||||
fResumeCommand = new DsfResumeCommand(session);
|
fResumeCommand = new DsfResumeCommand(session);
|
||||||
fTerminateCommand = new PDATerminateCommand(session);
|
fTerminateCommand = new PDATerminateCommand(session);
|
||||||
fSuspendTrigger = new DsfSuspendTrigger(session, fLaunch);
|
fSuspendTrigger = new PDASuspendTrigger(session, fLaunch);
|
||||||
|
|
||||||
session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand);
|
session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand);
|
||||||
session.registerModelAdapter(IStepOverHandler.class, fStepOverCommand);
|
session.registerModelAdapter(IStepOverHandler.class, fStepOverCommand);
|
||||||
|
|
|
@ -12,6 +12,7 @@ package org.eclipse.cdt.examples.dsf.pda.launch;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator;
|
import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.cdt.examples.dsf.pda.service.PDABackend;
|
import org.eclipse.cdt.examples.dsf.pda.service.PDABackend;
|
||||||
|
@ -105,12 +106,18 @@ public class PDAServicesInitSequence extends Sequence {
|
||||||
new PDARegisters(fSession).initialize(requestMonitor);
|
new PDARegisters(fSession).initialize(requestMonitor);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
|
* Indicate that the Data Model has been filled. This will trigger the Debug view to expand.
|
||||||
|
*/
|
||||||
new Step() {
|
new Step() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(RequestMonitor requestMonitor) {
|
public void execute(final RequestMonitor requestMonitor) {
|
||||||
fRunControl.resume(fCommandControl.getContext(), requestMonitor);
|
fSession.dispatchEvent(
|
||||||
|
new DataModelInitializedEvent(fCommandControl.getContext()),
|
||||||
|
fCommandControl.getProperties());
|
||||||
|
requestMonitor.done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sequence input parameters, used in initializing services.
|
// Sequence input parameters, used in initializing services.
|
||||||
|
|
|
@ -192,6 +192,7 @@ public class PDAExpressions extends AbstractDsfService implements ICachingServic
|
||||||
fCommandControl = getServicesTracker().getService(PDACommandControl.class);
|
fCommandControl = getServicesTracker().getService(PDACommandControl.class);
|
||||||
fStack = getServicesTracker().getService(PDAStack.class);
|
fStack = getServicesTracker().getService(PDAStack.class);
|
||||||
fCommandCache = new CommandCache(getSession(), fCommandControl);
|
fCommandCache = new CommandCache(getSession(), fCommandControl);
|
||||||
|
fCommandCache.setContextAvailable(fCommandControl.getContext(), true);
|
||||||
|
|
||||||
getSession().addServiceEventListener(this, null);
|
getSession().addServiceEventListener(this, null);
|
||||||
|
|
||||||
|
|
|
@ -207,6 +207,7 @@ public class PDAStack extends AbstractDsfService implements IStack, ICachingServ
|
||||||
|
|
||||||
// Create the commands cache
|
// Create the commands cache
|
||||||
fCommandCache = new CommandCache(getSession(), fCommandControl);
|
fCommandCache = new CommandCache(getSession(), fCommandControl);
|
||||||
|
fCommandCache.setContextAvailable(fCommandControl.getContext(), true);
|
||||||
|
|
||||||
// Register to listen for run control events, to clear cache accordingly.
|
// Register to listen for run control events, to clear cache accordingly.
|
||||||
getSession().addServiceEventListener(this, null);
|
getSession().addServiceEventListener(this, null);
|
||||||
|
|
Loading…
Add table
Reference in a new issue