Beispiel #1
0
 private void LogDebuggerErrors()
 {
     if (_errorStream != null)
     {
         while (!_streamReadPidCancellationTokenSource.IsCancellationRequested)
         {
             string line = this.GetLineFromStream(_errorStream, _streamReadPidCancellationTokenSource.Token);
             if (line == null)
             {
                 break;
             }
             Logger?.WriteTextBlock("dbgerr:", line);
         }
     }
 }
Beispiel #2
0
        /// <summary>
        /// Exception filter function used to report exceptions to telemetry. This **ALWAYS** returns 'true'.
        /// </summary>
        /// <param name="currentException">The current exception which is about to be caught.</param>
        /// <param name="logger">For logging messages</param>
        /// <param name="reportOnlyCorrupting">If true, only corrupting exceptions are reported</param>
        /// <returns>true</returns>
        public static bool BeforeCatch(Exception currentException, Logger logger, bool reportOnlyCorrupting)
        {
            if (reportOnlyCorrupting && !IsCorruptingException(currentException))
            {
                return(true); // ignore non-corrupting exceptions
            }

            try
            {
                HostTelemetry.ReportCurrentException(currentException, "Microsoft.MIDebugEngine");

                logger?.WriteLine("EXCEPTION: " + currentException.GetType());
                logger?.WriteTextBlock("EXCEPTION: ", currentException.StackTrace);
            }
            catch
            {
                // If anything goes wrong, ignore it. We want to report the original exception, not a telemetry problem
            }

            return(true);
        }
Beispiel #3
0
        public static LaunchOptions GetInstance(string registryRoot, string exePath, string args, string dir, string options, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine)
        {
            if (string.IsNullOrWhiteSpace(exePath))
            {
                throw new ArgumentNullException("exePath");
            }

            if (string.IsNullOrWhiteSpace(options))
            {
                throw new InvalidLaunchOptionsException(MICoreResources.Error_StringIsNullOrEmpty);
            }

            if (string.IsNullOrEmpty(registryRoot))
            {
                throw new ArgumentNullException("registryRoot");
            }

            Logger.WriteTextBlock("LaunchOptions", options);

            LaunchOptions launchOptions      = null;
            Guid          clsidLauncher      = Guid.Empty;
            object        launcherXmlOptions = null;

            try
            {
                using (XmlReader reader = OpenXml(options))
                {
                    switch (reader.LocalName)
                    {
                    case "LocalLaunchOptions":
                    {
                        var serializer       = new Microsoft.Xml.Serialization.GeneratedAssembly.LocalLaunchOptionsSerializer();
                        var xmlLaunchOptions = (Xml.LaunchOptions.LocalLaunchOptions)Deserialize(serializer, reader);
                        launchOptions = LocalLaunchOptions.CreateFromXml(xmlLaunchOptions);
                    }
                    break;

                    case "SerialPortLaunchOptions":
                    {
                        var serializer       = new Microsoft.Xml.Serialization.GeneratedAssembly.SerialPortLaunchOptionsSerializer();
                        var xmlLaunchOptions = (Xml.LaunchOptions.SerialPortLaunchOptions)Deserialize(serializer, reader);
                        launchOptions = SerialLaunchOptions.CreateFromXml(xmlLaunchOptions);
                    }
                    break;

                    case "PipeLaunchOptions":
                    {
                        var serializer       = new Microsoft.Xml.Serialization.GeneratedAssembly.PipeLaunchOptionsSerializer();
                        var xmlLaunchOptions = (Xml.LaunchOptions.PipeLaunchOptions)Deserialize(serializer, reader);
                        launchOptions = PipeLaunchOptions.CreateFromXml(xmlLaunchOptions);
                    }
                    break;

                    case "TcpLaunchOptions":
                    {
                        var serializer       = new Microsoft.Xml.Serialization.GeneratedAssembly.TcpLaunchOptionsSerializer();
                        var xmlLaunchOptions = (Xml.LaunchOptions.TcpLaunchOptions)Deserialize(serializer, reader);
                        launchOptions = TcpLaunchOptions.CreateFromXml(xmlLaunchOptions);
                    }
                    break;

                    case "IOSLaunchOptions":
                    {
                        var serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.IOSLaunchOptionsSerializer();
                        launcherXmlOptions = Deserialize(serializer, reader);
                        clsidLauncher      = new Guid("316783D1-1824-4847-B3D3-FB048960EDCF");
                    }
                    break;

                    case "AndroidLaunchOptions":
                    {
                        var serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.AndroidLaunchOptionsSerializer();
                        launcherXmlOptions = Deserialize(serializer, reader);
                        clsidLauncher      = new Guid("C9A403DA-D3AA-4632-A572-E81FF6301E9B");
                    }
                    break;

                    default:
                    {
                        throw new XmlException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_UnknownXmlElement, reader.LocalName));
                    }
                    }

                    // Read any remaining bits of XML to catch other errors
                    while (reader.NodeType != XmlNodeType.None)
                    {
                        reader.Read();
                    }
                }
            }
            catch (XmlException e)
            {
                throw new InvalidLaunchOptionsException(e.Message);
            }

            if (clsidLauncher != Guid.Empty)
            {
                launchOptions = ExecuteLauncher(registryRoot, clsidLauncher, exePath, args, dir, launcherXmlOptions, eventCallback, targetEngine);
            }

            if (targetEngine == TargetEngine.Native)
            {
                if (launchOptions.ExePath == null)
                {
                    launchOptions.ExePath = exePath;
                }
            }

            if (string.IsNullOrEmpty(launchOptions.ExeArguments))
            {
                launchOptions.ExeArguments = args;
            }

            if (string.IsNullOrEmpty(launchOptions.WorkingDirectory))
            {
                launchOptions.WorkingDirectory = dir;
            }

            if (launchOptions._setupCommands == null)
            {
                launchOptions._setupCommands = new List <LaunchCommand>(capacity: 0).AsReadOnly();
            }

            launchOptions._initializationComplete = true;
            return(launchOptions);
        }
Beispiel #4
0
        public override async void Init(ITransportCallback transportCallback, LaunchOptions options, Logger logger, HostWaitLoop waitLoop = null)
        {
            LocalLaunchOptions localOptions = options as LocalLaunchOptions;

            Encoding encNoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);

            string        commandPipeName;
            string        outputPipeName;
            string        pidPipeName;
            List <string> cmdArgs = new List <string>();

            string windowtitle = FormattableString.Invariant($"cppdbg: {Path.GetFileName(options.ExePath)}");

            if (PlatformUtilities.IsWindows())
            {
                // Create Windows Named pipes
                commandPipeName = Utilities.GetMIEngineTemporaryFilename("In");
                outputPipeName  = Utilities.GetMIEngineTemporaryFilename("Out");
                pidPipeName     = Utilities.GetMIEngineTemporaryFilename("Pid");
                string errorPipeName = Utilities.GetMIEngineTemporaryFilename("Error");

                NamedPipeServerStream inputToDebugger    = new NamedPipeServerStream(commandPipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte);
                NamedPipeServerStream outputFromDebugger = new NamedPipeServerStream(outputPipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte);
                NamedPipeServerStream errorFromDebugger  = new NamedPipeServerStream(errorPipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte);
                NamedPipeServerStream pidPipe            = new NamedPipeServerStream(pidPipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte);

                _pidReader = new StreamReader(pidPipe, encNoBom, false, UnixUtilities.StreamBufferSize);

                string thisModulePath = typeof(RunInTerminalTransport).GetTypeInfo().Assembly.ManifestModule.FullyQualifiedName;
                string launchCommand  = Path.Combine(Path.GetDirectoryName(thisModulePath), "WindowsDebugLauncher.exe");

                if (!File.Exists(launchCommand))
                {
                    string errorMessage = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_InternalFileMissing, launchCommand);
                    transportCallback.OnStdErrorLine(errorMessage);
                    transportCallback.OnDebuggerProcessExit(null);
                    return;
                }

                cmdArgs.Add(launchCommand);
                cmdArgs.Add("--stdin=" + commandPipeName);
                cmdArgs.Add("--stdout=" + outputPipeName);
                cmdArgs.Add("--stderr=" + errorPipeName);
                cmdArgs.Add("--pid=" + pidPipeName);
                cmdArgs.Add("--dbgExe=" + localOptions.MIDebuggerPath);
                cmdArgs.Add(localOptions.GetMiDebuggerArgs());

                _waitForConnection = Task.WhenAll(
                    inputToDebugger.WaitForConnectionAsync(),
                    outputFromDebugger.WaitForConnectionAsync(),
                    errorFromDebugger.WaitForConnectionAsync(),
                    pidPipe.WaitForConnectionAsync());

                _commandStream = new StreamWriter(inputToDebugger, encNoBom);
                _outputStream  = new StreamReader(outputFromDebugger, encNoBom, false, UnixUtilities.StreamBufferSize);
                _errorStream   = new StreamReader(errorFromDebugger, encNoBom, false, UnixUtilities.StreamBufferSize);
            }
            else
            {
                // Do Linux style pipes
                commandPipeName = UnixUtilities.MakeFifo(identifier: "In", logger: logger);
                outputPipeName  = UnixUtilities.MakeFifo(identifier: "Out", logger: logger);
                pidPipeName     = UnixUtilities.MakeFifo(identifier: "Pid", logger: logger);

                // Create filestreams
                FileStream stdInStream  = new FileStream(commandPipeName, FileMode.Open);
                FileStream stdOutStream = new FileStream(outputPipeName, FileMode.Open);
                _pidReader = new StreamReader(new FileStream(pidPipeName, FileMode.Open), encNoBom, false, UnixUtilities.StreamBufferSize);

                string debuggerCmd = UnixUtilities.GetDebuggerCommand(localOptions);

                // Default working directory is next to the app
                string debuggeeDir;
                if (Path.IsPathRooted(options.ExePath) && File.Exists(options.ExePath))
                {
                    debuggeeDir = Path.GetDirectoryName(options.ExePath);
                }
                else
                {
                    // If we don't know where the app is, default to HOME, and if we somehow can't get that, go with the root directory.
                    debuggeeDir = Environment.GetEnvironmentVariable("HOME");
                    if (string.IsNullOrEmpty(debuggeeDir))
                    {
                        debuggeeDir = "/";
                    }
                }

                string dbgCmdScript          = Path.Combine(Path.GetTempPath(), Utilities.GetMIEngineTemporaryFilename(identifier: "Cmd"));
                string launchDebuggerCommand = UnixUtilities.LaunchLocalDebuggerCommand(
                    debuggeeDir,
                    commandPipeName,
                    outputPipeName,
                    pidPipeName,
                    dbgCmdScript,
                    debuggerCmd,
                    localOptions.GetMiDebuggerArgs());

                logger?.WriteTextBlock("DbgCmd:", launchDebuggerCommand);

                using (FileStream dbgCmdStream = new FileStream(dbgCmdScript, FileMode.CreateNew))
                    using (StreamWriter dbgCmdWriter = new StreamWriter(dbgCmdStream, encNoBom)
                    {
                        AutoFlush = true
                    })
                    {
                        dbgCmdWriter.WriteLine("#!/bin/sh");
                        dbgCmdWriter.Write(launchDebuggerCommand);
                        dbgCmdWriter.Flush();
                    }

                if (PlatformUtilities.IsOSX())
                {
                    string osxLaunchScript = GetOSXLaunchScript();

                    // Call osascript with a path to the AppleScript. The apple script takes 2 parameters: a title for the terminal and the launch script.
                    cmdArgs.Add("/usr/bin/osascript");
                    cmdArgs.Add(osxLaunchScript);
                    cmdArgs.Add(FormattableString.Invariant($"\"{windowtitle}\""));
                    cmdArgs.Add(FormattableString.Invariant($"sh {dbgCmdScript} ;")); // needs a semicolon because this command is running through the launchscript.
                }
                else
                {
                    cmdArgs.Add("sh");
                    cmdArgs.Add(dbgCmdScript);
                }

                _outputStream  = new StreamReader(stdOutStream, encNoBom, false, UnixUtilities.StreamBufferSize);
                _commandStream = new StreamWriter(stdInStream, encNoBom);
            }

            RunInTerminalLauncher launcher = new RunInTerminalLauncher(windowtitle, localOptions.Environment);

            launcher.Launch(
                cmdArgs,
                localOptions.UseExternalConsole,
                LaunchSuccess,
                (error) =>
            {
                transportCallback.OnStdErrorLine(error);
                throw new InvalidOperationException(error);
            },
                logger);
            logger?.WriteLine("Wait for connection completion.");

            if (_waitForConnection != null)
            {
                // Add a timeout for waiting for connection - 20 seconds
                Task  waitOrTimeout = Task.WhenAny(_waitForConnection, Task.Delay(20000));
                await waitOrTimeout;
                if (waitOrTimeout.Status != TaskStatus.RanToCompletion)
                {
                    string errorMessage = String.Format(CultureInfo.CurrentCulture, MICoreResources.Error_DebuggerInitializeFailed_NoStdErr, "WindowsDebugLauncher.exe");
                    transportCallback.OnStdErrorLine(errorMessage);
                    transportCallback.OnDebuggerProcessExit(null);
                    return;
                }
            }

            base.Init(transportCallback, options, logger, waitLoop);
        }