Skip to content
Merged
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
97 changes: 63 additions & 34 deletions tracer/test/Datadog.Trace.TestHelpers/ProfilerHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// </copyright>

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Linq;
Expand All @@ -19,6 +20,8 @@ public class ProfilerHelper
.Concat(new[] { "dotnet", "iisexpress" })
.ToArray();

private static readonly object _lockObj = new();
private static readonly ConcurrentDictionary<string, bool> _corFlagsApplied = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
Copy link
Member

Choose a reason for hiding this comment

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

nit: should we ignore case 🤔 On Linux for example there could be two different samples with the same name, just different cases 😅 I don't think it's a problem in reality though

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually, we only change cor vars in Windows x86 net4, so I would keep it

private static string _corFlagsExe;

public static async Task<Process> StartProcessWithProfiler(
Expand Down Expand Up @@ -89,53 +92,79 @@ public static async Task<Process> StartProcessWithProfiler(

public static void SetCorFlags(string executable, ITestOutputHelper output, bool require32Bit)
{
var corFlagsExe = _corFlagsExe;
var setBit = require32Bit ? "/32BITREQ+" : "/32BITREQ-";
if (string.IsNullOrEmpty(corFlagsExe))
// Use the absolute path as the key to track which executables have been modified
var executablePath = Path.GetFullPath(executable);

if (_corFlagsApplied.TryGetValue(executablePath, out _))
{
return;
}

lock (_lockObj)
{
var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
var dotnetWindowsSdkToolsFolder = Path.Combine(programFiles, "Microsoft SDKs", "Windows", "v10.0A", "bin");
// check again to be safe
if (_corFlagsApplied.TryGetValue(executablePath, out _))
{
return;
}

output?.WriteLine($"Searching for CorFlags.exe in {dotnetWindowsSdkToolsFolder}");
if (Directory.Exists(dotnetWindowsSdkToolsFolder))
var corFlagsExe = _corFlagsExe;
var setBit = require32Bit ? "/32BITREQ+" : "/32BITREQ-";
if (string.IsNullOrEmpty(corFlagsExe))
{
// get sub directories, e.g.
// @"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8.1 Tools",
// @"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools",
foreach (var folder in Directory.EnumerateDirectories(dotnetWindowsSdkToolsFolder))
var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
var dotnetWindowsSdkToolsFolder = Path.Combine(programFiles, "Microsoft SDKs", "Windows", "v10.0A", "bin");

output?.WriteLine($"Searching for CorFlags.exe in {dotnetWindowsSdkToolsFolder}");
if (Directory.Exists(dotnetWindowsSdkToolsFolder))
{
var exe = Path.Combine(folder, "x64", "CorFlags.exe");
if (File.Exists(exe))
// get sub directories, e.g.
// @"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8.1 Tools",
// @"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools",
foreach (var folder in Directory.EnumerateDirectories(dotnetWindowsSdkToolsFolder))
{
corFlagsExe = exe;
break;
var exe = Path.Combine(folder, "x64", "CorFlags.exe");
if (File.Exists(exe))
{
corFlagsExe = exe;
break;
}
}
}
}

if (!string.IsNullOrEmpty(corFlagsExe))
{
Interlocked.Exchange(ref _corFlagsExe, corFlagsExe);
output?.WriteLine($"CorFlags.exe found at {corFlagsExe}");
if (!string.IsNullOrEmpty(corFlagsExe))
{
Interlocked.Exchange(ref _corFlagsExe, corFlagsExe);
output?.WriteLine($"CorFlags.exe found at {corFlagsExe}");
}
else
{
throw new Exception($"Could not find CorFlags.exe so unable to set {setBit}");
}
}
else

output?.WriteLine($"Updating {Path.GetFileName(executable)} using {setBit}");
var opts = new ProcessStartInfo(corFlagsExe, $"\"{executable}\" {setBit} /force")
{
throw new Exception($"Could not find CorFlags.exe so unable to set {setBit}");
}
}
CreateNoWindow = true,
UseShellExecute = false
};

output?.WriteLine($"Updating {Path.GetFileName(executable)} using {setBit}");
var opts = new ProcessStartInfo(corFlagsExe, $"\"{executable}\" {setBit} /force")
{
CreateNoWindow = true,
UseShellExecute = false
};
using (var process = Process.Start(opts))
{
if (process == null)
{
throw new Exception("Failed to start CorFlags process.");
}

var executedSuccessfully = Process.Start(opts).WaitForExit(20_000);
var exited = process.WaitForExit(20_000);
if (!exited)
{
throw new Exception($"Error setting CorFlags.exe {Path.GetFileName(executable)} {setBit}");
}
}

if (!executedSuccessfully)
{
throw new Exception($"Error setting CorFlags.exe {Path.GetFileName(executable)} {setBit}");
_corFlagsApplied.TryAdd(executablePath, true);
}
}
}
Expand Down
Loading