mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 10:16:03 +02:00
Bug 434558 - Disconnect actually terminates the session if launch
element is selected Change-Id: I7a0064b9d9ed316079f0da80834fef278701f568 Reviewed-on: https://git.eclipse.org/r/26318 Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com> Reviewed-by: Mikhail Khodjaiants <mikhailkhod@googlemail.com> Tested-by: Mikhail Khodjaiants <mikhailkhod@googlemail.com>
This commit is contained in:
parent
863def95be
commit
b38273c84d
10 changed files with 799 additions and 185 deletions
|
@ -11,14 +11,16 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
|
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
|
||||||
|
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IMultiTerminate;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||||
|
@ -28,10 +30,16 @@ import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession.SessionEndedListener;
|
import org.eclipse.cdt.dsf.service.DsfSession.SessionEndedListener;
|
||||||
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.MultiStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.debug.core.DebugException;
|
||||||
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
||||||
import org.eclipse.debug.core.commands.IEnabledStateRequest;
|
import org.eclipse.debug.core.commands.IEnabledStateRequest;
|
||||||
import org.eclipse.debug.core.commands.ITerminateHandler;
|
import org.eclipse.debug.core.commands.ITerminateHandler;
|
||||||
|
import org.eclipse.debug.core.model.IProcess;
|
||||||
|
|
||||||
public class DsfTerminateCommand implements ITerminateHandler {
|
public class DsfTerminateCommand implements ITerminateHandler {
|
||||||
private final DsfSession fSession;
|
private final DsfSession fSession;
|
||||||
|
@ -50,147 +58,111 @@ public class DsfTerminateCommand implements ITerminateHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void canExecute(final IEnabledStateRequest request) {
|
public void canExecute(final IEnabledStateRequest request) {
|
||||||
if (request.getElements().length != 1 ||
|
if (request.getElements().length == 0) {
|
||||||
!(request.getElements()[0] instanceof IDMVMContext ||
|
|
||||||
request.getElements()[0] instanceof GdbLaunch)) {
|
|
||||||
request.setEnabled(false);
|
request.setEnabled(false);
|
||||||
request.done();
|
request.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.getElements()[0] instanceof GdbLaunch) {
|
final GdbLaunch launch = getLaunch(request);
|
||||||
canExecute(((GdbLaunch)request.getElements()[0]), request);
|
if (launch != null) {
|
||||||
return;
|
fExecutor.execute(new DsfRunnable() {
|
||||||
}
|
@Override
|
||||||
|
public void run() {
|
||||||
IDMVMContext vmc = (IDMVMContext)request.getElements()[0];
|
request.setEnabled(false);
|
||||||
|
IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
|
||||||
// First check if there is an ancestor process to terminate. This is the smallest entity we can terminate
|
if (gdbControl != null && gdbControl.isActive()) {
|
||||||
final IProcessDMContext processDmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IProcessDMContext.class);
|
request.setEnabled(true);
|
||||||
if (processDmc == null) {
|
}
|
||||||
request.setEnabled(false);
|
else {
|
||||||
request.done();
|
// The GDB session may be terminated at this moment but if there
|
||||||
return;
|
// are processes in this launch that are not controlled by GDB
|
||||||
}
|
// we need to check them as well.
|
||||||
|
for (IProcess p : launch.getProcesses()) {
|
||||||
canExecute(processDmc, request);
|
if (p.canTerminate()) {
|
||||||
|
request.setEnabled(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fExecutor.execute(new DsfRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
IProcessDMContext[] procDmcs = getProcessDMContexts(request.getElements());
|
||||||
|
canTerminate(procDmcs, new DataRequestMonitor<Boolean>(fExecutor, null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (!isSuccess()) {
|
||||||
|
request.setEnabled(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
request.setEnabled(getData());
|
||||||
|
}
|
||||||
|
request.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(final IDebugCommandRequest request) {
|
public boolean execute(final IDebugCommandRequest request) {
|
||||||
if (request.getElements().length != 1 ||
|
if (request.getElements().length == 0) {
|
||||||
!(request.getElements()[0] instanceof IDMVMContext ||
|
|
||||||
request.getElements()[0] instanceof GdbLaunch)) {
|
|
||||||
request.done();
|
request.done();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.getElements()[0] instanceof GdbLaunch) {
|
final GdbLaunch launch = getLaunch(request);
|
||||||
return execute(((GdbLaunch)request.getElements()[0]), request);
|
if (launch != null) {
|
||||||
|
fExecutor.execute(new DsfRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
|
||||||
|
if (gdbControl != null && gdbControl.isActive()) {
|
||||||
|
gdbControl.terminate(new RequestMonitor(fExecutor, null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (!isSuccess()) {
|
||||||
|
request.setStatus(getStatus());
|
||||||
|
request.done();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
waitForTermination(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
terminateRemainingProcesses(launch, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
IDMVMContext vmc = (IDMVMContext)request.getElements()[0];
|
fExecutor.execute(new DsfRunnable() {
|
||||||
|
@Override
|
||||||
// First check if there is an ancestor process to terminate. This is the smallest entity we can terminate
|
public void run() {
|
||||||
final IProcessDMContext processDmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IProcessDMContext.class);
|
IProcessDMContext[] procDmcs = getProcessDMContexts(request.getElements());
|
||||||
if (processDmc == null) {
|
terminate(procDmcs, new RequestMonitor(fExecutor, null) {
|
||||||
request.done();
|
@Override
|
||||||
return false;
|
protected void handleCompleted() {
|
||||||
}
|
if (!isSuccess()) {
|
||||||
|
request.setStatus(getStatus());
|
||||||
return execute(processDmc, request);
|
request.done();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
private void canExecute(GdbLaunch launch, IEnabledStateRequest request) {
|
waitForTermination(request);
|
||||||
request.setEnabled(launch.canTerminate());
|
}
|
||||||
request.done();
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
private boolean execute(GdbLaunch launch, final IDebugCommandRequest request) {
|
});
|
||||||
try {
|
|
||||||
fExecutor.execute(new DsfRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final IGDBControl commandControl = fTracker.getService(IGDBControl.class);
|
|
||||||
if (commandControl != null) {
|
|
||||||
commandControl.terminate(new ImmediateRequestMonitor() {
|
|
||||||
@Override
|
|
||||||
protected void handleCompleted() {
|
|
||||||
if (!isSuccess()) {
|
|
||||||
request.setStatus(getStatus());
|
|
||||||
request.done();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
waitForTermination(request);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
request.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (RejectedExecutionException e) {
|
|
||||||
request.done();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void canExecute(final IProcessDMContext processDmc, final IEnabledStateRequest request) {
|
|
||||||
try {
|
|
||||||
fExecutor.execute(
|
|
||||||
new DsfRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// Get the processes service and the exec context.
|
|
||||||
IProcesses procService = fTracker.getService(IProcesses.class);
|
|
||||||
if (procService == null) {
|
|
||||||
// Service already invalid.
|
|
||||||
request.setEnabled(false);
|
|
||||||
request.done();
|
|
||||||
} else {
|
|
||||||
procService.canTerminate(processDmc, new ImmediateDataRequestMonitor<Boolean>() {
|
|
||||||
@Override
|
|
||||||
protected void handleCompleted() {
|
|
||||||
request.setEnabled(isSuccess() && getData());
|
|
||||||
request.done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (RejectedExecutionException e) {
|
|
||||||
request.setEnabled(false);
|
|
||||||
request.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean execute(final IProcessDMContext processDmc, final IDebugCommandRequest request) {
|
|
||||||
try {
|
|
||||||
fExecutor.execute(new DsfRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
IProcesses procService = fTracker.getService(IProcesses.class);
|
|
||||||
if (procService != null) {
|
|
||||||
procService.terminate(processDmc, new ImmediateRequestMonitor() {
|
|
||||||
@Override
|
|
||||||
protected void handleCompleted() {
|
|
||||||
if (!isSuccess()) {
|
|
||||||
request.setStatus(getStatus());
|
|
||||||
request.done();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
waitForTermination(request);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
request.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (RejectedExecutionException e) {
|
|
||||||
request.done();
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +189,13 @@ public class DsfTerminateCommand implements ITerminateHandler {
|
||||||
public void sessionEnded(DsfSession session) {
|
public void sessionEnded(DsfSession session) {
|
||||||
if (fSession.equals(session)) {
|
if (fSession.equals(session)) {
|
||||||
DsfSession.removeSessionEndedListener(this);
|
DsfSession.removeSessionEndedListener(this);
|
||||||
request.done();
|
GdbLaunch launch = getLaunch(request);
|
||||||
|
if (launch != null) {
|
||||||
|
terminateRemainingProcesses(launch, request);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
request.done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -254,4 +232,111 @@ public class DsfTerminateCommand implements ITerminateHandler {
|
||||||
}},
|
}},
|
||||||
1, TimeUnit.MINUTES);
|
1, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IProcessDMContext[] getProcessDMContexts(Object[] elements) {
|
||||||
|
final Set<IProcessDMContext> procDmcs = new HashSet<IProcessDMContext>();
|
||||||
|
for (Object obj : elements) {
|
||||||
|
if (obj instanceof IDMVMContext) {
|
||||||
|
IProcessDMContext procDmc =
|
||||||
|
DMContexts.getAncestorOfType(((IDMVMContext)obj).getDMContext(), IProcessDMContext.class);
|
||||||
|
if (procDmc != null) {
|
||||||
|
procDmcs.add(procDmc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return procDmcs.toArray(new IProcessDMContext[procDmcs.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void canTerminate(IProcessDMContext[] procDmcs, DataRequestMonitor<Boolean> rm) {
|
||||||
|
if (procDmcs.length == 0) {
|
||||||
|
IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
|
||||||
|
if (gdbControl != null) {
|
||||||
|
rm.setData(gdbControl.isActive());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, "Service is not available.")); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMultiTerminate multiTerminate = fTracker.getService(IMultiTerminate.class);
|
||||||
|
if (multiTerminate != null) {
|
||||||
|
multiTerminate.canTerminateSome(procDmcs, rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
IProcesses procService = fTracker.getService(IProcesses.class);
|
||||||
|
if (procService != null && procDmcs.length == 1) {
|
||||||
|
procService.canTerminate(procDmcs[0], rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rm.setData(false);
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void terminate(IProcessDMContext[] procDmcs, RequestMonitor rm) {
|
||||||
|
if (procDmcs.length == 0) {
|
||||||
|
IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
|
||||||
|
if (gdbControl != null) {
|
||||||
|
gdbControl.terminate(rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMultiTerminate multiTerminate = fTracker.getService(IMultiTerminate.class);
|
||||||
|
if (multiTerminate != null) {
|
||||||
|
multiTerminate.terminate(procDmcs, rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
IProcesses procService = fTracker.getService(IProcesses.class);
|
||||||
|
if (procService != null && procDmcs.length == 1) {
|
||||||
|
procService.terminate(procDmcs[0], rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GdbLaunch getLaunch(IDebugCommandRequest request) {
|
||||||
|
for (Object el : request.getElements()) {
|
||||||
|
if (el instanceof GdbLaunch) {
|
||||||
|
return (GdbLaunch)el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void terminateRemainingProcesses(final GdbLaunch launch, final IDebugCommandRequest request) {
|
||||||
|
// Run this in a separate job since this method is called from
|
||||||
|
// the executor thread. The job is scheduled with a delay to make
|
||||||
|
// sure that MIInferiorProcess is terminated. See MIInferiorProcess.waitForSync()
|
||||||
|
new Job("Terminate Job") { //$NON-NLS-1$
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
MultiStatus status =
|
||||||
|
new MultiStatus(GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, Messages.DsfTerminateCommand_Terminate_failed, null);
|
||||||
|
for (IProcess p : launch.getProcesses()) {
|
||||||
|
if (p.canTerminate()) {
|
||||||
|
try {
|
||||||
|
p.terminate();
|
||||||
|
}
|
||||||
|
catch(DebugException e) {
|
||||||
|
status.merge(e.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!status.isOK()) {
|
||||||
|
request.setStatus(status);
|
||||||
|
}
|
||||||
|
request.done();
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
}.schedule(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,81 +10,281 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
|
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IMultiDetach;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
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.IContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfCommandRunnable;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfSession.SessionEndedListener;
|
||||||
|
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
||||||
import org.eclipse.debug.core.commands.IDisconnectHandler;
|
import org.eclipse.debug.core.commands.IDisconnectHandler;
|
||||||
import org.eclipse.debug.core.commands.IEnabledStateRequest;
|
import org.eclipse.debug.core.commands.IEnabledStateRequest;
|
||||||
|
|
||||||
public class GdbDisconnectCommand implements IDisconnectHandler {
|
public class GdbDisconnectCommand implements IDisconnectHandler {
|
||||||
private final DsfExecutor fExecutor;
|
private final DsfSession fSession;
|
||||||
|
private final DsfExecutor fExecutor;
|
||||||
private final DsfServicesTracker fTracker;
|
private final DsfServicesTracker fTracker;
|
||||||
|
|
||||||
public GdbDisconnectCommand(DsfSession session) {
|
public GdbDisconnectCommand(DsfSession session) {
|
||||||
fExecutor = session.getExecutor();
|
super();
|
||||||
|
fSession = session;
|
||||||
|
fExecutor = session.getExecutor();
|
||||||
fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
|
fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
fTracker.dispose();
|
fTracker.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void canExecute(final IEnabledStateRequest request) {
|
public void canExecute(final IEnabledStateRequest request) {
|
||||||
if (request.getElements().length != 1) {
|
if (request.getElements().length == 0) {
|
||||||
request.setEnabled(false);
|
request.setEnabled(false);
|
||||||
request.done();
|
request.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
|
getContainerDMContexts(request.getElements(), new DataRequestMonitor<IContainerDMContext[]>(fExecutor, null) {
|
||||||
@Override public void doExecute() {
|
@Override
|
||||||
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getContext(), IContainerDMContext.class);
|
protected void handleCompleted() {
|
||||||
IProcesses procService = getProcessService();
|
if (!isSuccess()) {
|
||||||
|
request.setEnabled(false);
|
||||||
if (procService != null) {
|
request.done();
|
||||||
procService.canDetachDebuggerFromProcess(
|
}
|
||||||
containerDmc,
|
else {
|
||||||
new DataRequestMonitor<Boolean>(fExecutor, null) {
|
canDisconnect(getData(), new ImmediateDataRequestMonitor<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
request.setEnabled(isSuccess() && getData());
|
if (!isSuccess()) {
|
||||||
request.done();
|
request.setEnabled(false);
|
||||||
}
|
}
|
||||||
});
|
else {
|
||||||
} else {
|
request.setEnabled(getData());;
|
||||||
request.setEnabled(false);
|
}
|
||||||
request.done();
|
request.done();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(final IDebugCommandRequest request) {
|
public boolean execute(final IDebugCommandRequest request) {
|
||||||
if (request.getElements().length != 1) {
|
if (request.getElements().length == 0) {
|
||||||
request.done();
|
request.done();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
|
getContainerDMContexts(request.getElements(), new DataRequestMonitor<IContainerDMContext[]>(fExecutor, null) {
|
||||||
@Override public void doExecute() {
|
@Override
|
||||||
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getContext(), IContainerDMContext.class);
|
protected void handleCompleted() {
|
||||||
IProcesses procService = getProcessService();
|
if (!isSuccess()) {
|
||||||
|
request.setStatus(getStatus());
|
||||||
if (procService != null) {
|
request.done();
|
||||||
procService.detachDebuggerFromProcess(containerDmc, new RequestMonitor(fExecutor, null));
|
}
|
||||||
}
|
else {
|
||||||
}
|
disconnect(getData(), new ImmediateRequestMonitor() {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (!isSuccess()) {
|
||||||
|
request.setStatus(getStatus());
|
||||||
|
request.done();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
waitForTermination(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return false;
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the debug session to be fully shutdown before reporting
|
||||||
|
* that the terminate was completed. This is important for the
|
||||||
|
* 'Terminate and remove' operation.
|
||||||
|
* The wait time is limited with a timeout so as to eventually complete the
|
||||||
|
* request in the case of termination error, or when terminating
|
||||||
|
* a single process in a multi-process session.
|
||||||
|
* See bug 377447
|
||||||
|
*/
|
||||||
|
private void waitForTermination(final IDebugCommandRequest request) {
|
||||||
|
// It is possible that the session already had time to terminate
|
||||||
|
if (!DsfSession.isSessionActive(fSession.getId())) {
|
||||||
|
request.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listener that will indicate when the shutdown is complete
|
||||||
|
final SessionEndedListener endedListener = new SessionEndedListener () {
|
||||||
|
@Override
|
||||||
|
public void sessionEnded(DsfSession session) {
|
||||||
|
if (fSession.equals(session)) {
|
||||||
|
DsfSession.removeSessionEndedListener(this);
|
||||||
|
request.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DsfSession.addSessionEndedListener(endedListener);
|
||||||
|
|
||||||
|
// Create the timeout
|
||||||
|
// For a multi-process session, if a single process is
|
||||||
|
// terminated, this timeout will always hit (unless the
|
||||||
|
// session is also terminated before the timeout).
|
||||||
|
// We haven't found a problem with delaying the completion
|
||||||
|
// of the request that way.
|
||||||
|
// Note that this timeout is not removed even if we don't
|
||||||
|
// need it anymore, once the session has terminated;
|
||||||
|
// instead, we let it timeout and ignore it if the session
|
||||||
|
// is already terminated.
|
||||||
|
fExecutor.schedule(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Check that the session is still active when the timeout hits.
|
||||||
|
// If it is not, then everything has been cleaned up already.
|
||||||
|
if (DsfSession.isSessionActive(fSession.getId())) {
|
||||||
|
DsfSession.removeSessionEndedListener(endedListener);
|
||||||
|
|
||||||
|
// Marking the request as cancelled will prevent the removal of
|
||||||
|
// the launch from the Debug view in case of "Terminate and Remove".
|
||||||
|
// This is important for multi-process sessions when "Terminate and Remove"
|
||||||
|
// is applied to one of the running processes. In this case the selected
|
||||||
|
// process will be terminated but the associated launch will not be removed
|
||||||
|
// from the Debug view.
|
||||||
|
request.setStatus(Status.CANCEL_STATUS);
|
||||||
|
request.done();
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
1, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getContainerDMContexts(Object[] elements, final DataRequestMonitor<IContainerDMContext[]> rm) {
|
||||||
|
GdbLaunch launch = null;
|
||||||
|
final Set<IContainerDMContext> contDmcs = new HashSet<IContainerDMContext>();
|
||||||
|
for (Object obj : elements) {
|
||||||
|
if (obj instanceof GdbLaunch) {
|
||||||
|
launch = (GdbLaunch)obj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (obj instanceof IDMVMContext) {
|
||||||
|
IContainerDMContext contDmc =
|
||||||
|
DMContexts.getAncestorOfType(((IDMVMContext)obj).getDMContext(), IContainerDMContext.class);
|
||||||
|
if (contDmc != null) {
|
||||||
|
contDmcs.add(contDmc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (launch == null) {
|
||||||
|
rm.setData(contDmcs.toArray(new IContainerDMContext[contDmcs.size()]));
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
fExecutor.execute(new DsfRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ICommandControlService commandControl = fTracker.getService(ICommandControlService.class);
|
||||||
|
final IProcesses procService = fTracker.getService(IProcesses.class);
|
||||||
|
if (commandControl != null && procService != null) {
|
||||||
|
procService.getProcessesBeingDebugged(
|
||||||
|
commandControl.getContext(),
|
||||||
|
new ImmediateDataRequestMonitor<IDMContext[]>() {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (!isSuccess()) {
|
||||||
|
rm.setStatus(getStatus());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (IDMContext ctx : getData()) {
|
||||||
|
IContainerDMContext contDmc = DMContexts.getAncestorOfType(ctx, IContainerDMContext.class);
|
||||||
|
if (contDmc != null) {
|
||||||
|
contDmcs.add(contDmc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rm.setData(contDmcs.toArray(new IContainerDMContext[contDmcs.size()]));
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, "Service is not available.")); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, e.getLocalizedMessage()));
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void canDisconnect(IContainerDMContext[] contDmcs, DataRequestMonitor<Boolean> rm) {
|
||||||
|
if (contDmcs.length == 0) {
|
||||||
|
rm.setData(false);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMultiDetach multiDetach = fTracker.getService(IMultiDetach.class);
|
||||||
|
if (multiDetach != null) {
|
||||||
|
multiDetach.canDetachDebuggerFromSomeProcesses(contDmcs, rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
IProcesses procService = fTracker.getService(IProcesses.class);
|
||||||
|
if (procService != null && contDmcs.length == 1) {
|
||||||
|
procService.canDetachDebuggerFromProcess(contDmcs[0], rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rm.setData(false);
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disconnect(IContainerDMContext[] contDmcs, RequestMonitor rm) {
|
||||||
|
if (contDmcs.length == 0) {
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMultiDetach multiDetach = fTracker.getService(IMultiDetach.class);
|
||||||
|
if (multiDetach != null) {
|
||||||
|
multiDetach.detachDebuggerFromProcesses(contDmcs, rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
IProcesses procService = fTracker.getService(IProcesses.class);
|
||||||
|
if (procService != null && contDmcs.length == 1) {
|
||||||
|
procService.detachDebuggerFromProcess(contDmcs[0], rm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2014 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
|
||||||
|
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
|
||||||
|
public class Messages extends NLS {
|
||||||
|
public static String DsfTerminateCommand_Terminate_failed;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// initialize resource bundle
|
||||||
|
NLS.initializeMessages(Messages.class.getName(), Messages.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Messages() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
###############################################################################
|
||||||
|
# Copyright (c) 2014 Mentor Graphics 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:
|
||||||
|
# Mentor Graphics - Initial API and implementation
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
DsfTerminateCommand_Terminate_failed=Terminate failed
|
|
@ -57,6 +57,7 @@ import org.eclipse.debug.core.ILaunch;
|
||||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
import org.eclipse.debug.core.IStatusHandler;
|
import org.eclipse.debug.core.IStatusHandler;
|
||||||
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
||||||
|
import org.eclipse.debug.core.commands.IDisconnectHandler;
|
||||||
import org.eclipse.debug.core.commands.ITerminateHandler;
|
import org.eclipse.debug.core.commands.ITerminateHandler;
|
||||||
import org.eclipse.debug.core.model.IDisconnect;
|
import org.eclipse.debug.core.model.IDisconnect;
|
||||||
import org.eclipse.debug.core.model.ISourceLocator;
|
import org.eclipse.debug.core.model.ISourceLocator;
|
||||||
|
@ -195,10 +196,10 @@ public class GdbLaunch extends DsfLaunch
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// ITerminate
|
// ITerminate
|
||||||
|
|
||||||
static class TerminateRequest extends CRequest implements IDebugCommandRequest {
|
static class LaunchCommandRequest extends CRequest implements IDebugCommandRequest {
|
||||||
Object[] elements;
|
Object[] elements;
|
||||||
|
|
||||||
public TerminateRequest(Object[] objects) {
|
public LaunchCommandRequest(Object[] objects) {
|
||||||
elements = objects;
|
elements = objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +245,7 @@ public class GdbLaunch extends DsfLaunch
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminateRequest req = new TerminateRequest(new Object[] {this});
|
LaunchCommandRequest req = new LaunchCommandRequest(new Object[] {this});
|
||||||
handler.execute(req);
|
handler.execute(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +266,14 @@ public class GdbLaunch extends DsfLaunch
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect() throws DebugException {
|
public void disconnect() throws DebugException {
|
||||||
terminate();
|
IDisconnectHandler handler = (IDisconnectHandler)getAdapter(IDisconnectHandler.class);
|
||||||
|
if (handler == null) {
|
||||||
|
super.disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchCommandRequest req = new LaunchCommandRequest(new Object[] {this});
|
||||||
|
handler.execute(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDisconnect
|
// IDisconnect
|
||||||
|
@ -362,6 +370,8 @@ public class GdbLaunch extends DsfLaunch
|
||||||
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=377447.
|
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=377447.
|
||||||
if (adapter.equals(ITerminateHandler.class))
|
if (adapter.equals(ITerminateHandler.class))
|
||||||
return getSession().getModelAdapter(adapter);
|
return getSession().getModelAdapter(adapter);
|
||||||
|
if (adapter.equals(IDisconnectHandler.class))
|
||||||
|
return getSession().getModelAdapter(adapter);
|
||||||
|
|
||||||
// Allow to call the connect handler when the launch is selected
|
// Allow to call the connect handler when the launch is selected
|
||||||
if (adapter.equals(IConnectHandler.class))
|
if (adapter.equals(IConnectHandler.class))
|
||||||
|
|
|
@ -12,11 +12,15 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.gdb.service;
|
package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
||||||
|
@ -28,6 +32,8 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IMultiDetach;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IMultiTerminate;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
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.IExitedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||||
|
@ -58,9 +64,71 @@ import org.eclipse.debug.core.ILaunch;
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
public class GDBProcesses_7_2 extends GDBProcesses_7_1 implements IMultiTerminate, IMultiDetach {
|
||||||
|
|
||||||
/**
|
abstract private class ConditionalRequestMonitor extends ImmediateDataRequestMonitor<Boolean> {
|
||||||
|
|
||||||
|
private Iterator<? extends IDMContext> fIterator;
|
||||||
|
private boolean fAll = true;
|
||||||
|
private DataRequestMonitor<Boolean> fParentMonitor;
|
||||||
|
|
||||||
|
private ConditionalRequestMonitor(Iterator<? extends IDMContext> it, boolean all, DataRequestMonitor<Boolean> parentMonitor) {
|
||||||
|
super(parentMonitor);
|
||||||
|
fAll = all;
|
||||||
|
fParentMonitor = parentMonitor;
|
||||||
|
fIterator = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (!isSuccess()) {
|
||||||
|
fParentMonitor.setStatus(getStatus());
|
||||||
|
fParentMonitor.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getData() != fAll) {
|
||||||
|
fParentMonitor.setData(getData());
|
||||||
|
fParentMonitor.done();
|
||||||
|
}
|
||||||
|
else if (!fIterator.hasNext()) {
|
||||||
|
fParentMonitor.setData(fAll);
|
||||||
|
fParentMonitor.done();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proceed(fIterator, fAll, fParentMonitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected void proceed(Iterator<? extends IDMContext> it, boolean all, DataRequestMonitor<Boolean> parentMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CanDetachRequestMonitor extends ConditionalRequestMonitor {
|
||||||
|
|
||||||
|
private CanDetachRequestMonitor(Iterator<? extends IDMContext> it, boolean all, DataRequestMonitor<Boolean> parentMonitor) {
|
||||||
|
super(it, all, parentMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void proceed(Iterator<? extends IDMContext> it, boolean all, DataRequestMonitor<Boolean> parentMonitor) {
|
||||||
|
canDetachDebuggerFromProcess(it.next(), new CanDetachRequestMonitor(it, all, parentMonitor));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CanTerminateRequestMonitor extends ConditionalRequestMonitor {
|
||||||
|
|
||||||
|
private CanTerminateRequestMonitor(Iterator<? extends IDMContext> it, boolean all, DataRequestMonitor<Boolean> parentMonitor) {
|
||||||
|
super(it, all, parentMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void proceed(Iterator<? extends IDMContext> it, boolean all, DataRequestMonitor<Boolean> parentMonitor) {
|
||||||
|
canTerminate((IThreadDMContext)it.next(), new CanTerminateRequestMonitor(it, all, parentMonitor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* The id of the single thread to be used during event visualization.
|
* The id of the single thread to be used during event visualization.
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
|
@ -114,6 +182,8 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
||||||
* initialization is done.
|
* initialization is done.
|
||||||
*/
|
*/
|
||||||
private void doInitialize(RequestMonitor requestMonitor) {
|
private void doInitialize(RequestMonitor requestMonitor) {
|
||||||
|
register(new String[]{ IMultiDetach.class.getName(), IMultiTerminate.class.getName() }, new Hashtable<String,String>());
|
||||||
|
|
||||||
fCommandControl = getServicesTracker().getService(IGDBControl.class);
|
fCommandControl = getServicesTracker().getService(IGDBControl.class);
|
||||||
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
||||||
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
||||||
|
@ -607,5 +677,112 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
||||||
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
|
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
|
||||||
setTraceVisualization(e.isVisualizationModeEnabled());
|
setTraceVisualization(e.isVisualizationModeEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.6
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void canDetachDebuggerFromSomeProcesses(IDMContext[] dmcs, final DataRequestMonitor<Boolean> rm) {
|
||||||
|
canDetachFromProcesses(dmcs, false, rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.6
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void canDetachDebuggerFromAllProcesses(IDMContext[] dmcs, DataRequestMonitor<Boolean> rm) {
|
||||||
|
canDetachFromProcesses(dmcs, true, rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.6
|
||||||
|
*/
|
||||||
|
protected void canDetachFromProcesses(IDMContext[] dmcs, boolean all, DataRequestMonitor<Boolean> rm) {
|
||||||
|
Set<IMIContainerDMContext> contDmcs = new HashSet<IMIContainerDMContext>();
|
||||||
|
for (IDMContext c : dmcs) {
|
||||||
|
IMIContainerDMContext contDmc = DMContexts.getAncestorOfType(c, IMIContainerDMContext.class);
|
||||||
|
if (contDmc != null) {
|
||||||
|
contDmcs.add(contDmc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<IMIContainerDMContext> it = contDmcs.iterator();
|
||||||
|
if (!it.hasNext()) {
|
||||||
|
rm.setData(false);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
canDetachDebuggerFromProcess(it.next(), new CanDetachRequestMonitor(it, all, rm));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.6
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void detachDebuggerFromProcesses(IDMContext[] dmcs, final RequestMonitor rm) {
|
||||||
|
Set<IMIContainerDMContext> contDmcs = new HashSet<IMIContainerDMContext>();
|
||||||
|
for (IDMContext c : dmcs) {
|
||||||
|
IMIContainerDMContext contDmc = DMContexts.getAncestorOfType(c, IMIContainerDMContext.class);
|
||||||
|
if (contDmc != null) {
|
||||||
|
contDmcs.add(contDmc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (contDmcs.isEmpty()) {
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CountingRequestMonitor crm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), rm);
|
||||||
|
crm.setDoneCount(contDmcs.size());
|
||||||
|
for (IMIContainerDMContext contDmc : contDmcs) {
|
||||||
|
detachDebuggerFromProcess(contDmc, crm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.6
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void canTerminateSome(IThreadDMContext[] dmcs, DataRequestMonitor<Boolean> rm) {
|
||||||
|
canTerminate(dmcs, false, rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.6
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void canTerminateAll(IThreadDMContext[] dmcs, DataRequestMonitor<Boolean> rm) {
|
||||||
|
canTerminate(dmcs, true, rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.6
|
||||||
|
*/
|
||||||
|
protected void canTerminate(IThreadDMContext[] dmcs, boolean all, DataRequestMonitor<Boolean> rm) {
|
||||||
|
Iterator<IThreadDMContext> it = Arrays.asList(dmcs).iterator();
|
||||||
|
if (!it.hasNext()) {
|
||||||
|
rm.setData(false);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
canTerminate(it.next(), new CanTerminateRequestMonitor(it, all, rm));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.6
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void terminate(IThreadDMContext[] dmcs, RequestMonitor rm) {
|
||||||
|
if (dmcs.length == 0) {
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CountingRequestMonitor crm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), rm);
|
||||||
|
crm.setDoneCount(dmcs.length);
|
||||||
|
for (IThreadDMContext threadDmc : dmcs) {
|
||||||
|
terminate(threadDmc, crm);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: %pluginName
|
Bundle-Name: %pluginName
|
||||||
Bundle-Vendor: %providerName
|
Bundle-Vendor: %providerName
|
||||||
Bundle-SymbolicName: org.eclipse.cdt.dsf;singleton:=true
|
Bundle-SymbolicName: org.eclipse.cdt.dsf;singleton:=true
|
||||||
Bundle-Version: 2.5.0.qualifier
|
Bundle-Version: 2.6.0.qualifier
|
||||||
Bundle-Activator: org.eclipse.cdt.dsf.internal.DsfPlugin
|
Bundle-Activator: org.eclipse.cdt.dsf.internal.DsfPlugin
|
||||||
Bundle-Localization: plugin
|
Bundle-Localization: plugin
|
||||||
Require-Bundle: org.eclipse.core.runtime,
|
Require-Bundle: org.eclipse.core.runtime,
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<version>2.5.0-SNAPSHOT</version>
|
<version>2.6.0-SNAPSHOT</version>
|
||||||
<artifactId>org.eclipse.cdt.dsf</artifactId>
|
<artifactId>org.eclipse.cdt.dsf</artifactId>
|
||||||
<packaging>eclipse-plugin</packaging>
|
<packaging>eclipse-plugin</packaging>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2014 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.debug.service;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface provides the ability to perform detach on multiple contexts.
|
||||||
|
*
|
||||||
|
* @since 2.6
|
||||||
|
*/
|
||||||
|
public interface IMultiDetach {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether it is possible to detach the debugger from at least one
|
||||||
|
* of the specified processes.
|
||||||
|
*
|
||||||
|
* @param dmcs The contexts to detach the debugger from. Each context
|
||||||
|
* should have {@link IContainerDMContext} as an ancestor.
|
||||||
|
* @param rm Request monitor returning whether there is at least one context
|
||||||
|
* that can be detached from the debugger.
|
||||||
|
*/
|
||||||
|
void canDetachDebuggerFromSomeProcesses(IDMContext[] dmcs, DataRequestMonitor<Boolean> rm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether it is possible to detach the debugger from all of the specified processes.
|
||||||
|
*
|
||||||
|
* @param dmc The contexts to detach the debugger from. Each context
|
||||||
|
* should have {@link IContainerDMContext} as an ancestor.
|
||||||
|
* @param rm Request monitor returning whether all processes specified by the given contexts
|
||||||
|
* that can be detached from the debugger.
|
||||||
|
*/
|
||||||
|
void canDetachDebuggerFromAllProcesses(IDMContext[] dmcs, DataRequestMonitor<Boolean> rm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to detach debugger from the specified processes. Only contexts
|
||||||
|
* that are in a state that can be detached will be affected, others will be ignored.
|
||||||
|
*
|
||||||
|
* @param dmc The contexts to detach the debugger from. Each context
|
||||||
|
* should have {@link IContainerDMContext} as an ancestor.
|
||||||
|
*/
|
||||||
|
void detachDebuggerFromProcesses(IDMContext[] dmcs, RequestMonitor rm);
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2014 Mentor Graphics 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:
|
||||||
|
* Mentor Graphics - Initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.debug.service;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface provides the ability to perform terminate on multiple contexts.
|
||||||
|
*
|
||||||
|
* @since 2.6
|
||||||
|
*/
|
||||||
|
public interface IMultiTerminate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether it is possible to terminate at least one of the specified threads
|
||||||
|
* or processes.
|
||||||
|
*
|
||||||
|
* @param dmcs The contexts of the threads to terminate
|
||||||
|
* @param rm Request monitor returning whether there is at least one thread or process can be terminated.
|
||||||
|
*/
|
||||||
|
void canTerminateSome(IThreadDMContext[] dmcs, DataRequestMonitor<Boolean> rm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether it is possible to terminate all of the specified threads or processes.
|
||||||
|
*
|
||||||
|
* @param dmcs The contexts of the threads or processes to terminate
|
||||||
|
* @param rm Request monitor returning whether all of the threads can be terminated.
|
||||||
|
*/
|
||||||
|
void canTerminateAll(IThreadDMContext[] dmcs, DataRequestMonitor<Boolean> rm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to terminate the specified threads or processes. Only threads and processes
|
||||||
|
* that can be terminated will be affected, others will be ignored.
|
||||||
|
*
|
||||||
|
* @param dmc The contexts of the threads or processes to terminate.
|
||||||
|
*/
|
||||||
|
void terminate(IThreadDMContext[] dmcs, RequestMonitor rm);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue