diff --git a/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs b/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs index 7d826969e87..2dbcd31ea0e 100644 --- a/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs +++ b/src/Build/BackEnd/Components/BuildRequestEngine/BuildRequestEngine.cs @@ -119,7 +119,7 @@ internal BuildRequestEngine() { _debugDumpState = Traits.Instance.DebugScheduler; _debugDumpPath = ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? DebugUtils.DebugDumpPath() + ? DebugUtils.DebugPath : Environment.GetEnvironmentVariable("MSBUILDDEBUGPATH"); _debugForceCaching = Environment.GetEnvironmentVariable("MSBUILDDEBUGFORCECACHING") == "1"; diff --git a/src/Build/BackEnd/Components/Scheduler/Scheduler.cs b/src/Build/BackEnd/Components/Scheduler/Scheduler.cs index 535fad8afc6..377e6805897 100644 --- a/src/Build/BackEnd/Components/Scheduler/Scheduler.cs +++ b/src/Build/BackEnd/Components/Scheduler/Scheduler.cs @@ -179,7 +179,7 @@ public Scheduler() { _debugDumpState = Traits.Instance.DebugScheduler; _debugDumpPath = ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? DebugUtils.DebugDumpPath() + ? DebugUtils.DebugPath : Environment.GetEnvironmentVariable("MSBUILDDEBUGPATH"); _schedulingUnlimitedVariable = Environment.GetEnvironmentVariable("MSBUILDSCHEDULINGUNLIMITED"); _nodeLimitOffset = 0; diff --git a/src/Shared/CommunicationsUtilities.cs b/src/Shared/CommunicationsUtilities.cs index 79175ba5a69..9f643cc6ea6 100644 --- a/src/Shared/CommunicationsUtilities.cs +++ b/src/Shared/CommunicationsUtilities.cs @@ -179,6 +179,13 @@ static internal int NodeConnectionTimeout /// internal static Dictionary GetEnvironmentVariables() { +#if !CLR2COMPATIBILITY + // The DebugUtils static constructor can set the MSBUILDDEBUGPATH environment variable to propagate the debug path to out of proc nodes. + // Need to ensure that constructor is called before this method returns in order to capture its env var write. + // Otherwise the env var is not captured and thus gets deleted when RequiestBuilder resets the environment based on the cached results of this method. + ErrorUtilities.VerifyThrowInternalNull(DebugUtils.DebugPath, nameof(DebugUtils.DebugPath)); +#endif + Dictionary table = new Dictionary(200, StringComparer.OrdinalIgnoreCase); // Razzle has 150 environment variables if (NativeMethodsShared.IsWindows) @@ -561,7 +568,7 @@ internal static void Trace(int nodeId, string format, params object[] args) Environment.GetEnvironmentVariable("MSBUILDDEBUGPATH"); #else ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? DebugUtils.DebugDumpPath() + ? DebugUtils.DebugPath : Environment.GetEnvironmentVariable("MSBUILDDEBUGPATH"); #endif diff --git a/src/Shared/Debugging/DebugUtils.cs b/src/Shared/Debugging/DebugUtils.cs index 03a12d7410c..03736d2ad73 100644 --- a/src/Shared/Debugging/DebugUtils.cs +++ b/src/Shared/Debugging/DebugUtils.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using Microsoft.Build.Utilities; using System; using System.Diagnostics; using System.IO; @@ -17,6 +18,25 @@ private enum NodeMode OutOfProcTaskHostNode } + static DebugUtils() + { + string environmentDebugPath = Environment.GetEnvironmentVariable("MSBUILDDEBUGPATH"); + var debugDirectory = environmentDebugPath ?? Path.Combine(Directory.GetCurrentDirectory(), "MSBuild_Logs"); + + if (Traits.Instance.DebugEngine) + { + FileUtilities.EnsureDirectoryExists(debugDirectory); + + // Out of proc nodes do not know the startup directory so set the environment variable for them. + if (string.IsNullOrWhiteSpace(environmentDebugPath)) + { + Environment.SetEnvironmentVariable("MSBUILDDEBUGPATH", debugDirectory); + } + } + + DebugPath = debugDirectory; + } + private static readonly Lazy ProcessNodeMode = new( () => { @@ -57,27 +77,20 @@ private static bool CurrentProcessMatchesDebugName() public static readonly bool ShouldDebugCurrentProcess = CurrentProcessMatchesDebugName(); - public static string DebugDumpPath() - { - var debugDirectory = Environment.GetEnvironmentVariable("MSBUILDDEBUGPATH") ?? Path.Combine(Directory.GetCurrentDirectory(), "MSBuild_Logs"); - FileUtilities.EnsureDirectoryExists(debugDirectory); - - return debugDirectory; - } + public static string DebugPath { get; } public static string FindNextAvailableDebugFilePath(string fileName) { var extension = Path.GetExtension(fileName); var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); - var debugRoot = DebugDumpPath(); - var fullPath = Path.Combine(debugRoot, fileName); + var fullPath = Path.Combine(DebugPath, fileName); var counter = 0; while (File.Exists(fullPath)) { fileName = $"{fileNameWithoutExtension}_{counter++}{extension}"; - fullPath = Path.Combine(debugRoot, fileName); + fullPath = Path.Combine(DebugPath, fileName); } return fullPath; diff --git a/src/Shared/ExceptionHandling.cs b/src/Shared/ExceptionHandling.cs index d95f1743456..8ba3e225520 100644 --- a/src/Shared/ExceptionHandling.cs +++ b/src/Shared/ExceptionHandling.cs @@ -51,7 +51,7 @@ private static string GetDebugDumpPath() Environment.GetEnvironmentVariable("MSBUILDDEBUGPATH"); #else ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_0) - ? DebugUtils.DebugDumpPath() + ? DebugUtils.DebugPath : Environment.GetEnvironmentVariable("MSBUILDDEBUGPATH"); #endif