From cb49d0ed442de34b82c0a6f3d2a2cca37670c1ac Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Tue, 29 Jul 2008 17:12:19 +0000 Subject: [PATCH] Bug 227183 Adds the disconnect action. It is kept disabled though, because it is still missing events which must be generated when we connect and disconnect. --- .../debug/ui/actions/DsfCommandRunnable.java | 8 ++ .../dd/gdb/internal/ui/GdbAdapterFactory.java | 7 ++ .../ui/actions/GdbDisconnectCommand.java | 77 +++++++++++++++++++ .../provisional/launching/GdbLaunch.java | 22 +++++- .../provisional/service/GDBProcesses.java | 33 ++++++++ .../service/command/GDBControl.java | 2 +- .../eclipse/dd/mi/service/MIProcesses.java | 36 ++++----- .../service/command/commands/CLIDetach.java | 24 ++++++ 8 files changed, 184 insertions(+), 25 deletions(-) create mode 100644 plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/actions/GdbDisconnectCommand.java create mode 100644 plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/command/commands/CLIDetach.java diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfCommandRunnable.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfCommandRunnable.java index 66bcf9dbfdf..5ec14ae6e9e 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfCommandRunnable.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfCommandRunnable.java @@ -17,6 +17,7 @@ import org.eclipse.dd.dsf.concurrent.Immutable; import org.eclipse.dd.dsf.datamodel.DMContexts; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController; import org.eclipse.dd.dsf.debug.internal.ui.DsfDebugUIPlugin; +import org.eclipse.dd.dsf.debug.service.IProcesses; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.IStepQueueManager; import org.eclipse.dd.dsf.debug.service.StepQueueManager; @@ -65,6 +66,13 @@ public abstract class DsfCommandRunnable extends DsfRunnable { return null; } + /** + * @since 1.1 + */ + public IProcesses getProcessService() { + return fTracker.getService(IProcesses.class); + } + public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object element, IDebugCommandRequest request) { fTracker = servicesTracker; if (element instanceof IDMVMContext) { diff --git a/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/GdbAdapterFactory.java b/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/GdbAdapterFactory.java index 1141877cd89..822a00b6d6f 100644 --- a/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/GdbAdapterFactory.java +++ b/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/GdbAdapterFactory.java @@ -35,11 +35,13 @@ import org.eclipse.dd.gdb.internal.provisional.launching.GdbLaunch; import org.eclipse.dd.gdb.internal.provisional.launching.GdbLaunchDelegate; import org.eclipse.dd.gdb.internal.ui.actions.DsfTerminateCommand; import org.eclipse.dd.gdb.internal.ui.actions.GdbConnectCommand; +import org.eclipse.dd.gdb.internal.ui.actions.GdbDisconnectCommand; import org.eclipse.dd.gdb.internal.ui.actions.GdbRestartCommand; import org.eclipse.dd.gdb.internal.ui.viewmodel.GdbViewModelAdapter; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchesListener2; +import org.eclipse.debug.core.commands.IDisconnectHandler; import org.eclipse.debug.core.commands.IResumeHandler; import org.eclipse.debug.core.commands.IStepIntoHandler; import org.eclipse.debug.core.commands.IStepOverHandler; @@ -79,6 +81,7 @@ public class GdbAdapterFactory final GdbRestartCommand fRestartCommand; final DsfTerminateCommand fTerminateCommand; final GdbConnectCommand fConnectCommand; + final GdbDisconnectCommand fDisconnectCommand; final IDebugModelProvider fDebugModelProvider; final DsfSuspendTrigger fSuspendTrigger; final DsfSteppingModeTarget fSteppingModeTarget; @@ -111,6 +114,7 @@ public class GdbAdapterFactory fRestartCommand = new GdbRestartCommand(session, fLaunch); fTerminateCommand = new DsfTerminateCommand(session); fConnectCommand = new GdbConnectCommand(session); + fDisconnectCommand = new GdbDisconnectCommand(session); fSuspendTrigger = new DsfSuspendTrigger(session, fLaunch); fModelSelectionPolicyFactory = new DefaultDsfModelSelectionPolicyFactory(); @@ -123,6 +127,7 @@ public class GdbAdapterFactory session.registerModelAdapter(IRestart.class, fRestartCommand); session.registerModelAdapter(ITerminateHandler.class, fTerminateCommand); session.registerModelAdapter(IConnect.class, fConnectCommand); + session.registerModelAdapter(IDisconnectHandler.class, fDisconnectCommand); session.registerModelAdapter(IModelSelectionPolicyFactory.class, fModelSelectionPolicyFactory); fDebugModelProvider = new IDebugModelProvider() { @@ -161,6 +166,7 @@ public class GdbAdapterFactory session.unregisterModelAdapter(IRestart.class); session.unregisterModelAdapter(ITerminateHandler.class); session.unregisterModelAdapter(IConnect.class); + session.unregisterModelAdapter(IDisconnectHandler.class); session.unregisterModelAdapter(IModelSelectionPolicyFactory.class); fStepIntoCommand.dispose(); @@ -171,6 +177,7 @@ public class GdbAdapterFactory fRestartCommand.dispose(); fTerminateCommand.dispose(); fConnectCommand.dispose(); + fDisconnectCommand.dispose(); fSuspendTrigger.dispose(); } diff --git a/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/actions/GdbDisconnectCommand.java b/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/actions/GdbDisconnectCommand.java new file mode 100644 index 00000000000..62dc480d55e --- /dev/null +++ b/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/actions/GdbDisconnectCommand.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2008 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.dd.gdb.internal.ui.actions; + +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.DsfExecutor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.DMContexts; +import org.eclipse.dd.dsf.debug.service.IProcesses.IProcessDMContext; +import org.eclipse.dd.dsf.debug.ui.actions.DsfCommandRunnable; +import org.eclipse.dd.dsf.service.DsfServicesTracker; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IDisconnectHandler; +import org.eclipse.debug.core.commands.IEnabledStateRequest; + +public class GdbDisconnectCommand implements IDisconnectHandler { + private final DsfExecutor fExecutor; + private final DsfServicesTracker fTracker; + + public GdbDisconnectCommand(DsfSession session) { + fExecutor = session.getExecutor(); + fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId()); + } + + public void dispose() { + fTracker.dispose(); + } + + public void canExecute(final IEnabledStateRequest request) { + if (request.getElements().length != 1) { + request.setEnabled(false); + request.done(); + return; + } + + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { + @Override public void doExecute() { + IProcessDMContext procDmc = DMContexts.getAncestorOfType(getContext(), IProcessDMContext.class); + + getProcessService().canDetachDebuggerFromProcess( + procDmc, + new DataRequestMonitor(fExecutor, null) { + @Override + protected void handleCompleted() { + request.setEnabled(isSuccess() && getData()); + request.done(); + } + }); + } + }); + } + + public boolean execute(final IDebugCommandRequest request) { + if (request.getElements().length != 1) { + request.done(); + return false; + } + + fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { + @Override public void doExecute() { + IProcessDMContext procDmc = DMContexts.getAncestorOfType(getContext(), IProcessDMContext.class); + getProcessService().detachDebuggerFromProcess(procDmc, new RequestMonitor(fExecutor, null)); + } + }); + return false; + } +} diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/GdbLaunch.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/GdbLaunch.java index f20fe7a257a..5b376fd2fc6 100644 --- a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/GdbLaunch.java +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/GdbLaunch.java @@ -43,6 +43,7 @@ import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.Launch; +import org.eclipse.debug.core.model.IDisconnect; import org.eclipse.debug.core.model.IMemoryBlockRetrieval; import org.eclipse.debug.core.model.ISourceLocator; import org.eclipse.debug.core.model.ITerminate; @@ -52,7 +53,7 @@ import org.eclipse.debug.core.model.ITerminate; */ @ThreadSafe public class GdbLaunch extends Launch - implements ITerminate + implements ITerminate, IDisconnect { private DefaultDsfExecutor fExecutor; private DsfSession fSession; @@ -208,6 +209,25 @@ public class GdbLaunch extends Launch // ITerminate /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + // IDisconnect + @Override + public boolean canDisconnect() { + return canTerminate(); + } + + @Override + public boolean isDisconnected() { + return isTerminated(); + } + + @Override + public void disconnect() throws DebugException { + terminate(); + } + // IDisconnect + /////////////////////////////////////////////////////////////////////////// + /** * Shuts down the services, the session and the executor associated with * this launch. diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses.java index 5141a7b2c29..fb08918c6f2 100644 --- a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses.java +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses.java @@ -123,6 +123,39 @@ public class GDBProcesses extends MIProcesses { rm.done(); } + @Override + public void attachDebuggerToProcess(IProcessDMContext procCtx, final DataRequestMonitor rm) { + super.attachDebuggerToProcess( + procCtx, + new DataRequestMonitor(getExecutor(), rm) { + @Override + protected void handleSuccess() { + fGdb.setConnected(true); + rm.setData(getData()); + rm.done(); + } + }); + } + + @Override + public void canDetachDebuggerFromProcess(IProcessDMContext procCtx, DataRequestMonitor rm) { + rm.setData(false); // don't turn on yet, as we need to generate events to use this properly + rm.done(); + } + + @Override + public void detachDebuggerFromProcess(IProcessDMContext procCtx, final RequestMonitor rm) { + super.detachDebuggerFromProcess( + procCtx, + new RequestMonitor(getExecutor(), rm) { + @Override + protected void handleSuccess() { + fGdb.setConnected(false); + rm.done(); + } + }); + } + @Override public void getProcessesBeingDebugged(IDMContext dmc, DataRequestMonitor rm) { MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess(); diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/command/GDBControl.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/command/GDBControl.java index e9400c68fcf..87805819814 100644 --- a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/command/GDBControl.java +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/command/GDBControl.java @@ -401,7 +401,7 @@ public class GDBControl extends AbstractMIControl { return fInferiorProcess.getState() != MIInferiorProcess.State.TERMINATED && fConnected; } - void setConnected(boolean connected) { + public void setConnected(boolean connected) { fConnected = connected; } diff --git a/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIProcesses.java b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIProcesses.java index 397438ffa64..5311d6bbcbf 100644 --- a/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIProcesses.java +++ b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/MIProcesses.java @@ -31,6 +31,7 @@ import org.eclipse.dd.mi.internal.MIPlugin; import org.eclipse.dd.mi.service.command.AbstractMIControl; import org.eclipse.dd.mi.service.command.MIControlDMContext; import org.eclipse.dd.mi.service.command.commands.CLIAttach; +import org.eclipse.dd.mi.service.command.commands.CLIDetach; import org.eclipse.dd.mi.service.command.commands.CLIInfoThreads; import org.eclipse.dd.mi.service.command.output.CLIInfoThreadsInfo; import org.eclipse.dd.mi.service.command.output.MIInfo; @@ -380,33 +381,22 @@ public class MIProcesses extends AbstractDsfService implements IProcesses { } public void canDetachDebuggerFromProcess(IProcessDMContext procCtx, DataRequestMonitor rm) { - rm.setData(true); + rm.setData(false); rm.done(); } public void detachDebuggerFromProcess(IProcessDMContext procCtx, final RequestMonitor rm) { -// if (procCtx instanceof MIProcessDMC) { -// int pid; -// try { -// pid = Integer.parseInt(((MIProcessDMC)procCtx).getId()); -// } catch (NumberFormatException e) { -// rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid process id.", null)); //$NON-NLS-1$ -// rm.done(); -// return; -// } -// -// // The service version cannot use -target-detach because it didn't exist -// // in versions of GDB up to and including GDB 6.8 -// fCommandControl.queueCommand( -// new CLIDetach(procCtx, pid), -// new DataRequestMonitor(getExecutor(), rm)); -// } else { -// rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$ -// rm.done(); -// } - rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, - NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$ - rm.done(); + if (procCtx instanceof MIProcessDMC) { + MIControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, MIControlDMContext.class); + // This service version cannot use -target-detach because it didn't exist + // in versions of GDB up to and including GDB 6.8 + fCommandControl.queueCommand( + new CLIDetach(controlDmc), + new DataRequestMonitor(getExecutor(), rm)); + } else { + rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$ + rm.done(); + } } public void canTerminate(IThreadDMContext thread, DataRequestMonitor rm) { diff --git a/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/command/commands/CLIDetach.java b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/command/commands/CLIDetach.java new file mode 100644 index 00000000000..1582f0ed61e --- /dev/null +++ b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/command/commands/CLIDetach.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2008 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.dd.mi.service.command.commands; + +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.mi.service.command.output.MIInfo; + +/** + * This command disconnects from a remote target. + */ +public class CLIDetach extends CLICommand { + + public CLIDetach(IDMContext ctx) { + super(ctx, "detach"); //$NON-NLS-1$ + } +}