mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 338319: Allow terminating individual processes
This commit is contained in:
parent
4c700d7e5f
commit
e03d0d8880
10 changed files with 283 additions and 257 deletions
|
@ -30,9 +30,11 @@ import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContex
|
|||
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GDBProcess;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
|
@ -45,6 +47,7 @@ import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
|||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess.State;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
|
@ -53,6 +56,7 @@ import org.eclipse.cdt.dsf.service.DsfSession;
|
|||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
|
@ -74,6 +78,11 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
private IGDBBackend fBackend;
|
||||
private CommandFactory fCommandFactory;
|
||||
|
||||
// Indicates if we are currently connected to an inferior
|
||||
// We only need a boolean type since we only support single process debugging
|
||||
// in this version of the service
|
||||
private boolean fConnected;
|
||||
|
||||
// A map of pid to names. It is filled when we get all the
|
||||
// processes that are running
|
||||
private Map<Integer, String> fProcessNames = new HashMap<Integer, String>();
|
||||
|
@ -114,10 +123,6 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
GDBProcesses.class.getName() },
|
||||
new Hashtable<String, String>());
|
||||
|
||||
ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
|
||||
IContainerDMContext containerDmc = createContainerContextFromGroupId(commandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID);
|
||||
fGdb.getInferiorProcess().setContainerContext(containerDmc);
|
||||
|
||||
getSession().addServiceEventListener(this, null);
|
||||
|
||||
requestMonitor.done();
|
||||
|
@ -195,11 +200,7 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
|
||||
@Override
|
||||
public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
|
||||
if (!fGdb.isConnected() &&
|
||||
inferiorProcess != null &&
|
||||
inferiorProcess.getState() != MIInferiorProcess.State.TERMINATED) {
|
||||
|
||||
if (fBackend.getIsAttachSession() && !fConnected) {
|
||||
rm.setData(true);
|
||||
} else {
|
||||
rm.setData(false);
|
||||
|
@ -213,7 +214,7 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
// For a local attach, GDB can figure out the binary automatically,
|
||||
// so we don't specify it.
|
||||
|
||||
IMIContainerDMContext containerDmc = createContainerContext(procCtx, MIProcesses.UNIQUE_GROUP_ID);
|
||||
final IMIContainerDMContext containerDmc = createContainerContext(procCtx, MIProcesses.UNIQUE_GROUP_ID);
|
||||
|
||||
DataRequestMonitor<MIInfo> attachRm = new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
|
@ -223,10 +224,9 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
new DataRequestMonitor<IDMContext>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
fGdb.setConnected(true);
|
||||
|
||||
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
|
||||
if (inferiorProcess != null) {
|
||||
inferiorProcess.setContainerContext(containerDmc);
|
||||
inferiorProcess.setPid(((IMIProcessDMContext)procCtx).getProcId());
|
||||
}
|
||||
|
||||
|
@ -258,7 +258,11 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
|
||||
@Override
|
||||
public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||
rm.setData(false); // don't turn on yet, as we need to generate events to use this properly
|
||||
if (fBackend.getIsAttachSession() && fConnected) {
|
||||
rm.setData(true);
|
||||
} else {
|
||||
rm.setData(false);
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
@ -268,9 +272,7 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
dmc,
|
||||
new RequestMonitor(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
fGdb.setConnected(false);
|
||||
|
||||
protected void handleSuccess() {
|
||||
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
|
||||
if (inferiorProcess != null) {
|
||||
inferiorProcess.setPid(null);
|
||||
|
@ -301,7 +303,7 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
@Override
|
||||
public void getProcessesBeingDebugged(IDMContext dmc, DataRequestMonitor<IDMContext[]> rm) {
|
||||
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
|
||||
if (fGdb.isConnected() &&
|
||||
if (fConnected &&
|
||||
inferiorProcess != null &&
|
||||
inferiorProcess.getState() != MIInferiorProcess.State.TERMINATED) {
|
||||
|
||||
|
@ -353,9 +355,37 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void terminate(IThreadDMContext thread, RequestMonitor rm) {
|
||||
public void terminate(IThreadDMContext thread, final RequestMonitor rm) {
|
||||
if (thread instanceof IMIProcessDMContext) {
|
||||
fGdb.terminate(rm);
|
||||
getDebuggingContext(
|
||||
thread,
|
||||
new DataRequestMonitor<IDMContext>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (getData() instanceof IMIContainerDMContext) {
|
||||
if (fGdb.getInferiorProcess().getState() == State.RUNNING) {
|
||||
fBackend.interrupt();
|
||||
}
|
||||
|
||||
final IMIContainerDMContext container = (IMIContainerDMContext)getData();
|
||||
fGdb.queueCommand(
|
||||
fCommandFactory.createMIInterpreterExecConsoleKill(container),
|
||||
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// Before GDB 7.0, we must send a container exited event ourselves
|
||||
getSession().dispatchEvent(
|
||||
new ContainerExitedDMEvent(container), getProperties());
|
||||
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
|
@ -405,12 +435,13 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
/**
|
||||
* @since 4.0
|
||||
*/
|
||||
protected void createConsole(final boolean restart, final RequestMonitor rm) {
|
||||
protected void createConsole(final IContainerDMContext containerDmc, final boolean restart, final RequestMonitor rm) {
|
||||
fGdb.initInferiorInputOutput(new RequestMonitor(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
fGdb.createInferiorProcess();
|
||||
final Process inferior = fGdb.getInferiorProcess();
|
||||
fGdb.createInferiorProcess();
|
||||
final MIInferiorProcess inferior = fGdb.getInferiorProcess();
|
||||
inferior.setContainerContext(containerDmc);
|
||||
|
||||
final String label = fBackend.getProgramPath().lastSegment();
|
||||
final ILaunch launch = (ILaunch)getSession().getModelAdapter(ILaunch.class);
|
||||
|
@ -459,55 +490,55 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
return;
|
||||
}
|
||||
|
||||
createConsole(restart, new RequestMonitor(ImmediateExecutor.getInstance(), requestMonitor) {
|
||||
createConsole(containerDmc, restart, new RequestMonitor(ImmediateExecutor.getInstance(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
||||
final DataRequestMonitor<MIInfo> execMonitor = new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (fBackend.getSessionType() != SessionType.REMOTE) {
|
||||
// Don't send the ContainerStarted event for a remote session because
|
||||
// it has already been done by MIRunControlEventProcessor when receiving
|
||||
// the ^connect
|
||||
getSession().dispatchEvent(new ContainerStartedDMEvent(containerDmc), getProperties());
|
||||
}
|
||||
requestMonitor.setData(containerDmc);
|
||||
requestMonitor.done();
|
||||
}
|
||||
};
|
||||
|
||||
final ICommand<MIInfo> execCommand;
|
||||
if (useContinueCommand()) {
|
||||
execCommand = fCommandFactory.createMIExecContinue(containerDmc);
|
||||
} else {
|
||||
execCommand = fCommandFactory.createMIExecRun(containerDmc);
|
||||
}
|
||||
|
||||
boolean stopInMain = CDebugUtils.getAttribute(attributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
|
||||
false);
|
||||
|
||||
if (!stopInMain) {
|
||||
// Just start the program.
|
||||
fGdb.queueCommand(execCommand, execMonitor);
|
||||
} else {
|
||||
String stopSymbol = CDebugUtils.getAttribute(attributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
|
||||
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
|
||||
|
||||
// Insert a breakpoint at the requested stop symbol.
|
||||
IBreakpointsTargetDMContext bpTarget = DMContexts.getAncestorOfType(containerDmc, IBreakpointsTargetDMContext.class);
|
||||
fGdb.queueCommand(
|
||||
fCommandFactory.createMIBreakInsert(bpTarget, true, false, null, 0, stopSymbol, 0),
|
||||
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// After the break-insert is done, execute the -exec-run or -exec-continue command.
|
||||
fGdb.queueCommand(execCommand, execMonitor);
|
||||
final DataRequestMonitor<MIInfo> execMonitor = new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (fBackend.getSessionType() != SessionType.REMOTE) {
|
||||
// Don't send the ContainerStarted event for a remote session because
|
||||
// it has already been done by MIRunControlEventProcessor when receiving
|
||||
// the ^connect
|
||||
getSession().dispatchEvent(new ContainerStartedDMEvent(containerDmc), getProperties());
|
||||
}
|
||||
});
|
||||
}
|
||||
requestMonitor.setData(containerDmc);
|
||||
requestMonitor.done();
|
||||
}
|
||||
};
|
||||
|
||||
final ICommand<MIInfo> execCommand;
|
||||
if (useContinueCommand()) {
|
||||
execCommand = fCommandFactory.createMIExecContinue(containerDmc);
|
||||
} else {
|
||||
execCommand = fCommandFactory.createMIExecRun(containerDmc);
|
||||
}
|
||||
|
||||
boolean stopInMain = CDebugUtils.getAttribute(attributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
|
||||
false);
|
||||
|
||||
if (!stopInMain) {
|
||||
// Just start the program.
|
||||
fGdb.queueCommand(execCommand, execMonitor);
|
||||
} else {
|
||||
String stopSymbol = CDebugUtils.getAttribute(attributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
|
||||
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
|
||||
|
||||
// Insert a breakpoint at the requested stop symbol.
|
||||
IBreakpointsTargetDMContext bpTarget = DMContexts.getAncestorOfType(containerDmc, IBreakpointsTargetDMContext.class);
|
||||
fGdb.queueCommand(
|
||||
fCommandFactory.createMIBreakInsert(bpTarget, true, false, null, 0, stopSymbol, 0),
|
||||
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// After the break-insert is done, execute the -exec-run or -exec-continue command.
|
||||
fGdb.queueCommand(execCommand, execMonitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -524,6 +555,31 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
return fBackend.getSessionType() == SessionType.REMOTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(IStartedDMEvent e) {
|
||||
if (e.getDMContext() instanceof IContainerDMContext) {
|
||||
fConnected = true;
|
||||
}
|
||||
super.eventDispatched(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(IExitedDMEvent e) {
|
||||
if (e.getDMContext() instanceof IContainerDMContext) {
|
||||
fConnected = false;
|
||||
|
||||
if (Platform.getPreferencesService().getBoolean("org.eclipse.cdt.dsf.gdb.ui", //$NON-NLS-1$
|
||||
IGdbDebugPreferenceConstants.PREF_AUTO_TERMINATE_GDB,
|
||||
true, null)) {
|
||||
// If the inferior finishes, let's terminate GDB
|
||||
fGdb.terminate(new RequestMonitor(ImmediateExecutor.getInstance(), null));
|
||||
}
|
||||
}
|
||||
super.eventDispatched(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
|||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
|
@ -60,6 +61,8 @@ import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
|||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess.State;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadGroupCreatedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadGroupExitedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
|
||||
|
@ -79,6 +82,7 @@ import org.eclipse.cdt.dsf.service.DsfSession;
|
|||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
@ -436,6 +440,11 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
|
||||
private static final String FAKE_THREAD_ID = "0"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Keeps track of how many processes we are currently connected to
|
||||
*/
|
||||
private int fNumConnected;
|
||||
|
||||
/**
|
||||
* Keeps track if we are dealing with the very first process of GDB.
|
||||
*/
|
||||
|
@ -725,7 +734,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
|
||||
/** @since 4.0 */
|
||||
protected boolean doIsDebuggerAttachSupported() {
|
||||
return fBackend.getIsAttachSession() && !fCommandControl.isConnected();
|
||||
return fBackend.getIsAttachSession() && fNumConnected == 0;
|
||||
}
|
||||
|
||||
public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||
|
@ -790,7 +799,14 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
public void execute(RequestMonitor rm) {
|
||||
// By now, GDB has reported the groupId that was created for this process
|
||||
fContainerDmc = createContainerContext(procCtx, getGroupFromPid(((IMIProcessDMContext)procCtx).getProcId()));
|
||||
// Store the fully formed container context so it can be returned to the caller.
|
||||
|
||||
MIInferiorProcess inferior = fCommandControl.getInferiorProcess();
|
||||
if (inferior != null) {
|
||||
inferior.setContainerContext(fContainerDmc);
|
||||
inferior.setPid(((IMIProcessDMContext)procCtx).getProcId());
|
||||
}
|
||||
|
||||
// Store the fully formed container context so it can be returned to the caller.
|
||||
dataRm.setData(fContainerDmc);
|
||||
|
||||
// Start tracking breakpoints.
|
||||
|
@ -835,7 +851,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
|
||||
/** @since 4.0 */
|
||||
protected boolean doCanDetachDebuggerFromProcess() {
|
||||
return fBackend.getIsAttachSession() && fCommandControl.isConnected();
|
||||
return fBackend.getIsAttachSession() && fNumConnected > 0;
|
||||
}
|
||||
|
||||
public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||
|
@ -857,7 +873,13 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetDetach(controlDmc, procDmc.getProcId()),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
fCommandControl.getInferiorProcess().setPid(null);
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid context.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
|
@ -1096,9 +1118,27 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
rm.done();
|
||||
}
|
||||
|
||||
public void terminate(IThreadDMContext thread, RequestMonitor rm) {
|
||||
public void terminate(IThreadDMContext thread, final RequestMonitor rm) {
|
||||
if (thread instanceof IMIProcessDMContext) {
|
||||
fCommandControl.terminate(rm);
|
||||
getDebuggingContext(
|
||||
thread,
|
||||
new DataRequestMonitor<IDMContext>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (getData() instanceof IMIContainerDMContext) {
|
||||
if (fCommandControl.getInferiorProcess().getState() == State.RUNNING) {
|
||||
fBackend.interrupt();
|
||||
}
|
||||
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMIInterpreterExecConsoleKill((IMIContainerDMContext)getData()),
|
||||
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
|
@ -1214,6 +1254,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
public void eventDispatched(IStartedDMEvent e) {
|
||||
if (e instanceof ContainerStartedDMEvent) {
|
||||
fContainerCommandCache.reset();
|
||||
fNumConnected++;
|
||||
} else {
|
||||
fThreadCommandCache.reset();
|
||||
}
|
||||
|
@ -1224,6 +1265,22 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
public void eventDispatched(IExitedDMEvent e) {
|
||||
if (e instanceof ContainerExitedDMEvent) {
|
||||
fContainerCommandCache.reset();
|
||||
|
||||
assert fNumConnected > 0;
|
||||
fNumConnected--;
|
||||
|
||||
if (Platform.getPreferencesService().getBoolean("org.eclipse.cdt.dsf.gdb.ui", //$NON-NLS-1$
|
||||
IGdbDebugPreferenceConstants.PREF_AUTO_TERMINATE_GDB,
|
||||
true, null)) {
|
||||
if (fNumConnected == 0 &&
|
||||
!(fBackend.getIsAttachSession() &&
|
||||
fBackend.getSessionType() == SessionType.REMOTE)) {
|
||||
// If the last process we are debugging finishes, let's terminate GDB
|
||||
// but not for a remote attach session, since we could request to attach
|
||||
// to another process
|
||||
fCommandControl.terminate(new RequestMonitor(ImmediateExecutor.getInstance(), null));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fThreadCommandCache.reset();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
|||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
|
||||
|
@ -333,6 +334,11 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence {
|
|||
|
||||
if (fContainerDmc instanceof IMIContainerDMContext) {
|
||||
fContainerDmc = fProcService.createContainerContextFromGroupId(fCommandControl.getContext(), ((IMIContainerDMContext)fContainerDmc).getGroupId());
|
||||
fCommandControl.getInferiorProcess().setContainerContext(fContainerDmc);
|
||||
|
||||
IMIProcessDMContext procDmc = DMContexts.getAncestorOfType(fContainerDmc, IMIProcessDMContext.class);
|
||||
fCommandControl.getInferiorProcess().setPid(procDmc.getProcId());
|
||||
|
||||
// This is the container context that this sequence is supposed to return: set the dataRm
|
||||
fDataRequestMonitor.setData(fContainerDmc);
|
||||
} else {
|
||||
|
|
|
@ -28,20 +28,17 @@ 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.IDsfStatusConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses.ContainerExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CLIEventProcessor;
|
||||
|
@ -55,7 +52,6 @@ import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
|||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.utils.pty.PTY;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
@ -94,9 +90,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
private GDBControlDMContext fControlDmc;
|
||||
|
||||
private IGDBBackend fMIBackend;
|
||||
|
||||
private boolean fConnected;
|
||||
|
||||
|
||||
private MIRunControlEventProcessor fMIEventProcessor;
|
||||
private CLIEventProcessor fCLICommandProcessor;
|
||||
private AbstractCLIProcess fCLIProcess;
|
||||
|
@ -264,9 +258,9 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
*/
|
||||
public void createInferiorProcess() {
|
||||
if (fPty == null) {
|
||||
fInferiorProcess = new GDBInferiorProcess(GDBControl.this, fMIBackend, fMIBackend.getMIOutputStream());
|
||||
fInferiorProcess = new MIInferiorProcess(GDBControl.this, fMIBackend.getMIOutputStream());
|
||||
} else {
|
||||
fInferiorProcess = new GDBInferiorProcess(GDBControl.this, fMIBackend, fPty);
|
||||
fInferiorProcess = new MIInferiorProcess(GDBControl.this, fPty);
|
||||
}
|
||||
|
||||
// Create the CLI event processor each time this method is called
|
||||
|
@ -277,16 +271,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
}
|
||||
fCLICommandProcessor = new CLIEventProcessor(GDBControl.this, fControlDmc);
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return fInferiorProcess.getState() != MIInferiorProcess.State.TERMINATED &&
|
||||
(!fMIBackend.getIsAttachSession() || fConnected);
|
||||
}
|
||||
|
||||
public void setConnected(boolean connected) {
|
||||
fConnected = connected;
|
||||
}
|
||||
|
||||
|
||||
public AbstractCLIProcess getCLIProcess() {
|
||||
return fCLIProcess;
|
||||
}
|
||||
|
@ -341,17 +326,6 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
}
|
||||
}
|
||||
|
||||
/** @since 2.0 */
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ContainerExitedDMEvent e) {
|
||||
if (Platform.getPreferencesService().getBoolean("org.eclipse.cdt.dsf.gdb.ui", //$NON-NLS-1$
|
||||
IGdbDebugPreferenceConstants.PREF_AUTO_TERMINATE_GDB,
|
||||
true, null)) {
|
||||
// If the inferior finishes, let's terminate GDB
|
||||
terminate(new RequestMonitor(ImmediateExecutor.getInstance(), null));
|
||||
}
|
||||
}
|
||||
|
||||
public static class InitializationShutdownStep extends Sequence.Step {
|
||||
public enum Direction { INITIALIZING, SHUTTING_DOWN }
|
||||
|
||||
|
|
|
@ -28,16 +28,12 @@ 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.IDsfStatusConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.GDBProcesses_7_0.ContainerExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.service.GDBProcesses_7_0.ContainerStartedDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
|
@ -58,7 +54,6 @@ import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
|||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.utils.pty.PTY;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
@ -97,8 +92,6 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
|
|||
private GDBControlDMContext fControlDmc;
|
||||
|
||||
private IGDBBackend fMIBackend;
|
||||
|
||||
private int fConnected = 0;
|
||||
|
||||
private MIRunControlEventProcessor_7_0 fMIEventProcessor;
|
||||
private CLIEventProcessor_7_0 fCLICommandProcessor;
|
||||
|
@ -281,25 +274,12 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
|
|||
*/
|
||||
public void createInferiorProcess() {
|
||||
if (fPty == null) {
|
||||
fInferiorProcess = new GDBInferiorProcess(GDBControl_7_0.this, fMIBackend, fMIBackend.getMIOutputStream());
|
||||
fInferiorProcess = new MIInferiorProcess(GDBControl_7_0.this, fMIBackend.getMIOutputStream());
|
||||
} else {
|
||||
fInferiorProcess = new GDBInferiorProcess(GDBControl_7_0.this, fMIBackend, fPty);
|
||||
fInferiorProcess = new MIInferiorProcess(GDBControl_7_0.this, fPty);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return fInferiorProcess.getState() != MIInferiorProcess.State.TERMINATED &&
|
||||
(!fMIBackend.getIsAttachSession() || fConnected > 0);
|
||||
}
|
||||
|
||||
public void setConnected(boolean connected) {
|
||||
if (connected) {
|
||||
fConnected++;
|
||||
} else {
|
||||
if (fConnected > 0) fConnected--;
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractCLIProcess getCLIProcess() {
|
||||
return fCLIProcess;
|
||||
}
|
||||
|
@ -358,31 +338,6 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
|
|||
getSession().dispatchEvent(new GDBControlShutdownDMEvent(fControlDmc), getProperties());
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2.0 */
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ContainerStartedDMEvent e) {
|
||||
setConnected(true);
|
||||
}
|
||||
|
||||
/** @since 2.0 */
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ContainerExitedDMEvent e) {
|
||||
setConnected(false);
|
||||
|
||||
if (Platform.getPreferencesService().getBoolean("org.eclipse.cdt.dsf.gdb.ui", //$NON-NLS-1$
|
||||
IGdbDebugPreferenceConstants.PREF_AUTO_TERMINATE_GDB,
|
||||
true, null)) {
|
||||
if (!isConnected() &&
|
||||
!(fMIBackend.getIsAttachSession() &&
|
||||
fMIBackend.getSessionType() == SessionType.REMOTE)) {
|
||||
// If the last process we are debugging finishes, let's terminate GDB
|
||||
// but not for a remote attach session, since we could request to attach
|
||||
// to another process
|
||||
terminate(new RequestMonitor(ImmediateExecutor.getInstance(), null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 3.0 */
|
||||
@DsfServiceEventHandler
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2009 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.service.command;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
||||
import org.eclipse.cdt.utils.pty.PTY;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class GDBInferiorProcess extends MIInferiorProcess {
|
||||
|
||||
private IGDBBackend fBackend;
|
||||
|
||||
public GDBInferiorProcess(ICommandControlService commandControl, IGDBBackend backend, PTY p) {
|
||||
super(commandControl, p);
|
||||
fBackend = backend;
|
||||
}
|
||||
|
||||
public GDBInferiorProcess(ICommandControlService commandControl, IGDBBackend backend, OutputStream gdbOutputStream) {
|
||||
super(commandControl, gdbOutputStream);
|
||||
fBackend = backend;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ThreadSafeAndProhibitedFromDsfExecutor("getSession#getExecutor")
|
||||
public void destroy() {
|
||||
try {
|
||||
getSession().getExecutor().submit(new DsfRunnable() {
|
||||
public void run() {
|
||||
if (isDisposed() || !getSession().isActive()) return;
|
||||
|
||||
// An inferior will be destroy():interrupt and kill if
|
||||
// - For attach session:
|
||||
// never (we don't kill an independent process.)
|
||||
// - For Program session:
|
||||
// if the inferior is still running.
|
||||
// - For PostMortem(Core):
|
||||
// no need to do anything since the inferior
|
||||
// is not running
|
||||
if (fBackend.getIsAttachSession() == false) {
|
||||
// Try to interrupt the inferior, first.
|
||||
if (getState() == State.RUNNING) {
|
||||
fBackend.interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).get();
|
||||
} catch (RejectedExecutionException e) {
|
||||
} catch (InterruptedException e) {
|
||||
} catch (ExecutionException e) {
|
||||
} finally {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,10 +28,6 @@ public interface IGDBControl extends IMICommandControl {
|
|||
|
||||
void createInferiorProcess();
|
||||
|
||||
boolean isConnected();
|
||||
|
||||
void setConnected(boolean connected);
|
||||
|
||||
AbstractCLIProcess getCLIProcess();
|
||||
|
||||
MIInferiorProcess getInferiorProcess();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2010 QNX Software Systems and others.
|
||||
* Copyright (c) 2000, 2011 QNX Software 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
|
||||
|
@ -68,6 +68,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIDataWriteMemory;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIEnablePrettyPrinting;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIEnvironmentCD;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIEnvironmentDirectory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecArguments;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecFinish;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecInterrupt;
|
||||
|
@ -103,6 +104,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBShowExitCode;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInferiorTTYSet;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExec;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExecConsole;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExecConsoleKill;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIListFeatures;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIListThreadGroups;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIRemoveInferior;
|
||||
|
@ -143,7 +145,6 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarSetUpdateRange;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowAttributes;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowFormat;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarUpdate;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecArguments;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoProgramInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoSharedLibraryInfo;
|
||||
|
@ -632,6 +633,11 @@ public class CommandFactory {
|
|||
return new MIInterpreterExecConsole<MIInfo>(ctx, cmd);
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
public ICommand<MIInfo> createMIInterpreterExecConsoleKill(IMIContainerDMContext ctx) {
|
||||
return new MIInterpreterExecConsoleKill(ctx);
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
public ICommand<MIListFeaturesInfo> createMIListFeatures(ICommandControlDMContext ctx) {
|
||||
return new MIListFeatures(ctx);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2010 QNX Software Systems and others.
|
||||
* Copyright (c) 2009, 2011 QNX Software 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
|
||||
|
@ -28,11 +28,15 @@ 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.Query;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
|
||||
import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandListener;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
|
||||
|
@ -52,6 +56,8 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITargetStreamOutput;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
|
||||
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.utils.pty.PTY;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
@ -124,8 +130,6 @@ public class MIInferiorProcess extends Process
|
|||
* to write the user standard input into.
|
||||
*
|
||||
* @param commandControl Command control that this inferior process belongs to.
|
||||
* @param inferiorExecCtx The execution context controlling the execution
|
||||
* state of the inferior process.
|
||||
* @param gdbOutputStream The output stream to use to write user IO into.
|
||||
* @since 1.1
|
||||
*/
|
||||
|
@ -139,8 +143,6 @@ public class MIInferiorProcess extends Process
|
|||
* to write the user standard input into.
|
||||
*
|
||||
* @param commandControl Command control that this inferior process belongs to.
|
||||
* @param inferiorExecCtx The execution context controlling the execution
|
||||
* state of the inferior process.
|
||||
* @param p The terminal to use to write user IO into.
|
||||
* @since 1.1
|
||||
*/
|
||||
|
@ -153,7 +155,8 @@ public class MIInferiorProcess extends Process
|
|||
private MIInferiorProcess(ICommandControlService commandControl, final OutputStream gdbOutputStream, PTY p) {
|
||||
fCommandControl = commandControl;
|
||||
fSession = commandControl.getSession();
|
||||
|
||||
fSession.addServiceEventListener(this, null);
|
||||
|
||||
if (fCommandControl instanceof IMICommandControl) {
|
||||
fCommandFactory = ((IMICommandControl)fCommandControl).getCommandFactory();
|
||||
} else {
|
||||
|
@ -173,7 +176,6 @@ public class MIInferiorProcess extends Process
|
|||
fOutputStream = new OutputStream() {
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
// Have to re-dispatch to dispatch thread to check state
|
||||
if (getState() != State.RUNNING) {
|
||||
throw new IOException("Target is not running"); //$NON-NLS-1$
|
||||
}
|
||||
|
@ -206,6 +208,8 @@ public class MIInferiorProcess extends Process
|
|||
|
||||
@ConfinedToDsfExecutor("fSession#getExecutor")
|
||||
public void dispose() {
|
||||
fSession.removeServiceEventListener(this);
|
||||
|
||||
fCommandControl.removeEventListener(this);
|
||||
fCommandControl.removeCommandListener(this);
|
||||
|
||||
|
@ -369,18 +373,15 @@ public class MIInferiorProcess extends Process
|
|||
private void doDestroy() {
|
||||
if (isDisposed() || !fSession.isActive() || getState() == State.TERMINATED) return;
|
||||
|
||||
// To avoid a RejectedExecutionException, use an executor that
|
||||
// immediately executes in the same dispatch cycle.
|
||||
ICommand<MIInfo> cmd = fCommandFactory.createCLIExecAbort(getCommandControlService().getContext());
|
||||
getCommandControlService().queueCommand(
|
||||
cmd,
|
||||
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
setState(MIInferiorProcess.State.TERMINATED);
|
||||
}
|
||||
}
|
||||
);
|
||||
DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fSession.getId());
|
||||
IProcesses procService = tracker.getService(IProcesses.class);
|
||||
tracker.dispose();
|
||||
if (procService != null) {
|
||||
IProcessDMContext procDmc = DMContexts.getAncestorOfType(fContainerDMContext, IProcessDMContext.class);
|
||||
procService.terminate(procDmc, new RequestMonitor(ImmediateExecutor.getInstance(), null));
|
||||
} else {
|
||||
setState(State.TERMINATED);
|
||||
}
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
|
@ -406,12 +407,6 @@ public class MIInferiorProcess extends Process
|
|||
if (fState == State.TERMINATED) return;
|
||||
fState = state;
|
||||
if (fState == State.TERMINATED) {
|
||||
if (fContainerDMContext != null) {
|
||||
// This may not be necessary in 7.0 because of the =thread-group-exited event
|
||||
getSession().dispatchEvent(
|
||||
new ContainerExitedDMEvent(fContainerDMContext),
|
||||
getCommandControlService().getProperties());
|
||||
}
|
||||
closeIO();
|
||||
}
|
||||
notifyAll();
|
||||
|
@ -466,7 +461,14 @@ public class MIInferiorProcess extends Process
|
|||
if (value instanceof MIConst) {
|
||||
String reason = ((MIConst) value).getString();
|
||||
if ("exited-signalled".equals(reason) || "exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
setState(State.TERMINATED);
|
||||
if (fContainerDMContext != null) {
|
||||
// This may not be necessary in 7.0 because of the =thread-group-exited event
|
||||
getSession().dispatchEvent(
|
||||
new ContainerExitedDMEvent(fContainerDMContext),
|
||||
getCommandControlService().getProperties());
|
||||
} else {
|
||||
setState(State.TERMINATED);
|
||||
}
|
||||
} else {
|
||||
setState(State.STOPPED);
|
||||
}
|
||||
|
@ -520,10 +522,29 @@ public class MIInferiorProcess extends Process
|
|||
String state = rr.getResultClass();
|
||||
|
||||
if ("running".equals(state)) { setState(State.RUNNING); }//$NON-NLS-1$
|
||||
else if ("exit".equals(state)) { setState(State.TERMINATED); }//$NON-NLS-1$
|
||||
else if ("exit".equals(state)) { //$NON-NLS-1$
|
||||
if (fContainerDMContext != null) {
|
||||
// This may not be necessary in 7.0 because of the =thread-group-exited event
|
||||
getSession().dispatchEvent(
|
||||
new ContainerExitedDMEvent(fContainerDMContext),
|
||||
getCommandControlService().getProperties());
|
||||
} else {
|
||||
setState(State.TERMINATED);
|
||||
}
|
||||
}
|
||||
else if ("error".equals(state)) { setState(State.STOPPED); }//$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(IExitedDMEvent e) {
|
||||
if (e.getDMContext() instanceof IContainerDMContext) {
|
||||
setState(State.TERMINATED);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Post-poned because 'info program' yields different result on different platforms.
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=305385#c20
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Ericsson 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:
|
||||
* Ericsson - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.mi.service.command.commands;
|
||||
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
|
||||
/**
|
||||
* MIInterpreterExecConsoleKill
|
||||
* Send the CLI Kill command for a specific process.
|
||||
* @since 4.0
|
||||
*/
|
||||
public class MIInterpreterExecConsoleKill extends MIInterpreterExecConsole<MIInfo> {
|
||||
|
||||
public MIInterpreterExecConsoleKill(IMIContainerDMContext ctx) {
|
||||
super(ctx, "kill"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue