Add gcstress option to SuperILC (#1446)
authorJan Vorlicek <janvorli@microsoft.com>
Thu, 9 Jan 2020 17:58:34 +0000 (18:58 +0100)
committerGitHub <noreply@github.com>
Thu, 9 Jan 2020 17:58:34 +0000 (18:58 +0100)
* Add gcstress option to SuperILC

This option allows executing tests with gcstress mode set to a passed
in value.
I have also added additional fixes for race issues with _logWriter.

src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolderSet.cs
src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs
src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs
src/coreclr/src/tools/ReadyToRun.SuperIlc/CompilerRunner.cs
src/coreclr/src/tools/ReadyToRun.SuperIlc/ProcessRunner.cs

index 51c5da6..291a735 100644 (file)
@@ -713,6 +713,7 @@ namespace ReadyToRun.SuperIlc
             logWriter.WriteLine($"Version bubble:   {(_options.LargeBubble ? "input + all reference assemblies" : "single assembly")}");
             logWriter.WriteLine($"Input folder:     {_options.InputDirectory?.FullName}");
             logWriter.WriteLine($"CORE_ROOT:        {_options.CoreRootDirectory?.FullName}");
+            logWriter.WriteLine($"GC stress mode:   {(!string.IsNullOrEmpty(_options.GCStress) ? _options.GCStress : "None")}");
             logWriter.WriteLine($"Total folders:    {_buildFolders.Count()}");
             logWriter.WriteLine($"Blocked w/issues: {_buildFolders.Count(folder => folder.IsBlockedWithIssue)}");
             int foldersToBuild = FoldersToBuild.Count();
index 0bb6f95..684d18a 100644 (file)
@@ -36,11 +36,12 @@ namespace ReadyToRun.SuperIlc
         public FileInfo[] IssuesPath { get; set; }
         public FileInfo R2RDumpPath { get; set; }
         public FileInfo CrossgenResponseFile { get; set; }
-        public DirectoryInfo[] RewriteOldPath { get;set; }
-        public DirectoryInfo[] RewriteNewPath { get;set; }
+        public DirectoryInfo[] RewriteOldPath { get; set; }
+        public DirectoryInfo[] RewriteNewPath { get; set; }
         public bool MeasurePerf { get; set; }
         public string InputFileSearchString { get; set; }
         public string ConfigurationSuffix => (Release ? "-ret.out" : "-chk.out");
+        public string GCStress { get; set; }
 
         public IEnumerable<string> ReferencePaths()
         {
index dc90efc..8ec905c 100644 (file)
@@ -84,6 +84,7 @@ namespace ReadyToRun.SuperIlc
                         CompilationTimeoutMinutes(),
                         ExecutionTimeoutMinutes(),
                         R2RDumpPath(),
+                        GCStress(),
                     },
                     handler: CommandHandler.Create<BuildOptions>(CompileSubtreeCommand.CompileSubtree));
 
@@ -232,6 +233,9 @@ namespace ReadyToRun.SuperIlc
             Option InputFileSearchString() =>
                 new Option(new[] { "--input-file-search-string", "-input-file" }, "Search string for input files in the input directory", new Argument<string>());
 
+            Option GCStress() =>
+                new Option(new[] { "--gcstress" }, "Run tests with the specified GC stress level enabled (the argument value is in hex)", new Argument<string>());
+
             //
             // compile-nuget specific options
             //
index 67317d3..24320af 100644 (file)
@@ -8,6 +8,7 @@ using System.Diagnostics;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Text;
+using Microsoft.Build.Logging;
 
 namespace ReadyToRun.SuperIlc
 {
@@ -137,6 +138,11 @@ namespace ReadyToRun.SuperIlc
         {
             ProcessParameters processParameters = new ProcessParameters();
 
+            if (!string.IsNullOrEmpty(_options.GCStress))
+            {
+                processParameters.EnvironmentOverrides["COMPlus_GCStress"] = _options.GCStress;
+            }
+
             if (_options.ExecutionTimeoutMinutes != 0)
             {
                 processParameters.TimeoutMilliseconds = _options.ExecutionTimeoutMinutes * 60 * 1000;
@@ -294,7 +300,8 @@ namespace ReadyToRun.SuperIlc
 
         public override ProcessParameters Construct()
         {
-            return _runner.ScriptExecutionProcess(_outputRoot, _scriptPath, _modules, _folders);
+            ProcessParameters processParameters = _runner.ScriptExecutionProcess(_outputRoot, _scriptPath, _modules, _folders);
+            return processParameters;
         }
     }
 
index b989140..bfe504b 100644 (file)
@@ -101,7 +101,7 @@ public class ProcessRunner : IDisposable
     /// </summary>
     private int _state;
 
-    private TextWriter _logWriter;
+    private volatile TextWriter _logWriter;
 
     private CancellationTokenSource _cancellationTokenSource;
 
@@ -252,37 +252,38 @@ public class ProcessRunner : IDisposable
         }
     }
 
-    private void StandardOutputEventHandler(object sender, DataReceivedEventArgs eventArgs)
+    private void WriteLog(string message)
     {
-        string data = eventArgs?.Data;
         TextWriter logWriter = _logWriter;
-        if (!string.IsNullOrEmpty(data) && logWriter != null)
+
+        if (logWriter != null)
         {
             lock (logWriter)
             {
                 if (_logWriter != null)
                 {
-                    // The logWriter was not disposed yet
-                    logWriter.WriteLine(data);
+                    // The logWriter was not destroyed yet
+                    _logWriter.WriteLine(message);
                 }
             }
         }
     }
 
+    private void StandardOutputEventHandler(object sender, DataReceivedEventArgs eventArgs)
+    {
+        string data = eventArgs?.Data;
+        if (!string.IsNullOrEmpty(data))
+        {
+            WriteLog(data);
+        }
+    }
+
     private void StandardErrorEventHandler(object sender, DataReceivedEventArgs eventArgs)
     {
         string data = eventArgs?.Data;
-        TextWriter logWriter = _logWriter;
-        if (!string.IsNullOrEmpty(data) && logWriter != null)
+        if (!string.IsNullOrEmpty(data))
         {
-            lock (logWriter)
-            {
-                if (_logWriter != null)
-                {
-                    // The logWriter was not disposed yet
-                    logWriter.WriteLine(data);
-                }
-            }
+            WriteLog(data);
         }
     }
 
@@ -310,7 +311,7 @@ public class ProcessRunner : IDisposable
         }
         _processInfo.ExitCode = (_processInfo.TimedOut ? TimeoutExitCode : _process.ExitCode);
         _processInfo.Succeeded = (!_processInfo.TimedOut && _processInfo.ExitCode == _processInfo.Parameters.ExpectedExitCode);
-        _logWriter.WriteLine(">>>>");
+        WriteLog(">>>>");
 
         if (!_processInfo.Succeeded)
         {
@@ -323,7 +324,8 @@ public class ProcessRunner : IDisposable
         {
             string successMessage = linePrefix + $"succeeded in {_processInfo.DurationMilliseconds} msecs";
 
-            _logWriter.WriteLine(successMessage);
+            WriteLog(successMessage);
+
             Console.WriteLine(successMessage + $": {processSpec}");
             _processInfo.Succeeded = true;
         }
@@ -343,7 +345,9 @@ public class ProcessRunner : IDisposable
                 }
                 failureMessage += $", expected {_processInfo.Parameters.ExpectedExitCode}";
             }
-            _logWriter.WriteLine(failureMessage);
+
+            WriteLog(failureMessage);
+
             Console.Error.WriteLine(failureMessage + $": {processSpec}");
         }
 
@@ -351,7 +355,10 @@ public class ProcessRunner : IDisposable
 
         _processInfo.Finished = true;
 
-        _logWriter.Flush();
+        lock (_logWriter)
+        {
+            _logWriter.Flush();
+        }
 
         CleanupLogWriter();