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;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
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.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.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.IProcessDMContext;
|
||||
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.SessionEndedListener;
|
||||
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.jobs.Job;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
||||
import org.eclipse.debug.core.commands.IEnabledStateRequest;
|
||||
import org.eclipse.debug.core.commands.ITerminateHandler;
|
||||
import org.eclipse.debug.core.model.IProcess;
|
||||
|
||||
public class DsfTerminateCommand implements ITerminateHandler {
|
||||
private final DsfSession fSession;
|
||||
|
@ -50,70 +58,74 @@ public class DsfTerminateCommand implements ITerminateHandler {
|
|||
|
||||
@Override
|
||||
public void canExecute(final IEnabledStateRequest request) {
|
||||
if (request.getElements().length != 1 ||
|
||||
!(request.getElements()[0] instanceof IDMVMContext ||
|
||||
request.getElements()[0] instanceof GdbLaunch)) {
|
||||
if (request.getElements().length == 0) {
|
||||
request.setEnabled(false);
|
||||
request.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.getElements()[0] instanceof GdbLaunch) {
|
||||
canExecute(((GdbLaunch)request.getElements()[0]), request);
|
||||
return;
|
||||
}
|
||||
|
||||
IDMVMContext vmc = (IDMVMContext)request.getElements()[0];
|
||||
|
||||
// First check if there is an ancestor process to terminate. This is the smallest entity we can terminate
|
||||
final IProcessDMContext processDmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IProcessDMContext.class);
|
||||
if (processDmc == null) {
|
||||
final GdbLaunch launch = getLaunch(request);
|
||||
if (launch != null) {
|
||||
fExecutor.execute(new DsfRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
request.setEnabled(false);
|
||||
request.done();
|
||||
return;
|
||||
IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
|
||||
if (gdbControl != null && gdbControl.isActive()) {
|
||||
request.setEnabled(true);
|
||||
}
|
||||
else {
|
||||
// The GDB session may be terminated at this moment but if there
|
||||
// are processes in this launch that are not controlled by GDB
|
||||
// we need to check them as well.
|
||||
for (IProcess p : launch.getProcesses()) {
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
canExecute(processDmc, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(final IDebugCommandRequest request) {
|
||||
if (request.getElements().length != 1 ||
|
||||
!(request.getElements()[0] instanceof IDMVMContext ||
|
||||
request.getElements()[0] instanceof GdbLaunch)) {
|
||||
if (request.getElements().length == 0) {
|
||||
request.done();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.getElements()[0] instanceof GdbLaunch) {
|
||||
return execute(((GdbLaunch)request.getElements()[0]), request);
|
||||
}
|
||||
|
||||
IDMVMContext vmc = (IDMVMContext)request.getElements()[0];
|
||||
|
||||
// First check if there is an ancestor process to terminate. This is the smallest entity we can terminate
|
||||
final IProcessDMContext processDmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IProcessDMContext.class);
|
||||
if (processDmc == null) {
|
||||
request.done();
|
||||
return false;
|
||||
}
|
||||
|
||||
return execute(processDmc, request);
|
||||
}
|
||||
|
||||
private void canExecute(GdbLaunch launch, IEnabledStateRequest request) {
|
||||
request.setEnabled(launch.canTerminate());
|
||||
request.done();
|
||||
}
|
||||
|
||||
private boolean execute(GdbLaunch launch, final IDebugCommandRequest request) {
|
||||
try {
|
||||
final GdbLaunch launch = getLaunch(request);
|
||||
if (launch != null) {
|
||||
fExecutor.execute(new DsfRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final IGDBControl commandControl = fTracker.getService(IGDBControl.class);
|
||||
if (commandControl != null) {
|
||||
commandControl.terminate(new ImmediateRequestMonitor() {
|
||||
IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
|
||||
if (gdbControl != null && gdbControl.isActive()) {
|
||||
gdbControl.terminate(new RequestMonitor(fExecutor, null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!isSuccess()) {
|
||||
|
@ -123,56 +135,21 @@ public class DsfTerminateCommand implements ITerminateHandler {
|
|||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
terminateRemainingProcesses(launch, request);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
request.setEnabled(false);
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean execute(final IProcessDMContext processDmc, final IDebugCommandRequest request) {
|
||||
try {
|
||||
else {
|
||||
fExecutor.execute(new DsfRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IProcesses procService = fTracker.getService(IProcesses.class);
|
||||
if (procService != null) {
|
||||
procService.terminate(processDmc, new ImmediateRequestMonitor() {
|
||||
IProcessDMContext[] procDmcs = getProcessDMContexts(request.getElements());
|
||||
terminate(procDmcs, new RequestMonitor(fExecutor, null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!isSuccess()) {
|
||||
|
@ -182,15 +159,10 @@ public class DsfTerminateCommand implements ITerminateHandler {
|
|||
else {
|
||||
waitForTermination(request);
|
||||
}
|
||||
};
|
||||
});
|
||||
} else {
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
request.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -217,9 +189,15 @@ public class DsfTerminateCommand implements ITerminateHandler {
|
|||
public void sessionEnded(DsfSession session) {
|
||||
if (fSession.equals(session)) {
|
||||
DsfSession.removeSessionEndedListener(this);
|
||||
GdbLaunch launch = getLaunch(request);
|
||||
if (launch != null) {
|
||||
terminateRemainingProcesses(launch, request);
|
||||
}
|
||||
else {
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DsfSession.addSessionEndedListener(endedListener);
|
||||
|
@ -254,4 +232,111 @@ public class DsfTerminateCommand implements ITerminateHandler {
|
|||
}},
|
||||
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,25 +10,43 @@
|
|||
*******************************************************************************/
|
||||
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.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.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.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.launching.GdbLaunch;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
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.IDisconnectHandler;
|
||||
import org.eclipse.debug.core.commands.IEnabledStateRequest;
|
||||
|
||||
public class GdbDisconnectCommand implements IDisconnectHandler {
|
||||
private final DsfSession fSession;
|
||||
private final DsfExecutor fExecutor;
|
||||
private final DsfServicesTracker fTracker;
|
||||
|
||||
public GdbDisconnectCommand(DsfSession session) {
|
||||
super();
|
||||
fSession = session;
|
||||
fExecutor = session.getExecutor();
|
||||
fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
|
||||
}
|
||||
|
@ -39,30 +57,32 @@ public class GdbDisconnectCommand implements IDisconnectHandler {
|
|||
|
||||
@Override
|
||||
public void canExecute(final IEnabledStateRequest request) {
|
||||
if (request.getElements().length != 1) {
|
||||
if (request.getElements().length == 0) {
|
||||
request.setEnabled(false);
|
||||
request.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
|
||||
@Override public void doExecute() {
|
||||
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getContext(), IContainerDMContext.class);
|
||||
IProcesses procService = getProcessService();
|
||||
|
||||
if (procService != null) {
|
||||
procService.canDetachDebuggerFromProcess(
|
||||
containerDmc,
|
||||
new DataRequestMonitor<Boolean>(fExecutor, null) {
|
||||
getContainerDMContexts(request.getElements(), new DataRequestMonitor<IContainerDMContext[]>(fExecutor, null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
request.setEnabled(isSuccess() && getData());
|
||||
if (!isSuccess()) {
|
||||
request.setEnabled(false);
|
||||
request.done();
|
||||
}
|
||||
else {
|
||||
canDisconnect(getData(), new ImmediateDataRequestMonitor<Boolean>() {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!isSuccess()) {
|
||||
request.setEnabled(false);
|
||||
}
|
||||
else {
|
||||
request.setEnabled(getData());;
|
||||
}
|
||||
request.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
request.setEnabled(false);
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -70,21 +90,201 @@ public class GdbDisconnectCommand implements IDisconnectHandler {
|
|||
|
||||
@Override
|
||||
public boolean execute(final IDebugCommandRequest request) {
|
||||
if (request.getElements().length != 1) {
|
||||
if (request.getElements().length == 0) {
|
||||
request.done();
|
||||
return false;
|
||||
}
|
||||
|
||||
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
|
||||
@Override public void doExecute() {
|
||||
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getContext(), IContainerDMContext.class);
|
||||
IProcesses procService = getProcessService();
|
||||
|
||||
if (procService != null) {
|
||||
procService.detachDebuggerFromProcess(containerDmc, new RequestMonitor(fExecutor, null));
|
||||
getContainerDMContexts(request.getElements(), new DataRequestMonitor<IContainerDMContext[]>(fExecutor, null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!isSuccess()) {
|
||||
request.setStatus(getStatus());
|
||||
request.done();
|
||||
}
|
||||
else {
|
||||
disconnect(getData(), new ImmediateRequestMonitor() {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!isSuccess()) {
|
||||
request.setStatus(getStatus());
|
||||
request.done();
|
||||
}
|
||||
else {
|
||||
waitForTermination(request);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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.IStatusHandler;
|
||||
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.model.IDisconnect;
|
||||
import org.eclipse.debug.core.model.ISourceLocator;
|
||||
|
@ -195,10 +196,10 @@ public class GdbLaunch extends DsfLaunch
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// ITerminate
|
||||
|
||||
static class TerminateRequest extends CRequest implements IDebugCommandRequest {
|
||||
static class LaunchCommandRequest extends CRequest implements IDebugCommandRequest {
|
||||
Object[] elements;
|
||||
|
||||
public TerminateRequest(Object[] objects) {
|
||||
public LaunchCommandRequest(Object[] objects) {
|
||||
elements = objects;
|
||||
}
|
||||
|
||||
|
@ -244,7 +245,7 @@ public class GdbLaunch extends DsfLaunch
|
|||
return;
|
||||
}
|
||||
|
||||
TerminateRequest req = new TerminateRequest(new Object[] {this});
|
||||
LaunchCommandRequest req = new LaunchCommandRequest(new Object[] {this});
|
||||
handler.execute(req);
|
||||
}
|
||||
|
||||
|
@ -265,7 +266,14 @@ public class GdbLaunch extends DsfLaunch
|
|||
|
||||
@Override
|
||||
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
|
||||
|
@ -362,6 +370,8 @@ public class GdbLaunch extends DsfLaunch
|
|||
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=377447.
|
||||
if (adapter.equals(ITerminateHandler.class))
|
||||
return getSession().getModelAdapter(adapter);
|
||||
if (adapter.equals(IDisconnectHandler.class))
|
||||
return getSession().getModelAdapter(adapter);
|
||||
|
||||
// Allow to call the connect handler when the launch is selected
|
||||
if (adapter.equals(IConnectHandler.class))
|
||||
|
|
|
@ -12,11 +12,15 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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.DsfExecutor;
|
||||
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.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
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.IExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
|
@ -58,7 +64,69 @@ import org.eclipse.debug.core.ILaunch;
|
|||
*
|
||||
* @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.
|
||||
|
@ -114,6 +182,8 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
|||
* initialization is done.
|
||||
*/
|
||||
private void doInitialize(RequestMonitor requestMonitor) {
|
||||
register(new String[]{ IMultiDetach.class.getName(), IMultiTerminate.class.getName() }, new Hashtable<String,String>());
|
||||
|
||||
fCommandControl = getServicesTracker().getService(IGDBControl.class);
|
||||
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
||||
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
||||
|
@ -607,5 +677,112 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
|||
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
|
||||
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-Vendor: %providerName
|
||||
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-Localization: plugin
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<version>2.5.0-SNAPSHOT</version>
|
||||
<version>2.6.0-SNAPSHOT</version>
|
||||
<artifactId>org.eclipse.cdt.dsf</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</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