Bug 516371: Enable GDB target async support for Windows remote debugging

Traditionally CDT used sync debug support all the time. However there
are cases where using target async is better because of GDB missing
interrupt.

This patch expands the cases that use target async to be all
remote targets when using Windows host. That is in addition to
cases when the full GDB Console is supported (new-ui).

Signed-off-by: Muhammad Bilal <hafizbilal100@gmail.com>
Change-Id: I1309d20319a24e4f23543d4ed22735044fd5b811
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/.api_filters b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/.api_filters
new file mode 100644
index 0000000..989277b
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/.api_filters
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.cdt.dsf.gdb" version="2">
+    <resource path="src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java" type="org.eclipse.cdt.dsf.gdb.service.IGDBBackend">
+        <filter comment="CDT allows new default methods that are unlikely to conflict with existing methods, therefore major version bump is unneeded." id="404000815">
+            <message_arguments>
+                <message_argument value="org.eclipse.cdt.dsf.gdb.service.IGDBBackend"/>
+                <message_argument value="useTargetAsync()"/>
+            </message_arguments>
+        </filter>
+    </resource>
+</component>
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 b96d897..4f19969 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-Name: %pluginName
 Bundle-Vendor: %providerName
 Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb;singleton:=true
-Bundle-Version: 6.1.0.qualifier
+Bundle-Version: 6.2.0.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/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 3cd02b1..6e53e68 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
@@ -107,11 +107,11 @@
 			return;
 		}
 
-		// Use target async for non-stop mode or when the
-		// Full GDB CLI console is being used.
+		// Use target async for non-stop mode or when
+		// it is specifically enabled by backend in all-stop mode
 		// Otherwise Explicitly set target-async to off
 		boolean asyncOn = false;
-		if (isNonStop() || fGdbBackEnd.isFullGdbConsoleSupported()) {
+		if (isNonStop() || fGdbBackEnd.useTargetAsync()) {
 			asyncOn = true;
 		}
 
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend_7_12.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend_7_12.java
index a1255e2..5c2b571 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend_7_12.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend_7_12.java
@@ -63,6 +63,17 @@
 				&& !fPtyFailure;
 	}
 
+	/**
+	 * @since 6.2
+	 */
+	@Override
+	public boolean useTargetAsync() {
+		// Enable target asynchronously if there is Full GDB console as Full GDB Console requires async target or
+		// If Windows remote debugging as remote debugging in GDB has lots of issues with handling Ctrl-C (See Bug 516371)
+		return isFullGdbConsoleSupported()
+				|| (Platform.getOS().equals(Platform.OS_WIN32) && getSessionType() == SessionType.REMOTE);
+	}
+
 	protected void createPty() {
 		if (!isFullGdbConsoleSupported()) {
 			return;
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_12.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_12.java
index ce585b0..c69c86d 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_12.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_12.java
@@ -47,12 +47,12 @@
 	@Override
 	public void terminate(IThreadDMContext thread, RequestMonitor rm) {
 		IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
-		if (!backend.isFullGdbConsoleSupported()) {
+		if (!backend.useTargetAsync()) {
 			super.terminate(thread, rm);
 			return;
 		}
 
-		// If we are running the full GDB console, there is a bug with GDB 7.12
+		// If we are running the target-async support, there is a bug with GDB 7.12
 		// where after we terminate the process, the GDB prompt does not come
 		// back in the console.  As a workaround, we first interrupt the process
 		// to get the prompt back, and only then kill the process.
@@ -93,12 +93,12 @@
 		}
 
 		IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
-		if (!backend.isFullGdbConsoleSupported()) {
+		if (!backend.useTargetAsync()) {
 			super.detachDebuggerFromProcess(dmc, rm);
 			return;
 		}
 
-		// If we are running the full GDB console, there is a bug with GDB 7.12
+		// If we are running the target-async support, there is a bug with GDB 7.12
 		// where after we detach the process, the GDB prompt does not come
 		// back in the console.  As a workaround, we first interrupt the process
 		// to get the prompt back, and only then detach the process.
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 b578bb9..ac548b6 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
@@ -92,10 +92,7 @@
 
 	private void doSuspend(IExecutionDMContext context, final RequestMonitor rm) {
 		// 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()) {
+		if (fGDBBackEnd.useTargetAsync()) {
 			// 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);
@@ -124,11 +121,8 @@
 
 	@Override
 	public boolean isTargetAcceptingCommands() {
-		// 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()) {
+		// We shall directly return true if the async mode is ON.
+		if (fGDBBackEnd.useTargetAsync()) {
 			return true;
 		}
 
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java
index e283b62..96d39df 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java
@@ -171,6 +171,14 @@
 	}
 
 	/**
+	 * @return True if CDT should use target async in all-stop mode.
+	 * @since 6.2
+	 */
+	default boolean useTargetAsync() {
+		return false;
+	}
+
+	/**
 	 * @return The real GDB process that was started for the debug session
 	 * @since 5.2
 	 */
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 07906b6..9ba9aab 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
@@ -64,17 +64,15 @@
 		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<MIInfo>(getExecutor(), rm) {
-								@Override
-								protected void handleError() {
-									// Accept errors for older GDBs
-									rm.done();
-								}
-							});
+			commandControl.queueCommand(commandControl.getCommandFactory()
+					.createMIGDBSetTargetAsync(commandControl.getContext(), gdbBackEnd.useTargetAsync()),
+					new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
+						@Override
+						protected void handleError() {
+							// Accept errors for older GDBs
+							rm.done();
+						}
+					});
 		} else {
 			// Should not happen
 			rm.done();