Skip to content

[Helix] Crash/hang prototype #25010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .azure/pipelines/helix-matrix.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# We only want to run full helix matrix on master
pr: none
pr:
autoCancel: true
branches:
include:
- '*'
trigger: none
schedules:
- cron: "0 */12 * * *"
Expand Down
28 changes: 20 additions & 8 deletions eng/helix/content/RunTests/TestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,8 @@ public async Task<int> RunTestsAsync()
{
// Timeout test run 5 minutes before the Helix job would timeout
var cts = new CancellationTokenSource(Options.Timeout.Subtract(TimeSpan.FromMinutes(5)));
var commonTestArgs = $"test {Options.Target} --logger:xunit --logger:\"console;verbosity=normal\" --blame \"CollectHangDump;TestTimeout=5m\"";
var diagLog = Path.Combine(Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT"), "vstest.log");
var commonTestArgs = $"test {Options.Target} --diag:{diagLog} --logger:xunit --logger:\"console;verbosity=normal\" --blame \"CollectHangDump;TestTimeout=5m\"";
if (Options.Quarantined)
{
Console.WriteLine("Running quarantined tests.");
Expand Down Expand Up @@ -312,31 +313,42 @@ public void UploadResults()
// Combine the directory name + log name for the copied log file name to avoid overwriting duplicate test names in different test projects
var logName = $"{Path.GetFileName(Path.GetDirectoryName(file))}_{Path.GetFileName(file)}";
Console.WriteLine($"Copying: {file} to {Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, logName)}");
// Need to copy to HELIX_WORKITEM_UPLOAD_ROOT and HELIX_WORKITEM_UPLOAD_ROOT/../ in order for Azure Devops attachments to link properly and for Helix to store the logs
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, logName));
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, "..", logName));
}
}
else
{
Console.WriteLine("No logs found in artifacts/log");
}
Console.WriteLine($"Copying TestResults/**/*.dmp to {HELIX_WORKITEM_UPLOAD_ROOT}/");
Console.WriteLine($"Copying TestResults/**/*.trx to {HELIX_WORKITEM_UPLOAD_ROOT}/");
if (Directory.Exists("TestResults"))
{
foreach (var file in Directory.EnumerateFiles("TestResults", "*.dmp", SearchOption.AllDirectories))
foreach (var file in Directory.EnumerateFiles("TestResults", "*.trx", SearchOption.AllDirectories))
{
var fileName = Path.GetFileName(file);
Console.WriteLine($"Copying: {file} to {Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, fileName)}");
// Need to copy to HELIX_WORKITEM_UPLOAD_ROOT and HELIX_WORKITEM_UPLOAD_ROOT/../ in order for Azure Devops attachments to link properly and for Helix to store the logs
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, fileName));
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, "..", fileName));
}
}
else
{
Console.WriteLine("No dmps found in TestResults");
Console.WriteLine("No trx found in TestResults");
}
Console.WriteLine($"Copying TestResults/**/Sequence*.xml to {HELIX_WORKITEM_UPLOAD_ROOT}/");
if (Directory.Exists("TestResults"))
{
foreach (var file in Directory.EnumerateFiles("TestResults", "Sequence*.xml", SearchOption.AllDirectories))
{
var fileName = Path.GetFileName(file);
Console.WriteLine($"Copying: {file} to {Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, fileName)}");
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, fileName));
}
}
else
{
Console.WriteLine("No sequence xml file found in TestResults");
}

}
}
}
1 change: 1 addition & 0 deletions eng/helix/content/runtests.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ set DOTNET_ROOT=%DOTNET_HOME%\%$arch%
set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
set DOTNET_MULTILEVEL_LOOKUP=0
set DOTNET_CLI_HOME=%CD%\home%random%
set VSTEST_DUMP_PATH=%HELIX_DUMP_FOLDER%

set "PATH=%DOTNET_ROOT%;%PATH%;%HELIX_CORRELATION_PAYLOAD%\node\bin"
echo Set path to: "%PATH%"
Expand Down
4 changes: 4 additions & 0 deletions eng/helix/content/runtests.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#!/usr/bin/env bash

echo Verifying ulimit -c
ulimit -c

dotnet_sdk_version="$2"
dotnet_runtime_version="$3"

Expand All @@ -24,6 +27,7 @@ export DOTNET_MULTILEVEL_LOOKUP=0
export DOTNET_CLI_HOME="$DIR/.home$RANDOM"

export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
export VSTEST_DUMP_PATH=$HELIX_DUMP_FOLDER

RESET="\033[0m"
RED="\033[0;31m"
Expand Down
58 changes: 58 additions & 0 deletions src/Identity/src/Common/AssemblyResolution.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET472

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Microsoft.DotNet
{
internal static class AssemblyResolution
{
internal static TaskLoggingHelper Log;

public static void Initialize()
{
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
}

private static Assembly AssemblyResolve(object sender, ResolveEventArgs args)
{
var name = new AssemblyName(args.Name);

if (!name.Name.Equals("System.Collections.Immutable", StringComparison.OrdinalIgnoreCase))
{
return null;
}

var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "System.Collections.Immutable.dll");

Assembly sci;
try
{
sci = Assembly.LoadFile(fullPath);
}
catch (Exception e)
{
Log?.LogWarning($"AssemblyResolve: exception while loading '{fullPath}': {e.Message}");
return null;
}

if (name.Version <= sci.GetName().Version)
{
Log?.LogMessage(MessageImportance.Low, $"AssemblyResolve: loaded '{fullPath}' to {AppDomain.CurrentDomain.FriendlyName}");
return sci;
}

return null;
}
}
}

#endif
109 changes: 109 additions & 0 deletions src/Identity/src/Common/AssemblyResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace Microsoft.DotNet.Build.Common.Desktop
{
/// <summary>
/// Used to enable app-local assembly unification.
/// </summary>
internal static class AssemblyResolver
{
static AssemblyResolver()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}

/// <summary>
/// Call to enable the assembly resolver for the current AppDomain.
/// </summary>
public static void Enable()
{
// intentionally empty. This is just meant to ensure the static constructor
// has run.
}

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
// apply any existing policy
AssemblyName referenceName = new AssemblyName(AppDomain.CurrentDomain.ApplyPolicy(args.Name));

string fileName = referenceName.Name + ".dll";
string assemblyPath = null;
string probingPath = null;
Assembly assm = null;

// look next to requesting assembly
assemblyPath = args.RequestingAssembly?.Location;
if (!String.IsNullOrEmpty(assemblyPath))
{
probingPath = Path.Combine(Path.GetDirectoryName(assemblyPath), fileName);
Debug.WriteLine($"Considering {probingPath} based on RequestingAssembly");
if (Probe(probingPath, referenceName.Version, out assm))
{
return assm;
}
}

// look next to the executing assembly
assemblyPath = Assembly.GetExecutingAssembly().Location;
if (!String.IsNullOrEmpty(assemblyPath))
{
probingPath = Path.Combine(Path.GetDirectoryName(assemblyPath), fileName);

Debug.WriteLine($"Considering {probingPath} based on ExecutingAssembly");
if (Probe(probingPath, referenceName.Version, out assm))
{
return assm;
}
}

// look in AppDomain base directory
probingPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
Debug.WriteLine($"Considering {probingPath} based on BaseDirectory");
if (Probe(probingPath, referenceName.Version, out assm))
{
return assm;
}

// look in current directory
Debug.WriteLine($"Considering {fileName}");
if (Probe(fileName, referenceName.Version, out assm))
{
return assm;
}

return null;
}

/// <summary>
/// Considers a path to load for satisfying an assembly ref and loads it
/// if the file exists and version is sufficient.
/// </summary>
/// <param name="filePath">Path to consider for load</param>
/// <param name="minimumVersion">Minimum version to consider</param>
/// <param name="assembly">loaded assembly</param>
/// <returns>true if assembly was loaded</returns>
private static bool Probe(string filePath, Version minimumVersion, out Assembly assembly)
{
if (File.Exists(filePath))
{
AssemblyName name = AssemblyName.GetAssemblyName(filePath);

if (name.Version >= minimumVersion)
{
assembly = Assembly.Load(name);
return true;
}
}

assembly = null;
return false;
}
}
}
16 changes: 16 additions & 0 deletions src/Identity/src/Common/BuildTask.Desktop.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.DotNet.Build.Common.Desktop;

namespace Microsoft.DotNet.Build.Tasks
{
public partial class BuildTask
{
static BuildTask()
{
AssemblyResolver.Enable();
}
}
}
Loading