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:
parent
e1218f9cbd
commit
d8e9fa0782
3 changed files with 94 additions and 16 deletions
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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$
|
||||
|
|
|
@ -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$
|
||||
|
|
Loading…
Add table
Reference in a new issue