mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 422586 - Terminate session if remote connection is lost
Change-Id: I78e8ccd60c3f49e5c5ef87c5564cab8849281b8d Signed-off-by: Marc Khouzam <marc.khouzam@ericsson.com> Reviewed-on: https://git.eclipse.org/r/20286 Tested-by: Hudson CI Reviewed-by: Mikhail Khodjaiants <mikhailkhod@googlemail.com> IP-Clean: Mikhail Khodjaiants <mikhailkhod@googlemail.com> Tested-by: Mikhail Khodjaiants <mikhailkhod@googlemail.com>
This commit is contained in:
parent
78fc903d16
commit
1de1915f89
1 changed files with 167 additions and 3 deletions
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2012 Wind River Systems and others.
|
||||
* Copyright (c) 2006, 2014 Wind River Systems 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
|
||||
|
@ -15,6 +15,7 @@
|
|||
* Marc Khouzam (Ericsson) - Pass errorStream to startCommandProcessing() (Bug 350837)
|
||||
* Mikhail Khodjaiants (Mentor Graphics) - Terminate should cancel the initialization sequence
|
||||
* if it is still running (bug 373845)
|
||||
* Marc Khouzam (Ericsson) - Terminate the session if we lose the connection to the remote target (bug 422586)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.service.command;
|
||||
|
||||
|
@ -44,6 +45,7 @@ import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
|||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandToken;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
|
@ -66,7 +68,15 @@ import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.IEventProcessor;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIRunControlEventProcessor;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIConsoleStreamOutput;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MILogStreamOutput;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIOOBRecord;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
@ -127,12 +137,61 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An event processor that handles some GDB life cycle events.
|
||||
* Currently, it detects a lost connection with the remote.
|
||||
*/
|
||||
private class ControlEventProcessor implements IEventProcessor {
|
||||
|
||||
public ControlEventProcessor() {
|
||||
addCommandListener(this);
|
||||
addEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
removeEventListener(this);
|
||||
removeCommandListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventReceived(Object output) {
|
||||
if (output instanceof MIOutput) {
|
||||
verifyConnectionLost((MIOutput)output);
|
||||
} else {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commandDone(ICommandToken token, ICommandResult cmdResult) {
|
||||
if (cmdResult instanceof MIInfo) {
|
||||
verifyConnectionLost(((MIInfo)cmdResult).getMIOutput());
|
||||
} else {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commandQueued(ICommandToken token) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commandSent(ICommandToken token) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commandRemoved(ICommandToken token) {
|
||||
}
|
||||
}
|
||||
|
||||
private GDBControlDMContext fControlDmc;
|
||||
|
||||
private IGDBBackend fMIBackend;
|
||||
|
||||
private IEventProcessor fMIEventProcessor;
|
||||
private IEventProcessor fCLICommandProcessor;
|
||||
private IEventProcessor fControlEventProcessor;
|
||||
private AbstractCLIProcess fCLIProcess;
|
||||
|
||||
private GdbCommandTimeoutManager fCommandTimeoutManager;
|
||||
|
@ -325,7 +384,6 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
/**
|
||||
* @since 4.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void completeInitialization(final RequestMonitor rm) {
|
||||
// We take the attributes from the launchConfiguration
|
||||
|
@ -462,13 +520,15 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
|
||||
fCLICommandProcessor = createCLIEventProcessor(GDBControl.this, fControlDmc);
|
||||
fMIEventProcessor = createMIRunControlEventProcessor(GDBControl.this, fControlDmc);
|
||||
fControlEventProcessor = createControlEventProcessor();
|
||||
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdown(RequestMonitor requestMonitor) {
|
||||
fCLICommandProcessor.dispose();
|
||||
fControlEventProcessor.dispose();
|
||||
fCLICommandProcessor.dispose();
|
||||
fMIEventProcessor.dispose();
|
||||
fCLIProcess.dispose();
|
||||
|
||||
|
@ -594,6 +654,11 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
return new MIRunControlEventProcessor(connection, controlDmc);
|
||||
}
|
||||
|
||||
/** @since 4.3 */
|
||||
protected IEventProcessor createControlEventProcessor() {
|
||||
return new ControlEventProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
|
@ -654,6 +719,105 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse output from GDB to determine if the connection to the remote was lost.
|
||||
*
|
||||
* @param output The output received from GDB that must be parsed
|
||||
* to determine if the connection to the remote was lost.
|
||||
*
|
||||
* @return True if the connection was lost, false otherwise.
|
||||
* @since 4.3
|
||||
*/
|
||||
protected boolean verifyConnectionLost(MIOutput output) {
|
||||
boolean connectionLost = false;
|
||||
String reason = null;
|
||||
|
||||
// Check if any command has a result that indicates a lost connection.
|
||||
// This can happen as a normal command result, or as an out-of-band event.
|
||||
// The out-of-band case can happen when GDB sends another response to
|
||||
// a previous command. This case can happen, for example, in all-stop
|
||||
// when sending an -exec-continue and then killing gdbserver while connected
|
||||
// to a process; in that case a second result to -exec-continue will be sent
|
||||
// and will indicate the remote connection is closed.
|
||||
MIResultRecord rr = output.getMIResultRecord();
|
||||
if (rr != null) {
|
||||
String state = rr.getResultClass();
|
||||
if ("error".equals(state)) { //$NON-NLS-1$
|
||||
MIResult[] results = rr.getMIResults();
|
||||
for (MIResult result : results) {
|
||||
String var = result.getVariable();
|
||||
if (var.equals("msg")) { //$NON-NLS-1$
|
||||
MIValue value = result.getMIValue();
|
||||
if (value instanceof MIConst) {
|
||||
String str = ((MIConst)value).getCString();
|
||||
if (str != null && str.startsWith("Remote connection closed")) { //$NON-NLS-1$
|
||||
connectionLost = true;
|
||||
reason = str;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Only check for out-of-band records when there is no result record.
|
||||
// This is because OOBRecords that precede a result are included in the
|
||||
// result output even though they have already been processed. To avoid
|
||||
// processing them a second time, we only handle them when not dealing
|
||||
// with a result record.
|
||||
for (MIOOBRecord oobr : output.getMIOOBRecords()) {
|
||||
if (oobr instanceof MIConsoleStreamOutput) {
|
||||
MIConsoleStreamOutput out = (MIConsoleStreamOutput) oobr;
|
||||
String str = out.getString();
|
||||
if (str != null && str.startsWith("Ending remote debugging")) { //$NON-NLS-1$
|
||||
// This happens if the user types 'disconnect' in the console
|
||||
connectionLost = true;
|
||||
reason = str;
|
||||
break;
|
||||
|
||||
// Note that this will not trigger in the case where a
|
||||
// -target-disconnect is used. This is a case that CDT handles
|
||||
// explicitly as it is an MI command; we shouldn't have to catch it here.
|
||||
// In fact, catching it here and terminating the session would break
|
||||
// the workaround for GDB 7.2 handled by GDBProcesses_7_2.needFixForGDB72Bug352998()
|
||||
}
|
||||
} else if (oobr instanceof MILogStreamOutput) {
|
||||
MILogStreamOutput out = (MILogStreamOutput) oobr;
|
||||
String str = out.getString().trim();
|
||||
if (str != null && str.startsWith("Remote connection closed")) { //$NON-NLS-1$
|
||||
// This happens if gdbserver is killed or dies
|
||||
connectionLost = true;
|
||||
reason = str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (connectionLost) {
|
||||
connectionLost(reason);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the loss of the connection to the remote.
|
||||
* The default implementation terminates the debug session.
|
||||
*
|
||||
* @param reason A string indicating as much as possible why the connection was lost. Can be null.
|
||||
* @since 4.3
|
||||
*/
|
||||
protected void connectionLost(String reason) {
|
||||
terminate(new ImmediateRequestMonitor() {
|
||||
@Override
|
||||
protected void handleErrorOrWarning() {
|
||||
GdbPlugin.getDefault().getLog().log(getStatus());
|
||||
super.handleErrorOrWarning();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue