1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

[234467] When terminating a DSF-GDB launch, interrupt the inferior if it is running. Without that, the inferior is left running even though GDB is killed.

This commit is contained in:
Marc Khouzam 2009-05-20 13:45:58 +00:00
parent e1218f9cbd
commit d8e9fa0782
3 changed files with 94 additions and 16 deletions

View file

@ -0,0 +1,60 @@
/*******************************************************************************
* Copyright (c) 2009 Nokia Corporation.
* 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:
* Nokia - initial version. May 5, 2009
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service.command;
import java.io.IOException;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
import org.eclipse.cdt.dsf.mi.service.command.MIBackendCLIProcess;
import org.eclipse.cdt.dsf.service.DsfSession;
/**
* @author LWang
* @since 2.0
*
*/
public class GDBBackendCLIProcess extends MIBackendCLIProcess {
/**
* @param commandControl
* @param backend
* @throws IOException
*/
public GDBBackendCLIProcess(ICommandControlService commandControl,
IMIBackend backend) throws IOException {
super(commandControl, backend);
assert(commandControl instanceof IGDBControl);
}
@Override
public void destroy() {
try {
// This is called when user terminate the "launch" or "gdb" process
// in Debug View. We need to kill inferior too. Fix bug
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=234467
//
getSession().getExecutor().execute(new DsfRunnable() { public void run() {
if (!DsfSession.isSessionActive(getSession().getId())) return;
if (isDisposed()) return;
((IGDBControl)getCommandControlService()).terminate(
new RequestMonitor(getSession().getExecutor(), null));
}});
} catch (RejectedExecutionException e) {
// Session disposed.
}
}
}

View file

@ -41,10 +41,10 @@ import org.eclipse.cdt.dsf.mi.service.MIProcesses.ContainerStartedDMEvent;
import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl;
import org.eclipse.cdt.dsf.mi.service.command.CLIEventProcessor;
import org.eclipse.cdt.dsf.mi.service.command.MIBackendCLIProcess;
import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
import org.eclipse.cdt.dsf.mi.service.command.MIRunControlEventProcessor;
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess.State;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert;
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
@ -177,10 +177,18 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
}
public void terminate(final RequestMonitor rm) {
// To fix bug 234467:
// Interrupt GDB in case the inferior is running.
// That way, the inferior will also be killed when we exit GDB.
//
if (fInferiorProcess.getState() == State.RUNNING) {
fMIBackend.interrupt();
}
// Schedule a runnable to be executed 2 seconds from now.
// If we don't get a response to the quit command, this
// runnable will kill the task.
final Future<?> quitTimeoutFuture = getExecutor().schedule(
final Future<?> forceQuitTask = getExecutor().schedule(
new DsfRunnable() {
public void run() {
fMIBackend.destroy();
@ -199,13 +207,14 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
public void handleCompleted() {
// Cancel the time out runnable (if it hasn't run yet).
if (quitTimeoutFuture.cancel(false)) {
if (!isSuccess()) {
fMIBackend.destroy();
}
if (isSuccess()) {
// Cancel the time out runnable (if it hasn't run yet).
forceQuitTask.cancel(false);
rm.done();
}
// else: the forceQuitTask has or will handle it.
// It is good to wait for the forceQuitTask to trigger
// to leave enough time for the interrupt() to complete.
}
}
);
@ -463,7 +472,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
@Override
public void initialize(final RequestMonitor requestMonitor) {
try {
fCLIProcess = new MIBackendCLIProcess(GDBControl.this, fMIBackend);
fCLIProcess = new GDBBackendCLIProcess(GDBControl.this, fMIBackend);
}
catch(IOException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Failed to create CLI Process", e)); //$NON-NLS-1$

View file

@ -43,10 +43,10 @@ import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl;
import org.eclipse.cdt.dsf.mi.service.command.CLIEventProcessor_7_0;
import org.eclipse.cdt.dsf.mi.service.command.MIBackendCLIProcess;
import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
import org.eclipse.cdt.dsf.mi.service.command.MIRunControlEventProcessor_7_0;
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess.State;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert;
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
@ -178,10 +178,18 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
}
public void terminate(final RequestMonitor rm) {
// To fix bug 234467:
// Interrupt GDB in case the inferior is running.
// That way, the inferior will also be killed when we exit GDB.
//
if (fInferiorProcess.getState() == State.RUNNING) {
fMIBackend.interrupt();
}
// Schedule a runnable to be executed 2 seconds from now.
// If we don't get a response to the quit command, this
// runnable will kill the task.
final Future<?> quitTimeoutFuture = getExecutor().schedule(
final Future<?> forceQuitTask = getExecutor().schedule(
new DsfRunnable() {
public void run() {
fMIBackend.destroy();
@ -200,13 +208,14 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
public void handleCompleted() {
// Cancel the time out runnable (if it hasn't run yet).
if (quitTimeoutFuture.cancel(false)) {
if (!isSuccess()) {
fMIBackend.destroy();
}
if (isSuccess()) {
// Cancel the time out runnable (if it hasn't run yet).
forceQuitTask.cancel(false);
rm.done();
}
// else: the forceQuitTask has or will handle it.
// It is good to wait for the forceQuitTask to trigger
// to leave enough time for the interrupt() to complete.
}
}
);
@ -601,7 +610,7 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
@Override
public void initialize(final RequestMonitor requestMonitor) {
try {
fCLIProcess = new MIBackendCLIProcess(GDBControl_7_0.this, fMIBackend);
fCLIProcess = new GDBBackendCLIProcess(GDBControl_7_0.this, fMIBackend);
}
catch(IOException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Failed to create CLI Process", e)); //$NON-NLS-1$