mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 09:46:02 +02:00
[305178] Handling of failure cases when interrupting the target.
This commit is contained in:
parent
2edac02083
commit
2ff6a31767
6 changed files with 209 additions and 43 deletions
|
@ -36,7 +36,9 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
|
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl.InitializationShutdownStep;
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl.InitializationShutdownStep;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MISignalEvent;
|
||||||
import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.cdt.utils.spawner.ProcessFactory;
|
import org.eclipse.cdt.utils.spawner.ProcessFactory;
|
||||||
import org.eclipse.cdt.utils.spawner.Spawner;
|
import org.eclipse.cdt.utils.spawner.Spawner;
|
||||||
|
@ -99,6 +101,14 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend {
|
||||||
private int fGDBExitValue;
|
private int fGDBExitValue;
|
||||||
private int fGDBLaunchTimeout = 30;
|
private int fGDBLaunchTimeout = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Job that will set a failed status
|
||||||
|
* in the proper request monitor, if the interrupt
|
||||||
|
* did not succeed after a certain time.
|
||||||
|
*/
|
||||||
|
private MonitorInterruptJob fInterruptFailedJob;
|
||||||
|
|
||||||
|
|
||||||
public GDBBackend(DsfSession session, ILaunchConfiguration lc) {
|
public GDBBackend(DsfSession session, ILaunchConfiguration lc) {
|
||||||
super(session);
|
super(session);
|
||||||
fBackendId = "gdb[" +Integer.toString(fgInstanceCounter++) + "]"; //$NON-NLS-1$//$NON-NLS-2$
|
fBackendId = "gdb[" +Integer.toString(fgInstanceCounter++) + "]"; //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
@ -364,6 +374,20 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public void interrupt(final RequestMonitor rm) {
|
||||||
|
if (fProcess instanceof Spawner) {
|
||||||
|
Spawner gdbSpawner = (Spawner) fProcess;
|
||||||
|
gdbSpawner.interrupt();
|
||||||
|
fInterruptFailedJob = new MonitorInterruptJob(rm);
|
||||||
|
} else {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Cannot interrupt.", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
// destroy() should be supported even if it's not spawner.
|
// destroy() should be supported even if it's not spawner.
|
||||||
if (getState() == State.STARTED) {
|
if (getState() == State.STARTED) {
|
||||||
|
@ -558,6 +582,8 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend {
|
||||||
IGDBBackend.class.getName() },
|
IGDBBackend.class.getName() },
|
||||||
new Hashtable<String,String>());
|
new Hashtable<String,String>());
|
||||||
|
|
||||||
|
getSession().addServiceEventListener(GDBBackend.this, null);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This event is not consumed by any one at present, instead it's
|
* This event is not consumed by any one at present, instead it's
|
||||||
* the GDBControlInitializedDMEvent that's used to indicate that GDB
|
* the GDBControlInitializedDMEvent that's used to indicate that GDB
|
||||||
|
@ -574,6 +600,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend {
|
||||||
@Override
|
@Override
|
||||||
protected void shutdown(RequestMonitor requestMonitor) {
|
protected void shutdown(RequestMonitor requestMonitor) {
|
||||||
unregister();
|
unregister();
|
||||||
|
getSession().removeServiceEventListener(GDBBackend.this);
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -625,4 +652,50 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monitors an ongoing interrupt to be able to properly
|
||||||
|
* deal with the request monitor.
|
||||||
|
*/
|
||||||
|
private class MonitorInterruptJob extends Job {
|
||||||
|
private final RequestMonitor fRequestMonitor;
|
||||||
|
|
||||||
|
public MonitorInterruptJob(RequestMonitor rm) {
|
||||||
|
super("Interrupt monitor job.");
|
||||||
|
setSystem(true);
|
||||||
|
fRequestMonitor = rm;
|
||||||
|
schedule(5000); // Give the interrupt 5 seconds to succeed
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
getExecutor().submit(
|
||||||
|
new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
fRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Interrupt failed.", null)); //$NON-NLS-1$
|
||||||
|
fRequestMonitor.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RequestMonitor getRequestMonitor() { return fRequestMonitor; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must listen for an MI event and not a higher-level ISuspendedEvent.
|
||||||
|
* The reason is that some ISuspendedEvent are not sent when the target stops,
|
||||||
|
* in cases where we don't want to views to update.
|
||||||
|
* For example, if we want to interrupt the target to set a breakpoint,
|
||||||
|
* this interruption is done silently; we will receive the MI event though.
|
||||||
|
*/
|
||||||
|
/** @since 3.0 */
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(final MISignalEvent e) {
|
||||||
|
if (fInterruptFailedJob != null) {
|
||||||
|
if (fInterruptFailedJob.cancel()) {
|
||||||
|
fInterruptFailedJob.getRequestMonitor().done();
|
||||||
|
}
|
||||||
|
fInterruptFailedJob = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,11 +138,11 @@ public class GDBRunControl extends MIRunControl {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
if (getData()) {
|
if (getData()) {
|
||||||
fGdb.interrupt();
|
fGdb.interrupt(rm);
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context cannot be suspended.", null)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context cannot be suspended.", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
}
|
}
|
||||||
rm.done();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,11 +144,11 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
if (getData()) {
|
if (getData()) {
|
||||||
fGdb.interrupt();
|
fGdb.interrupt(rm);
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context cannot be suspended.", null)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context cannot be suspended.", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
}
|
}
|
||||||
rm.done();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,13 +265,17 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A counter of MIRunning/MIStopped events that should be kept silent for the specified thread.
|
* Indicates that the next MIRunning event for this thread should be silenced.
|
||||||
*/
|
*/
|
||||||
private class DisableRunningAndStoppedEvents {
|
private IMIExecutionDMContext fDisableNextRunningEventDmc;
|
||||||
public IMIExecutionDMContext executionDmc = null;
|
/**
|
||||||
public int count = 0;
|
* Indicates that the next MISignal (MIStopped) event for this thread should be silenced.
|
||||||
};
|
*/
|
||||||
private DisableRunningAndStoppedEvents fDisableRunningAndStoppedEvents = new DisableRunningAndStoppedEvents();
|
private IMIExecutionDMContext fDisableNextSignalEventDmc;
|
||||||
|
/**
|
||||||
|
* Stores the silenced MIStopped event in case we need to use it for a failure.
|
||||||
|
*/
|
||||||
|
private MIStoppedEvent fSilencedSignalEvent;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Initialization and shutdown
|
// Initialization and shutdown
|
||||||
|
@ -925,12 +929,22 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
|
|
||||||
fExecutionDmcToSuspend = (IMIExecutionDMContext)getData()[0];
|
fExecutionDmcToSuspend = (IMIExecutionDMContext)getData()[0];
|
||||||
|
|
||||||
// Don't broadcast the coming stopped/running events
|
assert fDisableNextRunningEventDmc == null;
|
||||||
assert fDisableRunningAndStoppedEvents.count == 0;
|
assert fDisableNextSignalEventDmc == null;
|
||||||
fDisableRunningAndStoppedEvents.count++;
|
|
||||||
fDisableRunningAndStoppedEvents.executionDmc = fExecutionDmcToSuspend;
|
// Don't broadcast the next stopped signal event
|
||||||
|
fDisableNextSignalEventDmc = fExecutionDmcToSuspend;
|
||||||
|
|
||||||
|
suspend(fExecutionDmcToSuspend,
|
||||||
|
new RequestMonitor(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleFailure() {
|
||||||
|
// We weren't able to suspend, so abort the operation
|
||||||
|
fDisableNextSignalEventDmc = null;
|
||||||
|
super.handleFailure();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
suspend(fExecutionDmcToSuspend, rm);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -946,15 +960,39 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
@Override
|
@Override
|
||||||
public void execute(final RequestMonitor rm) {
|
public void execute(final RequestMonitor rm) {
|
||||||
if (!fTargetAvailable) {
|
if (!fTargetAvailable) {
|
||||||
assert fDisableRunningAndStoppedEvents.count == 0 || fDisableRunningAndStoppedEvents.count == 1;
|
assert fDisableNextRunningEventDmc == null;
|
||||||
fDisableRunningAndStoppedEvents.count++;
|
fDisableNextRunningEventDmc = fExecutionDmcToSuspend;
|
||||||
fDisableRunningAndStoppedEvents.executionDmc = fExecutionDmcToSuspend;
|
|
||||||
|
|
||||||
// Can't use the resume() call because we 'silently' stopped
|
// Can't use the resume() call because we 'silently' stopped
|
||||||
// so resume() will not know we are actually stopped
|
// so resume() will not know we are actually stopped
|
||||||
fConnection.queueCommand(
|
fConnection.queueCommand(
|
||||||
fCommandFactory.createMIExecContinue(fExecutionDmcToSuspend),
|
fCommandFactory.createMIExecContinue(fExecutionDmcToSuspend),
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
fSilencedSignalEvent = null;
|
||||||
|
super.handleSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleFailure() {
|
||||||
|
// Darn, we're unable to restart the target. Must cleanup!
|
||||||
|
fDisableNextRunningEventDmc = null;
|
||||||
|
|
||||||
|
// We must also sent the Stopped event that we had kept silent
|
||||||
|
if (fSilencedSignalEvent != null) {
|
||||||
|
eventDispatched(fSilencedSignalEvent);
|
||||||
|
fSilencedSignalEvent = null;
|
||||||
|
} else {
|
||||||
|
// Maybe the stopped event didn't arrive yet.
|
||||||
|
// We don't want to silence it anymore
|
||||||
|
fDisableNextSignalEventDmc = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.handleFailure();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// We didn't suspend the thread, so we don't need to resume it
|
// We didn't suspend the thread, so we don't need to resume it
|
||||||
rm.done();
|
rm.done();
|
||||||
|
@ -972,10 +1010,10 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
*/
|
*/
|
||||||
@DsfServiceEventHandler
|
@DsfServiceEventHandler
|
||||||
public void eventDispatched(final MIRunningEvent e) {
|
public void eventDispatched(final MIRunningEvent e) {
|
||||||
if (fDisableRunningAndStoppedEvents.count > 0 &&
|
if (fDisableNextRunningEventDmc != null &&
|
||||||
fDisableRunningAndStoppedEvents.executionDmc.equals(e.getDMContext())) {
|
fDisableNextRunningEventDmc.equals(e.getDMContext())) {
|
||||||
|
|
||||||
fDisableRunningAndStoppedEvents.count--;
|
fDisableNextRunningEventDmc = null;
|
||||||
|
|
||||||
// Don't broadcast the running event
|
// Don't broadcast the running event
|
||||||
return;
|
return;
|
||||||
|
@ -1041,10 +1079,11 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fDisableRunningAndStoppedEvents.count > 0 &&
|
if (fDisableNextSignalEventDmc != null && e instanceof MISignalEvent &&
|
||||||
fDisableRunningAndStoppedEvents.executionDmc.equals(e.getDMContext())) {
|
fDisableNextSignalEventDmc.equals(e.getDMContext())) {
|
||||||
|
|
||||||
fDisableRunningAndStoppedEvents.count--;
|
fDisableNextSignalEventDmc = null;
|
||||||
|
fSilencedSignalEvent = e;
|
||||||
|
|
||||||
// Don't broadcast the stopped event
|
// Don't broadcast the stopped event
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -14,6 +14,7 @@ package org.eclipse.cdt.dsf.gdb.service;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
@ -101,6 +102,16 @@ public interface IGDBBackend extends IMIBackend {
|
||||||
*/
|
*/
|
||||||
public void interrupt();
|
public void interrupt();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interrupts the backend.
|
||||||
|
* The request monitor indicates if the interrupt succeeded or not;
|
||||||
|
* it may or may not indicate that the backend is already interrupted,
|
||||||
|
* but does indicate if the backend will become interrupted.
|
||||||
|
*
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public void interrupt(RequestMonitor rm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The type of the session currently ongoing with the backend
|
* @return The type of the session currently ongoing with the backend
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -324,10 +324,18 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
||||||
private StateChangeReason fStateChangeReason;
|
private StateChangeReason fStateChangeReason;
|
||||||
private IExecutionDMContext fStateChangeTriggeringContext;
|
private IExecutionDMContext fStateChangeTriggeringContext;
|
||||||
/**
|
/**
|
||||||
* A counter of MIRunning/MIStopped events that should
|
* Indicates that the next MIRunning event should be silenced.
|
||||||
* be kept silent.
|
|
||||||
*/
|
*/
|
||||||
private int fDisableRunningAndStoppedEventsCount = 0;
|
private boolean fDisableNextRunningEvent;
|
||||||
|
/**
|
||||||
|
* Indicates that the next MISignal (MIStopped) event should be silenced.
|
||||||
|
*/
|
||||||
|
private boolean fDisableNextSignalEvent;
|
||||||
|
/**
|
||||||
|
* Stores the silenced MIStopped event in case we need to use it
|
||||||
|
* for a failure.
|
||||||
|
*/
|
||||||
|
private MIStoppedEvent fSilencedSignalEvent;
|
||||||
|
|
||||||
private static final int FAKE_THREAD_ID = 0;
|
private static final int FAKE_THREAD_ID = 0;
|
||||||
|
|
||||||
|
@ -396,9 +404,9 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
||||||
*/
|
*/
|
||||||
@DsfServiceEventHandler
|
@DsfServiceEventHandler
|
||||||
public void eventDispatched(final MIRunningEvent e) {
|
public void eventDispatched(final MIRunningEvent e) {
|
||||||
if (fDisableRunningAndStoppedEventsCount > 0) {
|
if (fDisableNextRunningEvent) {
|
||||||
fDisableRunningAndStoppedEventsCount--;
|
fDisableNextRunningEvent = false;
|
||||||
// We don't broadcast running events right now
|
// We don't broadcast this running event
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,9 +429,10 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
||||||
*/
|
*/
|
||||||
@DsfServiceEventHandler
|
@DsfServiceEventHandler
|
||||||
public void eventDispatched(final MIStoppedEvent e) {
|
public void eventDispatched(final MIStoppedEvent e) {
|
||||||
if (fDisableRunningAndStoppedEventsCount > 0) {
|
if (fDisableNextSignalEvent && e instanceof MISignalEvent) {
|
||||||
fDisableRunningAndStoppedEventsCount--;
|
fDisableNextSignalEvent = false;
|
||||||
// We don't broadcast stopped events right now
|
fSilencedSignalEvent = e;
|
||||||
|
// We don't broadcast this stopped event
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +452,7 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
||||||
// Set the triggering context only if it's not the container context, since we are looking for a thread.
|
// Set the triggering context only if it's not the container context, since we are looking for a thread.
|
||||||
IExecutionDMContext triggeringCtx = !e.getDMContext().equals(containerDmc) ? e.getDMContext() : null;
|
IExecutionDMContext triggeringCtx = !e.getDMContext().equals(containerDmc) ? e.getDMContext() : null;
|
||||||
if (triggeringCtx == null) {
|
if (triggeringCtx == null) {
|
||||||
// Still no thread. Let's ask the bakend for one.
|
// Still no thread. Let's ask the backend for one.
|
||||||
// We need a proper thread id for the debug view to select the right thread
|
// We need a proper thread id for the debug view to select the right thread
|
||||||
// Bug 300096 comment #15 and Bug 302597
|
// Bug 300096 comment #15 and Bug 302597
|
||||||
getConnection().queueCommand(
|
getConnection().queueCommand(
|
||||||
|
@ -934,10 +943,20 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
||||||
@Override
|
@Override
|
||||||
public void execute(final RequestMonitor rm) {
|
public void execute(final RequestMonitor rm) {
|
||||||
if (!isTargetAvailable()) {
|
if (!isTargetAvailable()) {
|
||||||
// Don't broadcast the coming stopped/running events
|
assert fDisableNextRunningEvent == false;
|
||||||
assert fDisableRunningAndStoppedEventsCount == 0;
|
assert fDisableNextSignalEvent == false;
|
||||||
fDisableRunningAndStoppedEventsCount++;
|
|
||||||
suspend(getContextToSuspend(), rm);
|
// Don't broadcast the coming stopped signal event
|
||||||
|
fDisableNextSignalEvent = true;
|
||||||
|
suspend(getContextToSuspend(),
|
||||||
|
new RequestMonitor(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleFailure() {
|
||||||
|
// We weren't able to suspend, so abort the operation
|
||||||
|
fDisableNextSignalEvent = false;
|
||||||
|
super.handleFailure();
|
||||||
|
};
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
@ -951,14 +970,38 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
||||||
@Override
|
@Override
|
||||||
public void execute(final RequestMonitor rm) {
|
public void execute(final RequestMonitor rm) {
|
||||||
if (!isTargetAvailable()) {
|
if (!isTargetAvailable()) {
|
||||||
assert fDisableRunningAndStoppedEventsCount == 0 || fDisableRunningAndStoppedEventsCount == 1;
|
assert fDisableNextRunningEvent == false;
|
||||||
fDisableRunningAndStoppedEventsCount++;
|
fDisableNextRunningEvent = true;
|
||||||
|
|
||||||
// Can't use the resume() call because we 'silently' stopped
|
// Can't use the resume() call because we 'silently' stopped
|
||||||
// so resume() will not know we are actually stopped
|
// so resume() will not know we are actually stopped
|
||||||
fConnection.queueCommand(
|
fConnection.queueCommand(
|
||||||
fCommandFactory.createMIExecContinue(getContextToSuspend()),
|
fCommandFactory.createMIExecContinue(getContextToSuspend()),
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
fSilencedSignalEvent = null;
|
||||||
|
super.handleSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleFailure() {
|
||||||
|
// Darn, we're unable to restart the target. Must cleanup!
|
||||||
|
fDisableNextRunningEvent = false;
|
||||||
|
|
||||||
|
// We must also sent the Stopped event that we had kept silent
|
||||||
|
if (fSilencedSignalEvent != null) {
|
||||||
|
eventDispatched(fSilencedSignalEvent);
|
||||||
|
fSilencedSignalEvent = null;
|
||||||
|
} else {
|
||||||
|
// Maybe the stopped event didn't arrive yet.
|
||||||
|
// We don't want to silence it anymore
|
||||||
|
fDisableNextSignalEvent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.handleFailure();
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// We didn't suspend the container, so we don't need to resume it
|
// We didn't suspend the container, so we don't need to resume it
|
||||||
rm.done();
|
rm.done();
|
||||||
|
|
Loading…
Add table
Reference in a new issue