diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java index e8b28a53221..e98d5d9e5ea 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java @@ -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 fProcessNames = new HashMap(); @@ -114,10 +123,6 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses { GDBProcesses.class.getName() }, new Hashtable()); - 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 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 attachRm = new DataRequestMonitor(ImmediateExecutor.getInstance(), rm) { @Override @@ -223,10 +224,9 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses { new DataRequestMonitor(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 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 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(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(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 execMonitor = new DataRequestMonitor(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 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(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 execMonitor = new DataRequestMonitor(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 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(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 */ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java index 8512c2611dc..818511fe8cc 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java @@ -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 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 rm) { @@ -857,7 +873,13 @@ public class GDBProcesses_7_0 extends AbstractDsfService fCommandControl.queueCommand( fCommandFactory.createMITargetDetach(controlDmc, procDmc.getProcId()), - new DataRequestMonitor(getExecutor(), rm)); + new DataRequestMonitor(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(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(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(); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java index e2e5c30befd..b3c878316bd 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java @@ -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 { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java index 5924d9d88d7..89fafbd4013 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java @@ -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 } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java index b6561c46c80..e95a2642b5d 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java @@ -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 diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBInferiorProcess.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBInferiorProcess.java deleted file mode 100644 index 9cc24992c07..00000000000 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBInferiorProcess.java +++ /dev/null @@ -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(); - } - } -} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java index 575dda4c30a..1024a7c8c91 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java @@ -28,10 +28,6 @@ public interface IGDBControl extends IMICommandControl { void createInferiorProcess(); - boolean isConnected(); - - void setConnected(boolean connected); - AbstractCLIProcess getCLIProcess(); MIInferiorProcess getInferiorProcess(); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java index 149eb95f120..8eaa642088f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java @@ -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(ctx, cmd); } + /** @since 4.0 */ + public ICommand createMIInterpreterExecConsoleKill(IMIContainerDMContext ctx) { + return new MIInterpreterExecConsoleKill(ctx); + } + /** @since 4.0 */ public ICommand createMIListFeatures(ICommandControlDMContext ctx) { return new MIListFeatures(ctx); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIInferiorProcess.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIInferiorProcess.java index a9db39cba8a..11acf7f4dd2 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIInferiorProcess.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIInferiorProcess.java @@ -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 cmd = fCommandFactory.createCLIExecAbort(getCommandControlService().getContext()); - getCommandControlService().queueCommand( - cmd, - new DataRequestMonitor(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 diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIInterpreterExecConsoleKill.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIInterpreterExecConsoleKill.java new file mode 100644 index 00000000000..60a5eeebaf1 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIInterpreterExecConsoleKill.java @@ -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 { + + public MIInterpreterExecConsoleKill(IMIContainerDMContext ctx) { + super(ctx, "kill"); //$NON-NLS-1$ + } +}