From 0da8033c2c0947959860edab8c141fdf3a6ec2e3 Mon Sep 17 00:00:00 2001 From: Max Bureck Date: Mon, 26 Nov 2018 00:20:16 +0100 Subject: Bug 541520: Make GDB version detection standalone Provides GDB version detection as a public API that can be used without having a saved launch config, or having a launch config at all. Change-Id: Ifaee337899c01fe7066b27f7d66484bfc728f5ed Signed-off-by: Max Bureck --- .../eclipse/cdt/dsf/gdb/launching/GdbLaunch.java | 77 ++-------------------- .../eclipse/cdt/dsf/gdb/launching/LaunchUtils.java | 29 +++++++- 2 files changed, 32 insertions(+), 74 deletions(-) (limited to 'dsf-gdb') 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 9836ada7c16..729d211e334 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 @@ -41,7 +41,6 @@ import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.parser.util.StringUtil; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; @@ -72,8 +71,6 @@ import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; -import org.eclipse.cdt.utils.CommandLineUtil; -import org.eclipse.cdt.utils.spawner.ProcessFactory; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -81,13 +78,11 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; @@ -514,75 +509,13 @@ public class GdbLaunch extends DsfLaunch implements ITerminate, IDisconnect, ITr return fGdbVersion; } - String cmd = getGDBPath().toOSString() + " --version"; //$NON-NLS-1$ + String gdbPath = getGDBPath().toOSString(); + String[] launchEnvironment = getLaunchEnvironment(); - // Parse cmd to properly handle spaces and such things (bug 458499) - String[] args = CommandLineUtil.argumentsToArray(cmd); + String gdbVersion = LaunchUtils.getGDBVersion(gdbPath, launchEnvironment); + fGdbVersion = gdbVersion; + return fGdbVersion; - Process process = null; - Job timeoutJob = null; - try { - process = ProcessFactory.getFactory().exec(args, getLaunchEnvironment()); - - // Start a timeout job to make sure we don't get stuck waiting for - // an answer from a gdb that is hanging - // Bug 376203 - final Process finalProc = process; - timeoutJob = new Job("GDB version timeout job") { //$NON-NLS-1$ - { - setSystem(true); - } - - @Override - protected IStatus run(IProgressMonitor arg) { - // Took too long. Kill the gdb process and - // let things clean up. - finalProc.destroy(); - return Status.OK_STATUS; - } - }; - timeoutJob.schedule(10000); - - String streamOutput = readStream(process.getInputStream()); - - String gdbVersion = LaunchUtils.getGDBVersionFromText(streamOutput); - if (gdbVersion == null || gdbVersion.isEmpty()) { - Exception detailedException = null; - if (!streamOutput.isEmpty()) { - // We got some output but couldn't parse it. Make that - // output visible to the user in the error dialog. - detailedException = new Exception("Unexpected output format: \n\n" + streamOutput); //$NON-NLS-1$ - } else { - // We got no output. Check if we got something on the error - // stream. - streamOutput = readStream(process.getErrorStream()); - if (!streamOutput.isEmpty()) { - detailedException = new Exception(streamOutput); - } - } - - throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, - "Could not determine GDB version using command: " + StringUtil.join(args, " "), //$NON-NLS-1$ //$NON-NLS-2$ - detailedException)); - } - fGdbVersion = gdbVersion; - return fGdbVersion; - } catch (IOException e) { - throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, - "Error with command: " + StringUtil.join(args, " "), e));//$NON-NLS-1$ //$NON-NLS-2$ - } finally { - // If we get here we are obviously not stuck reading the stream so - // we can cancel the timeout job. - // Note that it may already have executed, but that is not a - // problem. - if (timeoutJob != null) { - timeoutJob.cancel(); - } - - if (process != null) { - process.destroy(); - } - } } /** diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java index b67cc2665b0..ecee91644c3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -284,7 +285,31 @@ public class LaunchUtils { */ @Deprecated public static String getGDBVersion(final ILaunchConfiguration configuration) throws CoreException { - String cmd = getGDBPath(configuration).toOSString() + " --version"; //$NON-NLS-1$ + String gdbPath = getGDBPath(configuration).toOSString(); + String[] launchEnvironment = getLaunchEnvironment(configuration); + + return getGDBVersion(gdbPath, launchEnvironment); + } + + /** + * This method actually launches 'gdb --version' to determine the version of + * the GDB that is being used. + * + * A timeout is scheduled which will kill the process if it takes too long. + * + * @param gdbPath the path to the GDB executable to be called + * @param launchEnvironment the environment variables set for the + * GDB process. Every element of the array must be of format "key=value". + * @return the detected version of GDB at {@code gdbPath} + * @throws CoreException is e.g. thrown if the execution of GDB fails + * @throws NullPointerException if {@code gdbPath} or {@code launchEnvironment} is {@code null} + * @since 5.6 + */ + public static String getGDBVersion(String gdbPath, String[] launchEnvironment) throws CoreException { + Objects.requireNonNull(gdbPath, "gdbPath"); //$NON-NLS-1$ + Objects.requireNonNull(launchEnvironment, "launchEnvironment"); //$NON-NLS-1$ + + String cmd = gdbPath + " --version"; //$NON-NLS-1$ // Parse cmd to properly handle spaces and such things (bug 458499) String[] args = CommandLineUtil.argumentsToArray(cmd); @@ -292,7 +317,7 @@ public class LaunchUtils { Process process = null; Job timeoutJob = null; try { - process = ProcessFactory.getFactory().exec(args, getLaunchEnvironment(configuration)); + process = ProcessFactory.getFactory().exec(args, launchEnvironment); // Start a timeout job to make sure we don't get stuck waiting for // an answer from a gdb that is hanging -- cgit v1.2.3