From f6f53aa705278263250d165c032c74b93a89ca35 Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Fri, 27 Jan 2017 15:52:20 -0500 Subject: [PATCH] Bug 511243 - MI async mode shall not be activated for all cases when using GDB 7.12 This solution makes the following changes: * With GDB 7.12, use async mode as long as the Full GDB console is supported or if the launch is configured for Non stop mode * with GDB 7.12, don't always use MI to interrupt the service, use the CLI when the async mode is off Change-Id: I92c466e028b400f9054298739cd80efac18bd03a --- .../launching/FinalLaunchSequence_7_12.java | 53 ++++++++++------ .../dsf/gdb/service/GDBRunControl_7_12.java | 61 ++++++++++++------- .../GDBJtagDSFFinalLaunchSequence_7_12.java | 45 +++++++------- 3 files changed, 100 insertions(+), 59 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence_7_12.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence_7_12.java index 8d85ec38eb8..0d3407a74b6 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence_7_12.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence_7_12.java @@ -19,6 +19,7 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress; import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; @@ -36,6 +37,7 @@ public class FinalLaunchSequence_7_12 extends FinalLaunchSequence_7_7 { private IGDBControl fCommandControl; private CommandFactory fCommandFactory; private Map fAttributes; + private IGDBBackend fGdbBackEnd; public FinalLaunchSequence_7_12(DsfSession session, Map attributes, RequestMonitorWithProgress rm) { @@ -76,6 +78,8 @@ public class FinalLaunchSequence_7_12 extends FinalLaunchSequence_7_7 { DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), getSession().getId()); fCommandControl = tracker.getService(IGDBControl.class); + fGdbBackEnd = tracker.getService(IGDBBackend.class); + tracker.dispose(); if (fCommandControl == null) { @@ -90,20 +94,37 @@ public class FinalLaunchSequence_7_12 extends FinalLaunchSequence_7_7 { } + private boolean isNonStop() { + boolean isNonStop = CDebugUtils.getAttribute(fAttributes, + IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP, + LaunchUtils.getIsNonStopModeDefault()); + return isNonStop; + } + @Execute public void stepSetTargetAsync(RequestMonitor requestMonitor) { - // Use target async when interfacing with GDB 7.12 or higher - // this will allow us to use the new enhanced GDB Full CLI console + if (fCommandControl == null || fGdbBackEnd == null) { + requestMonitor.done(); + return; + } + + // Use target async for non-stop mode or when the + // Full GDB CLI console is being used. + // Otherwise Explicitly set target-async to off + boolean asyncOn = false; + if (isNonStop() || fGdbBackEnd.isFullGdbConsoleSupported()) { + asyncOn = true; + } + fCommandControl.queueCommand( - fCommandFactory.createMIGDBSetTargetAsync(fCommandControl.getContext(), true), - new DataRequestMonitor(getExecutor(), requestMonitor) { - @Override - protected void handleError() { - // We should only be calling this for GDB >= 7.12, - // but just in case, accept errors for older GDBs - requestMonitor.done(); - } - }); + fCommandFactory.createMIGDBSetTargetAsync(fCommandControl.getContext(), asyncOn), + new DataRequestMonitor(getExecutor(), requestMonitor) { + @Override + protected void handleError() { + // Accept errors for older GDBs + requestMonitor.done(); + } + }); } /** @@ -127,15 +148,13 @@ public class FinalLaunchSequence_7_12 extends FinalLaunchSequence_7_7 { @Override @Execute public void stepSetNonStop(final RequestMonitor requestMonitor) { - boolean isNonStop = CDebugUtils.getAttribute(fAttributes, - IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP, - LaunchUtils.getIsNonStopModeDefault()); - - if (isNonStop) { + if (isNonStop()) { // GDBs that don't support non-stop don't allow you to set it to false. // We really should set it to false when GDB supports it though. // Something to fix later. - // Note that disabling pagination is taken care of elsewhere + // Note: The base class is setting pagination to off, this is only necessary when + // using the Full GDB console (The basic console is started in MI mode and does not paginate). + // When the Full GDB console is used, pagination is set to off when GDB is started. fCommandControl.queueCommand( fCommandFactory.createMIGDBSetNonStop(fCommandControl.getContext(), true), new DataRequestMonitor(getExecutor(), requestMonitor)); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_12.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_12.java index dd1ebb7e585..b7238ab090f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_12.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_12.java @@ -43,6 +43,7 @@ import org.eclipse.core.runtime.jobs.Job; public class GDBRunControl_7_12 extends GDBRunControl_7_10 { private IMICommandControl fCommandControl; private CommandFactory fCommandFactory; + private IGDBBackend fGDBBackEnd; private Map fBpIdToReverseOpMap = new HashMap<>(); public GDBRunControl_7_12(DsfSession session) { @@ -61,6 +62,8 @@ public class GDBRunControl_7_12 extends GDBRunControl_7_10 { private void doInitialize(final RequestMonitor rm) { fCommandControl = getServicesTracker().getService(IMICommandControl.class); + fGDBBackEnd = getServicesTracker().getService(IGDBBackend.class); + fCommandFactory = fCommandControl.getCommandFactory(); register(new String[]{ GDBRunControl_7_12.class.getName() }, @@ -87,32 +90,48 @@ public class GDBRunControl_7_12 extends GDBRunControl_7_10 { } private void doSuspend(IExecutionDMContext context, final RequestMonitor rm) { - // Start the job before sending the interrupt command - // to make sure we don't miss the *stopped event - final MonitorSuspendJob monitorJob = new MonitorSuspendJob(0, rm); - fCommandControl.queueCommand(fCommandFactory.createMIExecInterrupt(context), - new ImmediateDataRequestMonitor() { - @Override - protected void handleSuccess() { - // Nothing to do in the case of success, the monitoring job - // will take care of completing the RM once it gets the - // *stopped event. - } + // We use the MI interrupt command when working in async mode. + // Since this run control service is specifically for all-stop mode, + // the only possibility to be running asynchronously is if the Full GDB console + // is being used. + if (fGDBBackEnd.isFullGdbConsoleSupported()) { + // Start the job before sending the interrupt command + // to make sure we don't miss the *stopped event + final MonitorSuspendJob monitorJob = new MonitorSuspendJob(0, rm); + fCommandControl.queueCommand(fCommandFactory.createMIExecInterrupt(context), + new ImmediateDataRequestMonitor() { + @Override + protected void handleSuccess() { + // Nothing to do in the case of success, the monitoring job + // will take care of completing the RM once it gets the + // *stopped event. + } - @Override - protected void handleFailure() { - // In case of failure, we must cancel the monitoring job - // and indicate the failure in the rm. - monitorJob.cleanAndCancel(); - rm.done(getStatus()); - } - }); + @Override + protected void handleFailure() { + // In case of failure, we must cancel the monitoring job + // and indicate the failure in the rm. + monitorJob.cleanAndCancel(); + rm.done(getStatus()); + } + }); + } else { + // Asynchronous mode is off + super.suspend(context, rm); + } } @Override public boolean isTargetAcceptingCommands() { - // Async mode is on when running with GDB 7.12 or higher - return true; + // We shall directly return true if the async mode is ON, + // Since this run control service is specifically for all-stop mode, + // The only possibility to be running asynchronously is if the Full GDB console + // is being used. + if (fGDBBackEnd.isFullGdbConsoleSupported()) { + return true; + } + + return super.isTargetAcceptingCommands(); } /** diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence_7_12.java b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence_7_12.java index f6b05b76138..d97d74d96c5 100644 --- a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence_7_12.java +++ b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence_7_12.java @@ -15,6 +15,7 @@ import java.util.Map; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress; +import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.mi.service.IMICommandControl; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; import org.eclipse.cdt.dsf.service.DsfServicesTracker; @@ -51,27 +52,29 @@ public class GDBJtagDSFFinalLaunchSequence_7_12 extends GDBJtagDSFFinalLaunchSeq @Execute public void stepSetTargetAsync(RequestMonitor rm) { - DsfServicesTracker tracker = new DsfServicesTracker(Activator.getBundleContext(), - getSession().getId()); - IMICommandControl commandControl = tracker.getService(IMICommandControl.class); - tracker.dispose(); + // Processing this request after sourcing the gdbinit file to make sure the user + // cannot change this behavior + DsfServicesTracker tracker = new DsfServicesTracker(Activator.getBundleContext(), + getSession().getId()); + IMICommandControl commandControl = tracker.getService(IMICommandControl.class); + IGDBBackend gdbBackEnd = tracker.getService(IGDBBackend.class); + tracker.dispose(); - if (commandControl != null) { - // Use target async when interfacing with GDB 7.12 or higher - // this will allow us to use the new enhanced GDB Full CLI console - commandControl.queueCommand( - commandControl.getCommandFactory().createMIGDBSetTargetAsync(commandControl.getContext(), true), - new DataRequestMonitor(getExecutor(), rm) { - @Override - protected void handleError() { - // We should only be calling this for GDB >= 7.12, - // but just in case, accept errors for older GDBs - rm.done(); - } - }); - } else { - // Should never happen but accept errors in this case - rm.done(); - } + if (commandControl != null && gdbBackEnd != null) { + // Use target async when interfacing with the full GDB console (i.e. minimum GDB version 7.12) + // otherwise explicitly set it to off. + commandControl.queueCommand( + commandControl.getCommandFactory().createMIGDBSetTargetAsync(commandControl.getContext(), gdbBackEnd.isFullGdbConsoleSupported()), + new DataRequestMonitor(getExecutor(), rm) { + @Override + protected void handleError() { + // Accept errors for older GDBs + rm.done(); + } + }); + } else { + // Should not happen + rm.done(); + } } }