Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'dsf-gdb')
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DsfTerminateCommand.java179
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java5
2 files changed, 159 insertions, 25 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DsfTerminateCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DsfTerminateCommand.java
index 4850e0781d1..904611a4b3b 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DsfTerminateCommand.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DsfTerminateCommand.java
@@ -12,6 +12,10 @@
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
@@ -21,18 +25,84 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IProcesses;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
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.Status;
+import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.commands.IDebugCommandRequest;
import org.eclipse.debug.core.commands.IEnabledStateRequest;
import org.eclipse.debug.core.commands.ITerminateHandler;
public class DsfTerminateCommand implements ITerminateHandler {
- private final DsfExecutor fExecutor;
+
+ private class WaitForTerminationJob extends Job implements SessionEndedListener {
+
+ final private IDebugCommandRequest fRequest;
+ final private String fSessionId;
+ final private Lock fLock = new ReentrantLock();
+ final private Condition fTerminated = fLock.newCondition();
+
+ public WaitForTerminationJob(String sessionId, IDebugCommandRequest request) {
+ super("Wait for termination job"); //$NON-NLS-1$
+ setUser(false);
+ setSystem(true);
+ fSessionId = sessionId;
+ fRequest = request;
+ DsfSession.addSessionEndedListener(WaitForTerminationJob.this);
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ // Wait for all processes associated with the launch
+ // and the shutdown sequence to be completed.
+ // The wait time is restricted to stop the job in case
+ // of termination error.
+ boolean result = !DsfSession.isSessionActive(fSessionId);
+ if (!result) {
+ fLock.lock();
+ try {
+ result = fTerminated.await(1, TimeUnit.MINUTES);
+ }
+ catch(InterruptedException e) {
+ }
+ finally {
+ fLock.unlock();
+ }
+ }
+ // Marking the request as cancelled will prevent the removal of
+ // the launch from the Debug view in case of "Terminate and Remove".
+ fRequest.setStatus(result ? Status.OK_STATUS : Status.CANCEL_STATUS);
+ fRequest.done();
+ DsfSession.removeSessionEndedListener(WaitForTerminationJob.this);
+ return Status.OK_STATUS;
+ }
+
+ @Override
+ public void sessionEnded(DsfSession session) {
+ if (fSessionId.equals(session.getId())) {
+ fLock.lock();
+ try {
+ fTerminated.signal();
+ }
+ finally {
+ fLock.unlock();
+ }
+ }
+ }
+ }
+
+ private final DsfSession fSession;
+ private final DsfExecutor fExecutor;
private final DsfServicesTracker fTracker;
public DsfTerminateCommand(DsfSession session) {
+ fSession = session;
fExecutor = session.getExecutor();
fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
}
@@ -41,17 +111,22 @@ public class DsfTerminateCommand implements ITerminateHandler {
fTracker.dispose();
}
- // Run control may not be avilable after a connection is terminated and shut down.
+ // Run control may not be available after a connection is terminated and shut down.
@Override
public void canExecute(final IEnabledStateRequest request) {
if (request.getElements().length != 1 ||
- !(request.getElements()[0] instanceof IDMVMContext) )
- {
+ !(request.getElements()[0] instanceof IDMVMContext ||
+ request.getElements()[0] instanceof GdbLaunch)) {
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
@@ -61,7 +136,72 @@ public class DsfTerminateCommand implements ITerminateHandler {
request.done();
return;
}
-
+
+ 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)) {
+ 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 {
+ 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 {
+ WaitForTerminationJob job = new WaitForTerminationJob(fSession.getId(), request);
+ job.schedule();
+ }
+ };
+ });
+ } else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+ return false;
+ }
+
+ private void canExecute(final IProcessDMContext processDmc, final IEnabledStateRequest request) {
try {
fExecutor.execute(
new DsfRunnable() {
@@ -90,23 +230,7 @@ public class DsfTerminateCommand implements ITerminateHandler {
}
}
- @Override
- public boolean execute(final IDebugCommandRequest request) {
- if (request.getElements().length != 1 ||
- !(request.getElements()[0] instanceof IDMVMContext)) {
- request.done();
- return false;
- }
-
- 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;
- }
-
+ private boolean execute(final IProcessDMContext processDmc, final IDebugCommandRequest request) {
try {
fExecutor.execute(new DsfRunnable() {
@Override
@@ -116,8 +240,14 @@ public class DsfTerminateCommand implements ITerminateHandler {
procService.terminate(processDmc, new ImmediateRequestMonitor() {
@Override
protected void handleCompleted() {
- request.setStatus(getStatus());
- request.done();
+ if (!isSuccess()) {
+ request.setStatus(getStatus());
+ request.done();
+ }
+ else {
+ WaitForTerminationJob job = new WaitForTerminationJob(fSession.getId(), request);
+ job.schedule();
+ }
};
});
} else {
@@ -130,5 +260,4 @@ public class DsfTerminateCommand implements ITerminateHandler {
}
return false;
}
-
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java
index 70d33d94110..c65e8f9404e 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java
@@ -56,6 +56,7 @@ import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.commands.ITerminateHandler;
import org.eclipse.debug.core.model.IDisconnect;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.ISourceLocator;
@@ -300,6 +301,10 @@ public class GdbLaunch extends DsfLaunch
@SuppressWarnings("rawtypes")
@Override
public Object getAdapter(Class adapter) {
+ // We replace the standard terminate handler by DsfTerminateHandler
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=377447.
+ if (adapter.equals(ITerminateHandler.class))
+ return getSession().getModelAdapter(adapter);
// Must force adapters to be loaded.
Platform.getAdapterManager().loadAdapter(this, adapter.getName());
return super.getAdapter(adapter);

Back to the top