예제 #1
0
    /// <summary>
    /// Run a debuggee and create a dump.
    /// </summary>
    /// <param name="config">test configuration</param>
    /// <param name="output">output instance</param>
    /// <param name="testName">name of test</param>
    /// <param name="debuggeeName">debuggee name</param>
    /// <param name="debuggeeArguments">optional args to pass to debuggee</param>
    /// <param name="useCreateDump">if true, use "createdump" to generate core dump</param>
    public static async Task CreateDump(TestConfiguration config, ITestOutputHelper output, string testName, string debuggeeName,
                                        string debuggeeArguments = null, bool useCreateDump = true)
    {
        Directory.CreateDirectory(config.DebuggeeDumpOutputRootDir());

        if (!config.CreateDumpExists || !useCreateDump || config.GenerateDumpWithLLDB() || config.GenerateDumpWithGDB())
        {
            using (SOSRunner runner = await SOSRunner.StartDebugger(config, output, testName, debuggeeName, debuggeeArguments, Options.GenerateDump))
            {
                try
                {
                    await runner.LoadSosExtension();

                    string command = null;
                    switch (runner.Debugger)
                    {
                    case SOSRunner.NativeDebugger.Cdb:
                        await runner.ContinueExecution();

                        // On desktop create triage dump. On .NET Core, create full dump.
                        command = config.IsDesktop ? ".dump /o /mshuRp %DUMP_NAME%" : ".dump /o /ma %DUMP_NAME%";
                        break;

                    case SOSRunner.NativeDebugger.Gdb:
                        command = "generate-core-file %DUMP_NAME%";
                        break;

                    case SOSRunner.NativeDebugger.Lldb:
                        await runner.ContinueExecution();

                        command = "sos CreateDump %DUMP_NAME%";
                        break;

                    default:
                        throw new Exception(runner.Debugger.ToString() + " does not support creating dumps");
                    }

                    await runner.RunCommand(command);

                    await runner.QuitDebugger();
                }
                catch (Exception ex)
                {
                    runner.WriteLine(ex.ToString());
                    throw;
                }
            }
        }
        else
        {
            TestRunner.OutputHelper outputHelper = null;
            try
            {
                // Setup the logging from the options in the config file
                outputHelper = TestRunner.ConfigureLogging(config, output, testName);

                // Restore and build the debuggee. The debuggee name is lower cased because the
                // source directory name has been lowercased by the build system.
                DebuggeeConfiguration debuggeeConfig = await DebuggeeCompiler.Execute(config, debuggeeName, outputHelper);

                outputHelper.WriteLine("Starting {0}", testName);
                outputHelper.WriteLine("{");

                // Get the full debuggee launch command line (includes the host if required)
                string exePath   = debuggeeConfig.BinaryExePath;
                var    arguments = new StringBuilder();
                if (!string.IsNullOrWhiteSpace(config.HostExe))
                {
                    exePath = config.HostExe;
                    if (!string.IsNullOrWhiteSpace(config.HostArgs))
                    {
                        arguments.Append(config.HostArgs);
                        arguments.Append(" ");
                    }
                    arguments.Append(debuggeeConfig.BinaryExePath);
                }
                if (!string.IsNullOrWhiteSpace(debuggeeArguments))
                {
                    arguments.Append(" ");
                    arguments.Append(debuggeeArguments);
                }

                // Run the debuggee with the createdump environment variables set to generate a coredump on unhandled exception
                var           testLogger    = new TestRunner.TestLogger(outputHelper.IndentedOutput);
                var           variables     = GenerateVariables(config, debuggeeConfig, Options.GenerateDump);
                ProcessRunner processRunner = new ProcessRunner(exePath, ReplaceVariables(variables, arguments.ToString())).
                                              WithLog(testLogger).
                                              WithTimeout(TimeSpan.FromMinutes(5)).
                                              WithEnvironmentVariable("COMPlus_DbgEnableMiniDump", "1").
                                              WithEnvironmentVariable("COMPlus_DbgMiniDumpName", ReplaceVariables(variables, "%DUMP_NAME%"));

                processRunner.Start();

                // Wait for the debuggee to finish
                await processRunner.WaitForExit();
            }
            catch (Exception ex)
            {
                // Log the exception
                outputHelper?.WriteLine(ex.ToString());
                throw;
            }
            finally
            {
                outputHelper?.WriteLine("}");
                outputHelper?.Dispose();
            }
        }
    }