Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debug/org.eclipse.cdt.debug.application.product/debug.product3
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF5
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml7
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java6
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.java4
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.properties4
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsolePageParticipant.java22
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsole.java80
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsoleManager.java229
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsolePage.java163
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/TracingConsole.java2
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBProcess.java64
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java11
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java77
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend_7_12.java191
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java7
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java17
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java1
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties3
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendCLIProcess.java7
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendProcessWithoutIO.java44
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java39
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBBackendProcessWithoutIO.java22
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java26
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/extensions/GDBBackend_HEAD.java6
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractCLIProcess.java101
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIBackendCLIProcess.java5
-rw-r--r--releng/org.eclipse.cdt.target/cdt.target3
28 files changed, 1072 insertions, 77 deletions
diff --git a/debug/org.eclipse.cdt.debug.application.product/debug.product b/debug/org.eclipse.cdt.debug.application.product/debug.product
index fe8724b97ea..cab34794d25 100644
--- a/debug/org.eclipse.cdt.debug.application.product/debug.product
+++ b/debug/org.eclipse.cdt.debug.application.product/debug.product
@@ -347,6 +347,9 @@ Java and all Java-based trademarks are trademarks of Oracle Corporation in the U
<plugin id="org.eclipse.swt.win32.win32.x86_64" fragment="true"/>
<plugin id="org.eclipse.team.core"/>
<plugin id="org.eclipse.team.ui"/>
+ <plugin id="org.eclipse.tm.terminal.control"/>
+ <plugin id="org.eclipse.tm.terminal.view.core"/>
+ <plugin id="org.eclipse.tm.terminal.view.ui"/>
<plugin id="org.eclipse.text"/>
<plugin id="org.eclipse.tools.templates.core"/>
<plugin id="org.eclipse.tools.templates.ui"/>
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
index c60bc3436ba..35449285435 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
@@ -25,7 +25,10 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.core.filesystem;bundle-version="1.2.0",
org.eclipse.cdt.launch;bundle-version="6.1.0",
org.eclipse.debug.core,
- org.eclipse.core.resources
+ org.eclipse.core.resources,
+ org.eclipse.tm.terminal.control;bundle-version="4.0.0",
+ org.eclipse.tm.terminal.view.core;bundle-version="4.0.0",
+ org.eclipse.tm.terminal.view.ui;bundle-version="4.1.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.eclipse.cdt.dsf.gdb.internal.ui;x-friends:="org.eclipse.cdt.docker.launcher",
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
index 2afc82dc711..7d0180058cb 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
@@ -515,9 +515,10 @@
class="org.eclipse.cdt.dsf.gdb.internal.ui.console.ConsolePageParticipant"
id="org.eclipse.cdt.dsf.gdb.ui.dsfGdbConsolePageParticipant">
<enablement>
- <instanceof
- value="org.eclipse.ui.console.IOConsole">
- </instanceof>
+ <or>
+ <instanceof value="org.eclipse.ui.console.IOConsole"/>
+ <instanceof value="org.eclipse.cdt.dsf.gdb.internal.ui.console.GdbCliConsole"/>
+ </or>
</enablement>
</consolePageParticipant>
</extension>
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java
index 1bea161ab4a..5468fa6045c 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java
@@ -12,6 +12,7 @@
package org.eclipse.cdt.dsf.gdb.internal.ui;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.internal.ui.console.GdbCliConsoleManager;
import org.eclipse.cdt.dsf.gdb.internal.ui.console.TracingConsoleManager;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
@@ -46,6 +47,7 @@ public class GdbUIPlugin extends AbstractUIPlugin {
private static BundleContext fgBundleContext;
private static TracingConsoleManager fTracingConsoleManager;
+ private static GdbCliConsoleManager fGdbConsoleManager;
private static IPreferenceStore fCorePreferenceStore;
@@ -67,6 +69,9 @@ public class GdbUIPlugin extends AbstractUIPlugin {
fTracingConsoleManager = new TracingConsoleManager();
fTracingConsoleManager.startup();
+
+ fGdbConsoleManager = new GdbCliConsoleManager();
+ fGdbConsoleManager.startup();
}
/*
@@ -76,6 +81,7 @@ public class GdbUIPlugin extends AbstractUIPlugin {
@Override
public void stop(BundleContext context) throws Exception {
fTracingConsoleManager.shutdown();
+ fGdbConsoleManager.shutdown();
disposeAdapterSets();
plugin = null;
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.java
index 059e39b039b..d9e294d7130 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010 Marc-Andre Laperle and others.
+ * Copyright (c) 2010, 2016 Marc-Andre Laperle 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
@@ -17,7 +17,7 @@ import org.eclipse.osgi.util.NLS;
*/
public class ConsoleMessages extends NLS {
public static String ConsoleMessages_trace_console_name;
- public static String ConsoleMessages_trace_console_terminated;
+ public static String ConsoleMessages_console_terminated;
public static String ConsoleMessages_save_action_tooltip;
public static String ConsoleMessages_save_confirm_overwrite_title;
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.properties
index 5aafada28d0..7d098d352f9 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.properties
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsoleMessages.properties
@@ -1,5 +1,5 @@
##########################################################################
-# Copyright (c) 2010 Marc-Andre Laperle and others.
+# Copyright (c) 2010, 2016 Marc-Andre Laperle 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
@@ -10,7 +10,7 @@
##########################################################################
ConsoleMessages_trace_console_name=gdb traces
-ConsoleMessages_trace_console_terminated=<terminated>
+ConsoleMessages_console_terminated=<terminated>
ConsoleMessages_save_action_tooltip=Save console content
ConsoleMessages_save_confirm_overwrite_title=Confirm overwrite
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsolePageParticipant.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsolePageParticipant.java
index a8ff90be11a..73b3dfa60db 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsolePageParticipant.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/ConsolePageParticipant.java
@@ -57,7 +57,8 @@ public class ConsolePageParticipant implements IConsolePageParticipant, IDebugCo
DebugUITools.getDebugContextManager().getContextService(fPage.getSite().getWorkbenchWindow()).addDebugContextListener(this);
}
- if(console instanceof TracingConsole || isConsoleGdbCli(console)) {
+ if (console instanceof TracingConsole ||
+ (isConsoleGdbCli(console) && console instanceof TextConsole)) {
TextConsole textConsole = (TextConsole) console;
// Add the save console action
@@ -81,6 +82,9 @@ public class ConsolePageParticipant implements IConsolePageParticipant, IDebugCo
org.eclipse.debug.ui.console.IConsole debugConsole = (org.eclipse.debug.ui.console.IConsole)console;
return (debugConsole.getProcess() instanceof GDBProcess);
}
+ if (console instanceof GdbCliConsole) {
+ return true;
+ }
return false;
}
@@ -152,6 +156,10 @@ public class ConsolePageParticipant implements IConsolePageParticipant, IDebugCo
return null;
}
+ if (context instanceof GDBProcess) {
+ return (GDBProcess)context;
+ }
+
if (context != null) {
// Look for the process that this context refers to, so we can select its console
IDMContext dmc = context.getAdapter(IDMContext.class);
@@ -187,12 +195,18 @@ public class ConsolePageParticipant implements IConsolePageParticipant, IDebugCo
return null;
}
- /* (non-Javadoc)
- * @see org.eclipse.debug.internal.ui.contexts.provisional.IDebugContextListener#contextEvent(org.eclipse.debug.internal.ui.contexts.provisional.DebugContextEvent)
- */
@Override
public void debugContextChanged(DebugContextEvent event) {
if ((event.getFlags() & DebugContextEvent.ACTIVATED) > 0) {
+ if (fView != null && fConsole instanceof GdbCliConsole) {
+ IProcess currentProcess = getCurrentProcess();
+ if (currentProcess instanceof GDBProcess &&
+ ((GdbCliConsole)fConsole).getLaunch().equals(currentProcess.getLaunch())) {
+ fView.display(fConsole);
+ }
+ return;
+ }
+
IProcess consoleProcess = getConsoleProcess();
if (fView != null && consoleProcess != null && consoleProcess.equals(getCurrentProcess())) {
fView.display(fConsole);
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsole.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsole.java
new file mode 100644
index 00000000000..68f1e820803
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsole.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.console;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.console.AbstractConsole;
+import org.eclipse.ui.console.IConsoleView;
+import org.eclipse.ui.part.IPageBookViewPage;
+
+/**
+ * A GDB CLI console.
+ * This console actually runs a GDB process in CLI mode to achieve a
+ * full-featured CLI interface. This is only supported with GDB >= 7.12
+ * and if IGDBBackend.isFullGdbConsoleSupported() returns true.
+ */
+public class GdbCliConsole extends AbstractConsole {
+ private final ILaunch fLaunch;
+ private String fLabel;
+
+ public GdbCliConsole(ILaunch launch, String label) {
+ super(label, null);
+ fLaunch = launch;
+ fLabel = label;
+
+ resetName();
+ }
+
+ public ILaunch getLaunch() { return fLaunch; }
+
+ public void resetName() {
+ String newName = computeName();
+ String name = getName();
+ if (!name.equals(newName)) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(() -> setName(newName));
+ }
+ }
+
+ protected String computeName() {
+ String label = fLabel;
+
+ ILaunchConfiguration config = fLaunch.getLaunchConfiguration();
+ if (config != null && !DebugUITools.isPrivate(config)) {
+ String type = null;
+ try {
+ type = config.getType().getName();
+ } catch (CoreException e) {
+ }
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(config.getName());
+ if (type != null) {
+ buffer.append(" ["); //$NON-NLS-1$
+ buffer.append(type);
+ buffer.append("] "); //$NON-NLS-1$
+ }
+ buffer.append(label);
+ label = buffer.toString();
+ }
+
+ if (fLaunch.isTerminated()) {
+ return ConsoleMessages.ConsoleMessages_console_terminated + label;
+ }
+
+ return label;
+ }
+
+ @Override
+ public IPageBookViewPage createPage(IConsoleView view) {
+ view.setFocus();
+ return new GdbCliConsolePage(this);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsoleManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsoleManager.java
new file mode 100644
index 00000000000..b61a7b194e4
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsoleManager.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 Ericsson 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ericsson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.console;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchesListener2;
+import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.IConsoleManager;
+
+/**
+ * A console manager for GDB sessions which adds and removes
+ * gdb cli consoles.
+ *
+ * There is a single such console per debug session.
+ * This console interacts directly with the GDB process using
+ * the standard GDB CLI interface.
+ * These consoles cannot be enabled/disabled by the user.
+ * However, they are only supported by GDB >= 7.12;
+ * to handle this limitation, the console manager will use the DSF Backend
+ * service to establish if it should start a gdb cli console or not.
+ */
+public class GdbCliConsoleManager implements ILaunchesListener2 {
+
+ /**
+ * Start the tracing console. We don't do this in a constructor, because
+ * we need to use <code>this</code>.
+ */
+ public void startup() {
+ // Listen to launch events
+ DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
+ }
+
+ public void shutdown() {
+ DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
+ removeAllCliConsoles();
+ }
+
+ protected void removeAllCliConsoles() {
+ ILaunch[] launches = DebugPlugin.getDefault().getLaunchManager().getLaunches();
+ for (ILaunch launch : launches) {
+ removeCliConsole(launch);
+ }
+ }
+
+ @Override
+ public void launchesAdded(ILaunch[] launches) {
+ for (ILaunch launch : launches) {
+ addCliConsole(launch);
+ }
+ }
+
+ @Override
+ public void launchesChanged(ILaunch[] launches) {
+ }
+
+ @Override
+ public void launchesRemoved(ILaunch[] launches) {
+ for (ILaunch launch : launches) {
+ removeCliConsole(launch);
+ }
+ }
+
+ @Override
+ public void launchesTerminated(ILaunch[] launches) {
+ for (ILaunch launch : launches) {
+ renameCliConsole(launch);
+ }
+ }
+
+ protected void addCliConsole(ILaunch launch) {
+ // Full CLI GDB consoles are only added for GdbLaunches
+ if (launch instanceof GdbLaunch) {
+ new GdbCliConsoleCreator((GdbLaunch)launch).init();
+ }
+ }
+
+ protected void removeCliConsole(ILaunch launch) {
+ GdbCliConsole console = getCliConsole(launch);
+ if (console != null) {
+ ConsolePlugin.getDefault().getConsoleManager().removeConsoles(new IConsole[]{console});
+ }
+ }
+
+ protected void renameCliConsole(ILaunch launch) {
+ GdbCliConsole console = getCliConsole(launch);
+ if (console != null) {
+ console.resetName();
+ }
+ }
+
+ private GdbCliConsole getCliConsole(ILaunch launch) {
+ ConsolePlugin plugin = ConsolePlugin.getDefault();
+ if (plugin != null) {
+ // This plugin can be null when running headless JUnit tests
+ IConsoleManager manager = plugin.getConsoleManager();
+ IConsole[] consoles = manager.getConsoles();
+ for (IConsole console : consoles) {
+ if (console instanceof GdbCliConsole) {
+ GdbCliConsole gdbConsole = (GdbCliConsole)console;
+ if (gdbConsole.getLaunch().equals(launch)) {
+ return gdbConsole;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Class that determines if a GdbCliConsole should be created for
+ * this particular Gdblaunch. It figures this out by asking the
+ * Backend service.
+ */
+ private class GdbCliConsoleCreator {
+ private GdbLaunch fLaunch;
+ private DsfSession fSession;
+
+ public GdbCliConsoleCreator(GdbLaunch launch) {
+ fLaunch = launch;
+ fSession = launch.getSession();
+ }
+
+ public void init() {
+ try {
+ fSession.getExecutor().submit(new DsfRunnable() {
+ @Override
+ public void run() {
+ // Look for backend service right away. It probably
+ // won't be available yet but we must make sure.
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fSession.getId());
+ IGDBBackend backend = tracker.getService(IGDBBackend.class);
+ tracker.dispose();
+
+ if (backend != null) {
+ // Backend service already available, us it!
+ verifyAndCreateCliConsole(backend);
+ } else {
+ // Backend service not available yet, let's wait for it to start.
+ fSession.addServiceEventListener(new GdbBackendStartedListener(GdbCliConsoleCreator.this, fSession), null);
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ }
+ }
+
+ @ConfinedToDsfExecutor("fSession.getExecutor()")
+ private void verifyAndCreateCliConsole(IGDBBackend backend) {
+ if (backend != null && backend.isFullGdbConsoleSupported()) {
+ // Create an new Cli console .
+ String gdbVersion;
+ try {
+ gdbVersion = fLaunch.getGDBVersion();
+ } catch (CoreException e) {
+ assert false : "Should not happen since the gdb version is cached"; //$NON-NLS-1$
+ gdbVersion = "???"; //$NON-NLS-1$
+ }
+ String consoleTitle = fLaunch.getGDBPath().toOSString().trim() + " (" + gdbVersion +")"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ GdbCliConsole console = new GdbCliConsole(fLaunch, consoleTitle);
+
+ // Register this console
+ ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[]{console});
+
+ // Very important to make sure the console view is open or else things will not work
+ ConsolePlugin.getDefault().getConsoleManager().showConsoleView(console);
+ }
+ // Else, not the right type of backend service, or the service said not to start a GdbCliConsole
+ }
+
+ @ConfinedToDsfExecutor("fSession.getExecutor()")
+ private void backendStarted() {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fSession.getId());
+ IGDBBackend backend = tracker.getService(IGDBBackend.class);
+ tracker.dispose();
+
+ verifyAndCreateCliConsole(backend);
+ }
+ }
+
+ /**
+ * Class used to listen for Backend started event which indicate
+ * the DSF-GDB backend service can be used.
+ * This class must be public to receive the event.
+ */
+ public class GdbBackendStartedListener {
+ private DsfSession fSession;
+ private GdbCliConsoleCreator fCreator;
+
+ public GdbBackendStartedListener(GdbCliConsoleCreator creator, DsfSession session) {
+ fCreator = creator;
+ fSession = session;
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(BackendStateChangedEvent event) {
+ if (event.getState() == IMIBackend.State.STARTED &&
+ event.getSessionId().equals(fSession.getId()))
+ {
+ fCreator.backendStarted();
+ // No longer need to receive events.
+ fSession.removeServiceEventListener(this);
+ }
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsolePage.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsolePage.java
new file mode 100644
index 00000000000..c3600129d85
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/GdbCliConsolePage.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Ericsson 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.console;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.tm.internal.terminal.control.ITerminalListener;
+import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
+import org.eclipse.tm.internal.terminal.control.TerminalViewControlFactory;
+import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
+import org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
+import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
+import org.eclipse.tm.terminal.view.core.interfaces.ITerminalServiceOutputStreamMonitorListener;
+import org.eclipse.tm.terminal.view.core.interfaces.constants.ITerminalsConnectorConstants;
+import org.eclipse.tm.terminal.view.ui.interfaces.ILauncherDelegate;
+import org.eclipse.tm.terminal.view.ui.launcher.LauncherDelegateManager;
+import org.eclipse.ui.part.Page;
+
+public class GdbCliConsolePage extends Page {
+
+ private DsfSession fSession;
+ private Composite fMainComposite;
+
+ /** The control for the terminal widget embedded in the console */
+ private ITerminalViewControl fTerminalControl;
+
+ public GdbCliConsolePage(GdbCliConsole gdbConsole) {
+ ILaunch launch = gdbConsole.getLaunch();
+ if (launch instanceof GdbLaunch) {
+ fSession = ((GdbLaunch)launch).getSession();
+ } else {
+ assert false;
+ }
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ fTerminalControl.disposeTerminal();
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ fMainComposite = new Composite(parent, SWT.NONE);
+ fMainComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ fMainComposite.setLayout(new FillLayout());
+
+ // Create the terminal control that will be used to interact with GDB
+ fTerminalControl = TerminalViewControlFactory.makeControl(
+ new ITerminalListener() {
+ @Override public void setState(TerminalState state) {}
+ @Override public void setTerminalTitle(final String title) {}
+ },
+ fMainComposite,
+ new ITerminalConnector[] {},
+ true);
+
+ try {
+ fTerminalControl.setEncoding(Charset.defaultCharset().name());
+ } catch (UnsupportedEncodingException e) {
+ }
+
+ // Hook the terminal control to the GDB process
+ attachTerminalToGdbProcess();
+ }
+
+ @Override
+ public Control getControl() {
+ return fMainComposite;
+ }
+
+ @Override
+ public void setFocus() {
+ fTerminalControl.setFocus();
+ }
+
+ protected void attachTerminalToGdbProcess() {
+ if (fSession == null) {
+ return;
+ }
+
+ try {
+ fSession.getExecutor().submit(new DsfRunnable() {
+ @Override
+ public void run() {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fSession.getId());
+ IGDBBackend backend = tracker.getService(IGDBBackend.class);
+ tracker.dispose();
+
+ if (backend != null) {
+ if (backend.getProcess() != null) {
+ attachTerminal(backend.getProcess());
+ }
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ }
+ }
+
+ protected void attachTerminal(Process process) {
+ ILauncherDelegate delegate =
+ LauncherDelegateManager.getInstance().getLauncherDelegate("org.eclipse.tm.terminal.connector.streams.launcher.streams", false); //$NON-NLS-1$
+ if (delegate != null) {
+ Map<String, Object> properties = createNewSettings(process);
+
+ ITerminalConnector connector = delegate.createTerminalConnector(properties);
+ fTerminalControl.setConnector(connector);
+ if (fTerminalControl instanceof ITerminalControl) {
+ ((ITerminalControl)fTerminalControl).setConnectOnEnterIfClosed(false);
+ ((ITerminalControl)fTerminalControl).setVT100LineWrapping(true);
+ }
+
+ // Must use syncExec because the logic within must complete before the rest
+ // of the class methods (specifically getProcess()) is called
+ fMainComposite.getDisplay().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (fTerminalControl != null && !fTerminalControl.isDisposed()) {
+ fTerminalControl.clearTerminal();
+ fTerminalControl.connectTerminal();
+ }
+ }
+ });
+ }
+ }
+
+ protected Map<String, Object> createNewSettings(Process process) {
+
+ // Create the terminal connector
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put(ITerminalsConnectorConstants.PROP_LOCAL_ECHO, Boolean.FALSE);
+ properties.put(ITerminalsConnectorConstants.PROP_STREAMS_STDIN, process.getOutputStream());
+ properties.put(ITerminalsConnectorConstants.PROP_STREAMS_STDOUT, process.getInputStream());
+ properties.put(ITerminalsConnectorConstants.PROP_STREAMS_STDERR, process.getErrorStream());
+ properties.put(ITerminalsConnectorConstants.PROP_STDOUT_LISTENERS,
+ new ITerminalServiceOutputStreamMonitorListener[0]);
+ properties.put(ITerminalsConnectorConstants.PROP_STDERR_LISTENERS,
+ new ITerminalServiceOutputStreamMonitorListener[0]);
+ return properties;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/TracingConsole.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/TracingConsole.java
index e65bff0c98f..a60cab216f5 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/TracingConsole.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/console/TracingConsole.java
@@ -138,7 +138,7 @@ public class TracingConsole extends IOConsole {
}
if (fLaunch.isTerminated()) {
- return ConsoleMessages.ConsoleMessages_trace_console_terminated + label;
+ return ConsoleMessages.ConsoleMessages_console_terminated + label;
}
return label;
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBProcess.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBProcess.java
index b36c99f117f..22cf639c5fd 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBProcess.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBProcess.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010 Marc-Andre Laperle and others.
+ * Copyright (c) 2010, 2016 Marc-Andre Laperle 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
@@ -10,13 +10,21 @@
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.launching;
+import java.io.IOException;
import java.util.Map;
+import org.eclipse.cdt.dsf.gdb.service.command.IGDBBackendProcessWithoutIO;
import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IStreamMonitor;
+import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.debug.core.model.RuntimeProcess;
/**
- * A process for the gdb backend to differentiate it from the inferior
+ * A process for the gdb backend to differentiate it from the inferior.
+ *
+ * This process disables the base class handling of IO streams if we
+ * are using the full GDB console, which is handled by the
+ * GdbConsoleManager instead.
*
* @since 3.0
*/
@@ -27,4 +35,56 @@ public class GDBProcess extends RuntimeProcess {
super(launch, process, name, attributes);
}
+ @Override
+ public IStreamsProxy getStreamsProxy() {
+ IStreamsProxy proxy = super.getStreamsProxy();
+ // If our proxy is the one that ignores the streams,
+ // this method should return null.
+ // Returning null insures that there will not be a
+ // text console automatically created for this process
+ // see ProcessConsoleManager#launchChanged()
+ return proxy instanceof NoStreamsProxy ? null : proxy;
+ }
+
+ @Override
+ protected IStreamsProxy createStreamsProxy() {
+ // TRICKY. This method is called by the constructor of
+ // the super class. This means we don't have time to
+ // set any fields in this class by then. Therefore,
+ // we can only use what was set by the base class constructor
+ // to figure out how to behave.
+ // We can call getSystemProcess() as it is set earlier
+ // in the constructor then when this method is called.
+ if (getSystemProcess() instanceof IGDBBackendProcessWithoutIO) {
+ // If the GDB process used does not handle I/O, we return a proxy
+ // that ignores the streams.
+ return new NoStreamsProxy();
+ }
+ return super.createStreamsProxy();
+ }
+
+ /**
+ * Class that provides a streams proxy that actually
+ * ignores the I/O streams. We use this in the case
+ * of the full GDB console where the GDB CLI is used directly,
+ * without us needing to do anything with the I/O ourselves.
+ *
+ * This is different than NullStreamsProxy which would
+ * still read but discard the IO, which is not what we want.
+ */
+ private class NoStreamsProxy implements IStreamsProxy {
+ @Override
+ public IStreamMonitor getErrorStreamMonitor() {
+ return null;
+ }
+
+ @Override
+ public IStreamMonitor getOutputStreamMonitor() {
+ return null;
+ }
+
+ @Override
+ public void write(String input) throws IOException {
+ }
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java
index 6abe37d0eef..48ec7751db1 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java
@@ -64,7 +64,6 @@ import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.memory.GdbMemoryBlockRetrievalManager;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
-import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
@@ -202,13 +201,13 @@ public class GdbLaunch extends DsfLaunch implements ITerminate, IDisconnect, ITr
@ThreadSafeAndProhibitedFromDsfExecutor("getDsfExecutor()")
public void addCLIProcess(String label) throws CoreException {
try {
- // Add the CLI process object to the launch.
- AbstractCLIProcess cliProc = getDsfExecutor().submit(new Callable<AbstractCLIProcess>() {
+ // Add the GDB process object to the launch.
+ Process gdbProc = getDsfExecutor().submit(new Callable<Process>() {
@Override
- public AbstractCLIProcess call() throws CoreException {
+ public Process call() throws CoreException {
IGDBControl gdb = fTracker.getService(IGDBControl.class);
if (gdb != null) {
- return gdb.getCLIProcess();
+ return gdb.getGDBBackendProcess();
}
return null;
}
@@ -221,7 +220,7 @@ public class GdbLaunch extends DsfLaunch implements ITerminate, IDisconnect, ITr
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(IGdbDebugConstants.PROCESS_TYPE_CREATION_ATTR,
IGdbDebugConstants.GDB_PROCESS_CREATION_VALUE);
- DebugPlugin.newProcess(this, cliProc, label, attributes);
+ DebugPlugin.newProcess(this, gdbProc, label, attributes);
} catch (InterruptedException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, 0,
"Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java
index 94ebb852dbe..d2fa6815355 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java
@@ -157,7 +157,8 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
};
}
- private GdbLaunch getGDBLaunch() {
+ /** @since 5.1 */
+ protected GdbLaunch getGDBLaunch() {
return (GdbLaunch) getSession().getModelAdapter(ILaunch.class);
}
@@ -171,7 +172,9 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
* array. Allow subclass to override.
*
* @since 4.6
+ * @deprecated Replaced by getDebuggerCommandLine()
*/
+ @Deprecated
protected String[] getGDBCommandLineArray() {
// The goal here is to keep options to an absolute minimum.
// All configuration should be done in the final launch sequence
@@ -189,6 +192,39 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
return CommandLineUtil.argumentsToArray(cmd);
}
+ /**
+ * Returns the GDB command and its arguments as an array.
+ * Allow subclass to override.
+ * @since 5.1
+ */
+ // This method replaces getGDBCommandLineArray() because we need
+ // to override it for GDB 7.12 even if an extender has overridden
+ // getGDBCommandLineArray().
+ // Here is the scenario:
+ // An extender has overridden getGDBCommandLineArray() to launch
+ // GDB in MI mode but with extra parameters. Once GDBBackend_7_12
+ // is released, the extender may likely point their extension to
+ // GDBBackend_7_12 instead of GDBBackend (which will even happen
+ // automatically if the extender extends GDBBackend_HEAD).
+ // In such a case, they would override the changes in
+ // GDBBackend_7_12.getGDBCommandLineArray() and the debug session
+ // is likely to fail since with GDBBackend_7_12, we launch GDB
+ // in CLI mode.
+ //
+ // Instead, we use getDebuggerCommandLine() and override that method in
+ // GDBBackend_7_12. That way an extender will not override it
+ // without noticing (since it didn't exist before). Then we can call
+ // the overridden getGDBCommandLineArray() and work with that to
+ // make it work with the new way to launch GDB of GDBBackend_7_12
+ //
+ // Note that we didn't name this method getGDBCommandLine() because
+ // this name had been used in CDT 8.8 and could still be part of
+ // extenders' code.
+ protected String[] getDebuggerCommandLine() {
+ // Call the old method in case it was overridden
+ return getGDBCommandLineArray();
+ }
+
@Override
public String getGDBInitFile() throws CoreException {
return getGDBLaunch().getGDBInitFile();
@@ -237,11 +273,34 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
}
/**
+ * Launch GDB process. Allow subclass to override.
+ *
+ * @since 5.1
+ */
+ // Again, we create a new method that we know has not been already
+ // overridden. That way, even if extenders have overridden the
+ // original launchGDBProcess(String[]), we will instead use
+ // the GDBBackend_7_12#launchGDBProcess() method when appropriate.
+ // This is important because if we didn't, the new console would
+ // not work properly.
+ //
+ // Of course, in that case, we won't call the extenders overridden
+ // launchGDBProcess(String[]) and therefore will not get their
+ // specialized code. I feel this is still a lower risk than
+ // not starting the full GDB console properly.
+ protected Process launchGDBProcess() throws CoreException {
+ // Call the old method in case it was overridden
+ return launchGDBProcess(getDebuggerCommandLine());
+ }
+
+ /**
* Launch GDB process with command and arguments. Allow subclass to
* override.
*
* @since 4.6
+ * @deprecated Replace by launchGDBProcess()
*/
+ @Deprecated
protected Process launchGDBProcess(String[] commandLine) throws CoreException {
Process proc = null;
try {
@@ -254,6 +313,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
return proc;
}
+ @Override
public Process getProcess() {
return fProcess;
}
@@ -466,7 +526,8 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
}
try {
- fProcess = launchGDBProcess(getGDBCommandLineArray());
+ fProcess = launchGDBProcess();
+
// Need to do this on the executor for thread-safety
getExecutor().submit(new DsfRunnable() {
@Override
@@ -488,8 +549,12 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
BufferedReader errorReader = null;
boolean success = false;
try {
+ // Must call getMIInputStream() because we always want to read from the MI stream,
+ // which is not always the same as the input stream of fProcess. They are
+ // different when we use the full GDB console
+ InputStream inputStream = getMIInputStream();
// Read initial GDB prompt
- inputReader = new BufferedReader(new InputStreamReader(getMIInputStream()));
+ inputReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = inputReader.readLine()) != null) {
line = line.trim();
@@ -501,7 +566,11 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa
// Failed to read initial prompt, check for error
if (!success) {
- errorReader = new BufferedReader(new InputStreamReader(getMIErrorStream()));
+ // Don't call getMIErrorStream() because it can be overridden with a
+ // dummy stream in the case of the full GDB console.
+ // Instead, make sure we read the error from the process itself.
+ InputStream errorStream = fProcess.getErrorStream();
+ errorReader = new BufferedReader(new InputStreamReader(errorStream));
String errorInfo = errorReader.readLine();
if (errorInfo == null) {
errorInfo = "GDB prompt not read"; //$NON-NLS-1$
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
new file mode 100644
index 00000000000..edb881e87ca
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend_7_12.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.eclipse.cdt.core.parser.util.StringUtil;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.utils.pty.PTY;
+import org.eclipse.cdt.utils.pty.PTY.Mode;
+import org.eclipse.cdt.utils.spawner.ProcessFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Implementation of {@link IGDBBackend} using GDB 7.12. This version provides
+ * full GDB console support. It achieves this by launching GDB in CLI mode
+ * in a special console widget and then connecting to GDB via MI by telling GDB to
+ * open a new MI console. The rest of the DSF-GDB support then stays the same.
+ *
+ * If we are unable to create a PTY, we then revert to the previous behavior of
+ * the base class.
+ *
+ * @since 5.1
+ */
+public class GDBBackend_7_12 extends GDBBackend {
+
+ /** The PTY that is used to enable the full GDB console */
+ private PTY fPty;
+ /** Indicate that we failed to create a PTY. */
+ private boolean fPtyFailure;
+
+ private InputStream fDummyErrorStream;
+
+ public GDBBackend_7_12(DsfSession session, ILaunchConfiguration lc) {
+ super(session, lc);
+ createPty();
+ }
+
+ @Override
+ public boolean isFullGdbConsoleSupported() {
+ return !Platform.getOS().equals(Platform.OS_WIN32)
+ && !fPtyFailure;
+ }
+
+ protected void createPty() {
+ if (!isFullGdbConsoleSupported()) {
+ return;
+ }
+
+ try {
+ fPty = new PTY();
+ fPty.validateSlaveName();
+
+ // With the PTY the stderr is redirected to the PTY's output stream.
+ // Therefore, return a dummy stream for the error stream.
+ fDummyErrorStream = new InputStream() {
+ @Override
+ public int read() throws IOException {
+ return -1;
+ }
+ };
+ } catch (IOException e) {
+ fPty = null;
+ fPtyFailure = true;
+ GdbPlugin.log(new Status(
+ IStatus.INFO, GdbPlugin.PLUGIN_ID,
+ NLS.bind(Messages.PTY_Console_not_available, e.getMessage())));
+ }
+ }
+
+ @Override
+ public OutputStream getMIOutputStream() {
+ if (fPty == null) {
+ return super.getMIOutputStream();
+ }
+ return fPty.getOutputStream();
+ };
+
+ @Override
+ public InputStream getMIInputStream() {
+ if (fPty == null) {
+ return super.getMIInputStream();
+ }
+ return fPty.getInputStream();
+ };
+
+ @Override
+ public InputStream getMIErrorStream() {
+ if (fPty == null) {
+ return super.getMIErrorStream();
+ }
+ return fDummyErrorStream;
+ };
+
+ @Override
+ protected String[] getDebuggerCommandLine() {
+ // Start from the original command line method which
+ // could have been overridden by extenders, and add what we need
+ // to convert it to a command that will launch in CLI mode.
+ // Then trigger the MI console
+ @SuppressWarnings("deprecation")
+ String[] originalCommandLine = getGDBCommandLineArray();
+
+ if (!isFullGdbConsoleSupported()) {
+ return originalCommandLine;
+ }
+
+ // Below are the parameters we need to add to an existing commandLine,
+ // to trigger a launch with the full CLI. This would also work
+ // as the only parameters for a full CLI launch (although "--interpreter console"
+ // could be removed in that case)
+ String[] extraArguments = new String[] {
+ // Start with -q option to avoid extra output which may trigger pagination
+ // This is important because if pagination is triggered on the version
+ // printout, we won't be able to send the command to start the MI channel.
+ // Note that we cannot turn off pagination early enough to prevent the
+ // original version output from paginating
+ "-q", //$NON-NLS-1$
+
+// We don't put --nx at this time because our base class puts it already and if
+// if an extender has removed it, we shouldn't add it again.
+// Once we no longer extends the deprecated getGDBCommandLineArray() and simply
+// create the full commandLine here, we should put it
+// // Use the --nx option to avoid reading the gdbinit file here.
+// // The gdbinit file is read explicitly in the FinalLaunchSequence to make
+// // it easier to customize.
+// "--nx", //$NON-NLS-1$
+
+ // Force a CLI console since the originalCommandLine
+ // probably specified "-i mi" or "--interpreter mi"
+ // Once we no longer extend the deprecated
+ // getGDBCommandLineArray() and simply create the full
+ // commandLine here, we could remove this parameter
+ "--interpreter", "console", //$NON-NLS-1$ //$NON-NLS-2$
+
+ // Now trigger the new console towards our PTY.
+ "-ex", "new-ui mi " + fPty.getSlaveName(), //$NON-NLS-1$ //$NON-NLS-2$
+
+ // Now print the version so the user gets that familiar output
+ "-ex", "show version" //$NON-NLS-1$ //$NON-NLS-2$
+ };
+
+ int oriLength = originalCommandLine.length;
+ int extraLength = extraArguments.length;
+ String[] newCommandLine = new String[oriLength+extraLength];
+ System.arraycopy(originalCommandLine, 0, newCommandLine, 0, oriLength);
+ System.arraycopy(extraArguments, 0, newCommandLine, oriLength, extraLength);
+
+ return newCommandLine;
+ }
+
+ @Override
+ protected Process launchGDBProcess() throws CoreException {
+ if (!isFullGdbConsoleSupported()) {
+ return super.launchGDBProcess();
+ }
+
+ // If we are launching the full console, we need to use a PTY in TERMINAL mode
+ // for the GDB CLI to properly display in its view
+ Process proc = null;
+ String[] commandLine = getDebuggerCommandLine();
+ try {
+ IPath path = getGDBWorkingDirectory();
+ proc = ProcessFactory.getFactory().exec(
+ commandLine,
+ getGDBLaunch().getLaunchEnvironment(),
+ new File(path != null ? path.toOSString() : ""), //$NON-NLS-1$
+ new PTY(Mode.TERMINAL));
+ } catch (IOException e) {
+ String message = "Error while launching command: " + StringUtil.join(commandLine, " "); //$NON-NLS-1$ //$NON-NLS-2$
+ throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, message, e));
+ }
+
+ return proc;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
index e9814b248cc..1968421f67b 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
@@ -88,6 +88,8 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
public static final String GDB_7_7_VERSION = "7.7"; //$NON-NLS-1$
/** @since 4.8 */
public static final String GDB_7_10_VERSION = "7.10"; //$NON-NLS-1$
+ /** @since 5.1 */
+ public static final String GDB_7_12_VERSION = "7.12"; //$NON-NLS-1$
private final String fVersion;
private final ILaunchConfiguration fConfiguration;
@@ -224,6 +226,11 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
}
protected IMIBackend createBackendGDBService(DsfSession session, ILaunchConfiguration lc) {
+ if (compareVersionWith(GDB_7_12_VERSION) >= 0
+ || compareVersionWith("7.11.50") >= 0 // TODO remove once GDB 7.12 is released
+ ) {
+ return new GDBBackend_7_12(session, lc);
+ }
return new GDBBackend(session, lc);
}
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 abbc9844869..4dccacc137d 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
@@ -156,4 +156,21 @@ public interface IGDBBackend extends IMIBackend {
* @since 3.0
*/
public boolean getUpdateThreadListOnSuspend() throws CoreException;
+
+ /**
+ * @return True if the full GDB console should be used. False otherwise.
+ *
+ * @since 5.1
+ */
+ default boolean isFullGdbConsoleSupported() {
+ return false;
+ }
+
+ /**
+ * @return The real GDB process that was started for the debug session
+ * @since 5.1
+ */
+ default Process getProcess() {
+ throw new RuntimeException();
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java
index da5bc459d7a..a6657cce834 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java
@@ -31,6 +31,7 @@ class Messages extends NLS {
public static String RegisterGroup_name_used;
public static String RegisterGroup_invalid_number_of_registers;
public static String GDB_Version_Mismatch;
+ public static String PTY_Console_not_available;
static {
// initialize resource bundle
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties
index dd6e0eff46e..d2c0fd6f97e 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties
@@ -22,4 +22,5 @@ ErrorNotSupported=Operation not supported with this GDB version
RegisterGroup_name_reserved=The group name "{0}" is reserved
RegisterGroup_name_used=The group name "{0}" is already in use
RegisterGroup_invalid_number_of_registers=A minimum of one register is needed for a Register Group
-GDB_Version_Mismatch=Running older GDB version {0} when service {1} expects version {2} or higher \ No newline at end of file
+GDB_Version_Mismatch=Running older GDB version {0} when service {1} expects version {2} or higher
+PTY_Console_not_available=PTY not available, cannot use full GDB console: {0} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendCLIProcess.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendCLIProcess.java
index 3a07602ea84..0cec1bbc1c4 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendCLIProcess.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendCLIProcess.java
@@ -21,7 +21,12 @@ import org.eclipse.cdt.dsf.mi.service.IMIBackend;
import org.eclipse.cdt.dsf.mi.service.command.MIBackendCLIProcess;
import org.eclipse.cdt.dsf.service.DsfSession;
-/**
+/**
+ * Note that starting with GDB 7.12, as long as a PTY is available,
+ * this process is no longer used. Instead, the real GDB process,
+ * along with its console will be used directly. A second PTY
+ * will be used to communicate using MI.
+
* @author LWang
* @since 2.0
*
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendProcessWithoutIO.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendProcessWithoutIO.java
new file mode 100644
index 00000000000..0345b140954
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBBackendProcessWithoutIO.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service.command;
+
+import java.io.IOException;
+
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+
+/**
+ * Note that starting with GDB 7.12, as long as a PTY is available, this process
+ * is used instead of GDBBackendProcess. This is because the GDB CLI is handled
+ * directly by GDB and the current class only needs to handle the life-cycle of
+ * the GDB process.
+ *
+ * This class is therefore a representation of the GDB process that will be
+ * added to the launch. This class is not the real GDB process but simply an
+ * entry for the launch to handle user actions but no IO.
+ *
+ * This class extends {@link GDBBackendCLIProcess} to re-use its implementation
+ * of the {@link Process} abstract methods, but disables all I/O and
+ * local CLI handling.
+ *
+ * @since 5.1
+ */
+public class GDBBackendProcessWithoutIO extends GDBBackendCLIProcess implements IGDBBackendProcessWithoutIO {
+
+ public GDBBackendProcessWithoutIO(ICommandControlService commandControl, IMIBackend backend) throws IOException {
+ super(commandControl, backend);
+ }
+
+ @Override
+ public boolean handleIO() {
+ // Streams are handled directly by the real process.
+ // This class is just representation for the launch, without IO.
+ return false;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java
index 51d414b572a..1d751cb7b87 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java
@@ -193,7 +193,7 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
private IEventProcessor fMIEventProcessor;
private IEventProcessor fCLICommandProcessor;
private IEventProcessor fControlEventProcessor;
- private AbstractCLIProcess fCLIProcess;
+ private Process fBackendProcess;
private GdbCommandTimeoutManager fCommandTimeoutManager;
@@ -358,11 +358,24 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
);
}
+ /**
+ * @deprecated Replaced by {@link #getGDBBackendProcess()}
+ */
+ @Deprecated
@Override
- public AbstractCLIProcess getCLIProcess() {
- return fCLIProcess;
+ public AbstractCLIProcess getCLIProcess() {
+ if (fBackendProcess instanceof AbstractCLIProcess) {
+ return (AbstractCLIProcess)fBackendProcess;
+ }
+ return null;
}
+ /** @since 5.1 */
+ @Override
+ public Process getGDBBackendProcess() {
+ return fBackendProcess;
+ }
+
/**
* @since 2.0
*/
@@ -546,8 +559,8 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
/** @since 5.1 */
protected void doCommandProcessorsStep(final RequestMonitor requestMonitor) {
- try {
- fCLIProcess = new GDBBackendCLIProcess(GDBControl.this, fMIBackend);
+ try {
+ fBackendProcess = createBackendProcess();
}
catch(IOException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Failed to create CLI Process", e)); //$NON-NLS-1$
@@ -567,7 +580,9 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
fControlEventProcessor.dispose();
fCLICommandProcessor.dispose();
fMIEventProcessor.dispose();
- fCLIProcess.dispose();
+ if (fBackendProcess instanceof AbstractCLIProcess) {
+ ((AbstractCLIProcess)fBackendProcess).dispose();
+ }
requestMonitor.done();
}
@@ -715,6 +730,18 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
return new ControlEventProcessor();
}
+ /** @since 5.1 */
+ protected Process createBackendProcess() throws IOException {
+ if (fMIBackend.isFullGdbConsoleSupported()) {
+ // If the full GDB console is supported, which uses the GDB process itself,
+ // we return a GDBBackendProcess that does not take care of I/O
+ return new GDBBackendProcessWithoutIO(this, fMIBackend);
+ }
+ // If the full GDB console is not supported according to the backend service,
+ // then we create a special GDBBackendProcess that handles the CLI
+ return new GDBBackendCLIProcess(this, fMIBackend);
+ }
+
/**
* @since 4.1
*/
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBBackendProcessWithoutIO.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBBackendProcessWithoutIO.java
new file mode 100644
index 00000000000..147e7a08a23
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBBackendProcessWithoutIO.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service.command;
+
+/**
+ * Interface used by a process representing the GDB process but for which there
+ * is no IO.
+ *
+ * When using the full GDB console, this marker can be used for the class that
+ * will represent the GDB process in the launch since the IO should not be
+ * handled by the launch and the console it normally created, but is handled by
+ * the full GDB console itself.
+ *
+ * @since 5.1
+ */
+public interface IGDBBackendProcessWithoutIO {
+} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java
index 2e149156b78..afbdc782304 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java
@@ -17,11 +17,37 @@ import java.util.List;
import java.util.Properties;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
public interface IGDBControl extends IMICommandControl {
+ /**
+ * Returns the process that represents GDB.
+ * This is the process that should be added to the launch.
+ * Note that this is usually not be the actual GDB process but
+ * only one that is used to represent it.
+ * To get the real GDB process use
+ * {@link IGDBBackend#getProcess()}.
+ *
+ * @since 5.1
+ */
+ default Process getGDBBackendProcess() {
+ return getCLIProcess();
+ };
+
+ /**
+ * @deprecated The return value of this method was too
+ * restrictive. It has been replaced with
+ * {@link #getGDBBackendProcess()}
+ * @return The AbstractCLIProcess that handles the CLI.
+ * Will return null if the CLI is not handled
+ * by an AbstractCLIProcess; this will sometimes
+ * happen for GDB >= 7.12 if the CLI is handled
+ * by the GDB process itself.
+ */
+ @Deprecated
AbstractCLIProcess getCLIProcess();
/**
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/extensions/GDBBackend_HEAD.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/extensions/GDBBackend_HEAD.java
index dbf43752405..75353aafa65 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/extensions/GDBBackend_HEAD.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/extensions/GDBBackend_HEAD.java
@@ -7,7 +7,7 @@
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service.extensions;
-import org.eclipse.cdt.dsf.gdb.service.GDBBackend;
+import org.eclipse.cdt.dsf.gdb.service.GDBBackend_7_12;
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
import org.eclipse.cdt.dsf.service.DsfSession;
@@ -37,13 +37,13 @@ import org.eclipse.debug.core.ILaunchConfiguration;
*
* @since 4.8
*/
-public class GDBBackend_HEAD extends GDBBackend {
+public class GDBBackend_HEAD extends GDBBackend_7_12 {
public GDBBackend_HEAD(DsfSession session, ILaunchConfiguration lc) {
super(session, lc);
validateGdbVersion(session);
}
- protected String getMinGDBVersionSupported() { return GdbDebugServicesFactory.GDB_7_1_VERSION; }
+ protected String getMinGDBVersionSupported() { return GdbDebugServicesFactory.GDB_7_12_VERSION; }
protected void validateGdbVersion(DsfSession session) {
GdbDebugServicesFactory.validateGdbVersion(session, getMinGDBVersionSupported(), this);
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractCLIProcess.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractCLIProcess.java
index eabfcfbac51..adbb1a494f0 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractCLIProcess.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractCLIProcess.java
@@ -46,9 +46,14 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
/**
- * This Process implementation tracks the process the GDB process. This
- * process object is displayed in Debug view and is used to
- * accept CLI commands and to write their output to the console.
+ * This Process implementation tracks the GDB process. This
+ * process object is displayed in the Debug view and is used to
+ * accept CLI commands and to write their output to the console.
+ *
+ * Starting with GDB 7.12, as long as a PTY is available,
+ * this process is no longer used. Instead, the real GDB process,
+ * along with its console will be used directly. A second PTY
+ * will be used to communicate using MI.
*
* @see org.eclipse.debug.core.model.IProcess
*/
@@ -64,7 +69,7 @@ public abstract class AbstractCLIProcess extends Process
private final DsfSession fSession;
private final ICommandControlService fCommandControl;
- private final OutputStream fOutputStream = new CLIOutputStream();
+ private OutputStream fOutputStream;
// Client process console stream.
private PipedInputStream fMIInConsolePipe;
@@ -103,34 +108,42 @@ public abstract class AbstractCLIProcess extends Process
fSession = commandControl.getSession();
fCommandControl = commandControl;
- commandControl.addEventListener(this);
- commandControl.addCommandListener(this);
+ if (handleIO()) {
+ fOutputStream = new CLIOutputStream();
- PipedInputStream miInConsolePipe = null;
- PipedOutputStream miOutConsolePipe = null;
- PipedInputStream miInLogPipe = null;
- PipedOutputStream miOutLogPipe = null;
-
- try {
- // Using a LargePipedInputStream see https://bugs.eclipse.org/bugs/show_bug.cgi?id=223154
- miOutConsolePipe = new PipedOutputStream();
- miInConsolePipe = new LargePipedInputStream(miOutConsolePipe);
- miOutLogPipe = new PipedOutputStream();
- miInLogPipe = new LargePipedInputStream(miOutLogPipe);
- } catch (IOException e) {
- ILog log = GdbPlugin.getDefault().getLog();
- if (log != null) {
- log.log(new Status(
- IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Error when creating log pipes", e)); //$NON-NLS-1$
- }
+ commandControl.addEventListener(this);
+ commandControl.addCommandListener(this);
+
+ PipedInputStream miInConsolePipe = null;
+ PipedOutputStream miOutConsolePipe = null;
+ PipedInputStream miInLogPipe = null;
+ PipedOutputStream miOutLogPipe = null;
+
+ try {
+ // Using a LargePipedInputStream see https://bugs.eclipse.org/bugs/show_bug.cgi?id=223154
+ miOutConsolePipe = new PipedOutputStream();
+ miInConsolePipe = new LargePipedInputStream(miOutConsolePipe);
+ miOutLogPipe = new PipedOutputStream();
+ miInLogPipe = new LargePipedInputStream(miOutLogPipe);
+ } catch (IOException e) {
+ ILog log = GdbPlugin.getDefault().getLog();
+ if (log != null) {
+ log.log(new Status(
+ IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Error when creating log pipes", e)); //$NON-NLS-1$
+ }
+ }
+ fMIOutConsolePipe = miOutConsolePipe;
+ fMIInConsolePipe = miInConsolePipe;
+ fMIOutLogPipe = miOutLogPipe;
+ fMIInLogPipe = miInLogPipe;
}
- // Must initialize these outside of the try block because they are final.
- fMIOutConsolePipe = miOutConsolePipe;
- fMIInConsolePipe = miInConsolePipe;
- fMIOutLogPipe = miOutLogPipe;
- fMIInLogPipe = miInLogPipe;
}
+ /**
+ * @since 5.1
+ */
+ protected boolean handleIO() { return true; }
+
protected DsfSession getSession() { return fSession; }
/**
@@ -165,18 +178,26 @@ public abstract class AbstractCLIProcess extends Process
}
private void closeIO() {
- try {
- fMIOutConsolePipe.close();
- } catch (IOException e) {}
- try {
- fMIInConsolePipe.close();
- } catch (IOException e) {}
- try {
- fMIOutLogPipe.close();
- } catch (IOException e) {}
- try {
- fMIInLogPipe.close();
- } catch (IOException e) {}
+ if (fMIOutConsolePipe != null) {
+ try {
+ fMIOutConsolePipe.close();
+ } catch (IOException e) {}
+ }
+ if (fMIInConsolePipe != null) {
+ try {
+ fMIInConsolePipe.close();
+ } catch (IOException e) {}
+ }
+ if (fMIOutLogPipe != null) {
+ try {
+ fMIOutLogPipe.close();
+ } catch (IOException e) {}
+ }
+ if (fMIInLogPipe != null) {
+ try {
+ fMIInLogPipe.close();
+ } catch (IOException e) {}
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIBackendCLIProcess.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIBackendCLIProcess.java
index a7091a0945f..f2dcb01f69c 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIBackendCLIProcess.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIBackendCLIProcess.java
@@ -37,6 +37,11 @@ import org.eclipse.core.runtime.Status;
/**
* CLI Process object implementation which uses the {@link IMIBackend} service
* to monitor and control the underlying process.
+ *
+ * Note that starting with GDB 7.12, as long as a PTY is available,
+ * this process is no longer used. Instead, the real GDB process,
+ * along with its console will be used directly. A second PTY
+ * will be used to communicate using MI.
*
* @since 1.1
*/
diff --git a/releng/org.eclipse.cdt.target/cdt.target b/releng/org.eclipse.cdt.target/cdt.target
index 5d2df286e14..b7e1a52c59a 100644
--- a/releng/org.eclipse.cdt.target/cdt.target
+++ b/releng/org.eclipse.cdt.target/cdt.target
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde version="3.8"?><target name="cdt" sequenceNumber="14">
+<?pde version="3.8"?><target name="cdt" sequenceNumber="15">
<locations>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.apache.commons.compress" version="0.0.0"/>
@@ -60,6 +60,7 @@
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.tm.terminal.control" version="0.0.0"/>
+<unit id="org.eclipse.tm.terminal.view.ui" version="0.0.0"/>
<repository location="http://download.eclipse.org/tm/terminal/builds/development/nightly/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">

Back to the top