From 2578bcf7c474c3782f7a548d1a327f7d73bfc91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Svensson?= Date: Wed, 13 Apr 2022 21:26:49 +0200 Subject: [PATCH] Bug 579687: Reduce concurrent commands to 1 for GDB 9/10/11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the fault in GDB is triggered when there is more than one MI command sent before the response for the prior one is processed, limit the number of concurrent commands to 1 for the affected versions. Contributed by STMicroelectronics Change-Id: I8a2baa8e641e9bfeb0627ad868a5b41c3f94db14 Signed-off-by: Torbjörn Svensson --- .../META-INF/MANIFEST.MF | 2 +- .../mi/service/command/AbstractMIControl.java | 63 +++++++++++++++---- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF index 71278b2e40f..e903cf5bff1 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb;singleton:=true -Bundle-Version: 6.5.100.qualifier +Bundle-Version: 6.5.101.qualifier Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.GdbPlugin Bundle-Localization: plugin Require-Bundle: org.eclipse.core.runtime, diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java index 14a0b056caf..f4c485a12f2 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java @@ -48,6 +48,7 @@ import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.ICachingService; +import org.eclipse.cdt.dsf.debug.service.IDsfDebugServicesFactory; import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.debug.service.command.ICommand; @@ -59,6 +60,9 @@ import org.eclipse.cdt.dsf.debug.service.command.IEventListener; import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants; import org.eclipse.cdt.dsf.gdb.internal.GdbDebugOptions; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; +import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils; +import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory; import org.eclipse.cdt.dsf.mi.service.IMICommandControl; import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; @@ -78,9 +82,11 @@ import org.eclipse.cdt.dsf.service.AbstractDsfService; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.debug.core.ILaunch; import org.eclipse.osgi.util.NLS; /** @@ -101,6 +107,7 @@ public abstract class AbstractMIControl extends AbstractDsfService implements IM private TxThread fTxThread; private RxThread fRxThread; private ErrorThread fErrorThread; + private final int fNumberOfConcurrentCommands; // MI did not always support the --thread/--frame options // This boolean is used to know if we should use -thread-select and -stack-select-frame instead @@ -190,6 +197,12 @@ public abstract class AbstractMIControl extends AbstractDsfService implements IM fUseThreadAndFrameOptions = true; } fCommandFactory = factory; + + if (isConcurrentCommandsSupported()) { + fNumberOfConcurrentCommands = NUMBER_CONCURRENT_COMMANDS; + } else { + fNumberOfConcurrentCommands = 1; + } } /** @@ -381,23 +394,21 @@ public abstract class AbstractMIControl extends AbstractDsfService implements IM fCommandQueue.add(handle); processCommandQueued(handle); - if (fRxCommands.size() < NUMBER_CONCURRENT_COMMANDS) { - // In a separate dispatch cycle. This allows command listeners - // to respond to the command queued event. - getExecutor().execute(new DsfRunnable() { - @Override - public void run() { - processNextQueuedCommand(); - } - }); - } + // In a separate dispatch cycle. This allows command listeners + // to respond to the command queued event. + getExecutor().execute(new DsfRunnable() { + @Override + public void run() { + processNextQueuedCommand(); + } + }); } return handle; } private void processNextQueuedCommand() { - if (!fCommandQueue.isEmpty()) { + if (!fCommandQueue.isEmpty() && fRxCommands.size() < fNumberOfConcurrentCommands) { final CommandHandle handle = fCommandQueue.remove(0); if (handle != null) { processCommandSent(handle); @@ -1264,4 +1275,34 @@ public abstract class AbstractMIControl extends AbstractDsfService implements IM getSession().dispatchEvent(new RefreshAllDMEvent(getContext()), getProperties()); rm.done(); } + + private String getGdbVersion() { + ILaunch launch = (ILaunch) getSession().getModelAdapter(ILaunch.class); + if (launch instanceof GdbLaunch) { + IDsfDebugServicesFactory servicesFactory = ((GdbLaunch) launch).getServiceFactory(); + if (servicesFactory instanceof GdbDebugServicesFactory) { + return ((GdbDebugServicesFactory) servicesFactory).getVersion(); + } + } + return null; + } + + private boolean isConcurrentCommandsSupported() { + if (Platform.getOS().equals(Platform.OS_LINUX)) { + // Check if GDB client version is in range [8.3.50, 12.1) + // See https://sourceware.org/bugzilla/show_bug.cgi?id=28711 for details + + String version = getGdbVersion(); + if (version == null || version.isEmpty()) { + // Unknown version, assume it's affected + return false; + } + if (LaunchUtils.compareVersions(version, "8.3.50") >= 0 //$NON-NLS-1$ + && LaunchUtils.compareVersions(version, "12.1") < 0) { //$NON-NLS-1$ + // Within problematic version range + return false; + } + } + return true; + } }