Skip to content
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
35 changes: 35 additions & 0 deletions src/BenchmarkDotNet/Detectors/AppHostDetector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using BenchmarkDotNet.Extensions;
using System.Diagnostics;
using System.Reflection;

namespace BenchmarkDotNet.Detectors;

internal static class AppHostDetector
{
public static bool HasAppHost()
{
var entryAssembly = Assembly.GetEntryAssembly();

// Check NativeAOT
if (entryAssembly == null)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetEntryAssembly also returns null in test frameworks, so this doesn't even catch the issue you found.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetEntryAssembly also returns null in test frameworks

Is it able to provide code/environment that reproduce issue?

I've testes AppHostDetector.cs behavior on Windows with following combinations .
But it can't reproduce issue.

  • Use xUnit.v2/v3.
  • Use VSTest/MTP mode.
  • Run tests by using TestExplorer/dotnet run/run exe

As far as I've confirmed testhost.dll is resolved as entry assembly when using xunit.v2.
And test DLL is resolved when using xunit.v3.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my first prototype of #2682 I tried using it and found it to return null in the test framework. 35b0082#diff-3e3d929255c5bc775e61d756a968c3a994409c578dba06e5630745484c7ce62bR52-R54

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was using the old manual running multiple frameworks test project, which at the time was using an ancient version of xUnit, so maybe it's doesn't repro anymore. But it seems unreliable at least.

return false;

using var process = Process.GetCurrentProcess();
var processName = process.ProcessName;

// Check executed with `dotnet run`
if (processName.Equals("dotnet", StringComparison.OrdinalIgnoreCase))
return false;

// Check Single-file executable (AppHost is bundled)
if (entryAssembly.Location.IsBlank())
return true;

// Check entry assembly extension.
if (entryAssembly.Location.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
return true;

// Return false for unknown environment
return false;
}
}
14 changes: 12 additions & 2 deletions src/BenchmarkDotNet/Disassemblers/DisassemblyDiagnoser.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using BenchmarkDotNet.Analysers;
using BenchmarkDotNet.Analysers;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Detectors;
using BenchmarkDotNet.Disassemblers;
Expand Down Expand Up @@ -100,7 +100,7 @@ public async ValueTask HandleAsync(HostSignal signal, DiagnoserActionParameters
);
break;
case HostSignal.SeparateLogic when ShouldUseMonoDisassembler(benchmark):
var result = await monoDisassembler.Disassemble(benchmark, (MonoRuntime) benchmark.Job.Environment.Runtime!, cancellationToken).ConfigureAwait(false);
var result = await monoDisassembler.Disassemble(benchmark, (MonoRuntime)benchmark.Job.Environment.Runtime!, cancellationToken).ConfigureAwait(false);
results.Add(benchmark, result);
break;
}
Expand Down Expand Up @@ -174,6 +174,16 @@ public async IAsyncEnumerable<ValidationError> ValidateAsync(ValidationParameter
{
yield return new ValidationError(true, $"Only Windows and Linux are supported in DisassemblyDiagnoser without Mono. Current OS is {System.Runtime.InteropServices.RuntimeInformation.OSDescription}");
}

var isInProcess = benchmark.Job.Infrastructure.TryGetToolchain(out toolchain) && toolchain.IsInProcess;
if (isInProcess && OsDetector.IsMacOS() && AppHostDetector.HasAppHost())
{
// On macos environment, WriteDump API is used and it cause freeze when using AppHost with InProcessToolchain.
// https://github.com/dotnet/BenchmarkDotNet/issues/3076
var errorMessage = "DisassemblyDiagnoser is not supported on macos environment that using AppHost and InProcessToolchain. "
+ "Disable AppHost with '<UseAppHost>false</UseAppHost>' or use another toolchain";
yield return new ValidationError(true, errorMessage);
}
}
}

Expand Down