From 238cd860d7a146e59c0e74aef7946fd91c1981df Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Mon, 25 Aug 2025 19:48:44 +0200 Subject: [PATCH 1/6] fix sidecar for legacy architecture and runtime --- .../BackEnd/TaskHostFactory_Tests.cs | 78 ++++++++++++++++++- .../NodeProviderOutOfProcTaskHost.cs | 22 +++++- src/Shared/CommunicationsUtilities.cs | 2 +- 3 files changed, 96 insertions(+), 6 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs b/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs index 3e2ddc21569..86a50d10ea3 100644 --- a/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs +++ b/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs @@ -115,7 +115,7 @@ public void TaskNodesDieAfterBuild(bool taskHostFactorySpecified, bool envVariab /// can coexist in the same build and operate independently. /// [Fact] - public void TransientandSidecarNodeCanCoexist() + public void TransientAndSidecarNodeCanCoexist() { using (TestEnvironment env = TestEnvironment.Create(_output)) { @@ -182,6 +182,82 @@ public void TransientandSidecarNodeCanCoexist() } } + /// + /// Verifies that node reuse is disabled when using CLR2 runtime. + /// + [Fact] + public void NodeReuseDisabledForCLR2Runtime() + { + using (TestEnvironment env = TestEnvironment.Create(_output)) + { + using ProcessTracker processTracker = new(); + { + string clr2TaskProject = $@" + + + + + + + + + + + + +"; + + TransientTestFile project = env.CreateFile("clr2Project.csproj", clr2TaskProject); + + // Enable node reuse globally and force out-of-proc execution + env.SetEnvironmentVariable("MSBUILDENABLENODEREUSE", "1"); + env.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1"); + + ProjectInstance projectInstance = new(project.Path); + projectInstance.Build().ShouldBeTrue(); + + string firstPid = projectInstance.GetPropertyValue("PID1"); + string secondPid = projectInstance.GetPropertyValue("PID2"); + + // Verify both PIDs are valid + string.IsNullOrEmpty(firstPid).ShouldBeFalse("First task should have executed in out-of-proc node"); + string.IsNullOrEmpty(secondPid).ShouldBeFalse("Second task should have executed in out-of-proc node"); + + Int32.TryParse(firstPid, out int pid1).ShouldBeTrue(); + Int32.TryParse(secondPid, out int pid2).ShouldBeTrue(); + + // CLR2 should prevent node reuse - each task gets its own process + pid1.ShouldNotBe(pid2, "CLR2 runtime should prevent node reuse, creating separate processes for each task"); + + // Both processes should be different from the main MSBuild process + Process.GetCurrentProcess().Id.ShouldNotBe(pid1); + Process.GetCurrentProcess().Id.ShouldNotBe(pid2); + + // Verify that both task host processes exit quickly (transient behavior) + VerifyTransientTaskHostExit(pid1, "First CLR2 task host"); + VerifyTransientTaskHostExit(pid2, "Second CLR2 task host"); + } + } + } + + /// + /// Helper method to verify that a task host process exits quickly (transient behavior). + /// + private void VerifyTransientTaskHostExit(int pid, string processDescription) + { + try + { + Process taskHostProcess = Process.GetProcessById(pid); + taskHostProcess.WaitForExit(3000).ShouldBeTrue($"{processDescription} should exit quickly due to no node reuse"); + } + catch (ArgumentException e) + { + // Expected behavior - process may exit before we can attach to it + e.Message.ShouldBe($"Process with an Id of {pid} is not running."); + } + } + /// /// Verifies that various parameter types can be correctly transmitted to and received from /// a task host process, ensuring proper serialization/deserialization of all supported types. diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index f166b79299f..dc0e1191300 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -647,8 +647,6 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor // if runtime host path is null it means we don't have MSBuild.dll path resolved and there is no need to include it in the command line arguments. string commandLineArgsPlaceholder = "{0} /nologo /nodemode:2 /nodereuse:{1} /low:{2} "; - bool enableNodeReuse = ComponentHost.BuildParameters.EnableNodeReuse && Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.NodeReuse); - IList nodeContexts; int nodeId = (int)hostContext; @@ -665,7 +663,7 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor // There is always one task host per host context so we always create just 1 one task host node here. nodeContexts = GetNodes( runtimeHostPath, - string.Format(commandLineArgsPlaceholder, Path.Combine(msbuildAssemblyPath, Constants.MSBuildAssemblyName), ComponentHost.BuildParameters.EnableNodeReuse, ComponentHost.BuildParameters.LowPriority), + string.Format(commandLineArgsPlaceholder, Path.Combine(msbuildAssemblyPath, Constants.MSBuildAssemblyName), EnableNodeReuse(hostContext), ComponentHost.BuildParameters.LowPriority), nodeId, this, handshake, @@ -689,7 +687,7 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor nodeContexts = GetNodes( msbuildLocation, - string.Format(commandLineArgsPlaceholder, string.Empty, enableNodeReuse, ComponentHost.BuildParameters.LowPriority), + string.Format(commandLineArgsPlaceholder, string.Empty, EnableNodeReuse(hostContext), ComponentHost.BuildParameters.LowPriority), nodeId, this, new Handshake(hostContext), @@ -698,6 +696,22 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor 1); return nodeContexts.Count == 1; + + // Determines whether node reuse should be enabled for the given host context. + // Node reuse allows MSBuild to reuse existing task host processes for better performance, + // but is disabled for certain legacy runtime and architecture combinations. + bool EnableNodeReuse(HandshakeOptions hostContext) + { + // Node reuse is not supported for x86 or CLR2 task hosts. + bool isX86 = !Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.X64) + && !Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.Arm64); + bool isCLR2 = Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.CLR2); + + return ComponentHost.BuildParameters.EnableNodeReuse + && Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.NodeReuse) + && !isCLR2 + && !isX86; + } } /// diff --git a/src/Shared/CommunicationsUtilities.cs b/src/Shared/CommunicationsUtilities.cs index f68b50de294..c76fceb0b2d 100644 --- a/src/Shared/CommunicationsUtilities.cs +++ b/src/Shared/CommunicationsUtilities.cs @@ -186,7 +186,7 @@ internal Handshake(HandshakeOptions nodeType, string predefinedToolsDirectory = { } - // Helper method to validate handshake option presense. + // Helper method to validate handshake option presence internal static bool IsHandshakeOptionEnabled(HandshakeOptions hostContext, HandshakeOptions option) => (hostContext & option) == option; // Source options of the handshake. From 8ec417ae63f2ae2dbc65833135e1da0fc3c6b8f0 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Mon, 25 Aug 2025 19:56:01 +0200 Subject: [PATCH 2/6] remove extra changes --- .../BackEnd/ProcessIdTaskSidecar.cs | 2 +- .../BackEnd/TaskHostFactory_Tests.cs | 78 +------------------ 2 files changed, 2 insertions(+), 78 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/ProcessIdTaskSidecar.cs b/src/Build.UnitTests/BackEnd/ProcessIdTaskSidecar.cs index 486c644ee07..37c08e5e665 100644 --- a/src/Build.UnitTests/BackEnd/ProcessIdTaskSidecar.cs +++ b/src/Build.UnitTests/BackEnd/ProcessIdTaskSidecar.cs @@ -9,7 +9,7 @@ namespace Microsoft.Build.UnitTests { /// - /// This task was created for https://github.com/dotnet/msbuild/issues/3141 + /// This task was created for https://github.com/dotnet/msbuild/issues/3141. /// public class ProcessIdTaskSidecar : Task { diff --git a/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs b/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs index 86a50d10ea3..f07625e675f 100644 --- a/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs +++ b/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs @@ -180,83 +180,7 @@ public void TransientAndSidecarNodeCanCoexist() } } } - } - - /// - /// Verifies that node reuse is disabled when using CLR2 runtime. - /// - [Fact] - public void NodeReuseDisabledForCLR2Runtime() - { - using (TestEnvironment env = TestEnvironment.Create(_output)) - { - using ProcessTracker processTracker = new(); - { - string clr2TaskProject = $@" - - - - - - - - - - - - -"; - - TransientTestFile project = env.CreateFile("clr2Project.csproj", clr2TaskProject); - - // Enable node reuse globally and force out-of-proc execution - env.SetEnvironmentVariable("MSBUILDENABLENODEREUSE", "1"); - env.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1"); - - ProjectInstance projectInstance = new(project.Path); - projectInstance.Build().ShouldBeTrue(); - - string firstPid = projectInstance.GetPropertyValue("PID1"); - string secondPid = projectInstance.GetPropertyValue("PID2"); - - // Verify both PIDs are valid - string.IsNullOrEmpty(firstPid).ShouldBeFalse("First task should have executed in out-of-proc node"); - string.IsNullOrEmpty(secondPid).ShouldBeFalse("Second task should have executed in out-of-proc node"); - - Int32.TryParse(firstPid, out int pid1).ShouldBeTrue(); - Int32.TryParse(secondPid, out int pid2).ShouldBeTrue(); - - // CLR2 should prevent node reuse - each task gets its own process - pid1.ShouldNotBe(pid2, "CLR2 runtime should prevent node reuse, creating separate processes for each task"); - - // Both processes should be different from the main MSBuild process - Process.GetCurrentProcess().Id.ShouldNotBe(pid1); - Process.GetCurrentProcess().Id.ShouldNotBe(pid2); - - // Verify that both task host processes exit quickly (transient behavior) - VerifyTransientTaskHostExit(pid1, "First CLR2 task host"); - VerifyTransientTaskHostExit(pid2, "Second CLR2 task host"); - } - } - } - - /// - /// Helper method to verify that a task host process exits quickly (transient behavior). - /// - private void VerifyTransientTaskHostExit(int pid, string processDescription) - { - try - { - Process taskHostProcess = Process.GetProcessById(pid); - taskHostProcess.WaitForExit(3000).ShouldBeTrue($"{processDescription} should exit quickly due to no node reuse"); - } - catch (ArgumentException e) - { - // Expected behavior - process may exit before we can attach to it - e.Message.ShouldBe($"Process with an Id of {pid} is not running."); - } - } + } /// /// Verifies that various parameter types can be correctly transmitted to and received from From b1aa384e2959fc491de618f6390f48bb40274a9a Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Mon, 25 Aug 2025 20:25:07 +0200 Subject: [PATCH 3/6] disable one more node reuse case --- src/Shared/CommunicationsUtilities.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Shared/CommunicationsUtilities.cs b/src/Shared/CommunicationsUtilities.cs index c76fceb0b2d..ee6602c8865 100644 --- a/src/Shared/CommunicationsUtilities.cs +++ b/src/Shared/CommunicationsUtilities.cs @@ -921,10 +921,15 @@ internal static HandshakeOptions GetHandshakeOptions( break; } - if (nodeReuse) + if (nodeReuse + + // Don't set node reuse for legacy runtime and architecture combinations. + && clrVersion != 2 + && !architectureFlagToSet.Equals(XMakeAttributes.MSBuildArchitectureValues.x86)) { context |= HandshakeOptions.NodeReuse; } + if (lowPriority) { context |= HandshakeOptions.LowPriority; From 395178abcc6b1f6fc1a1b4693a692406179878b2 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Tue, 26 Aug 2025 10:26:38 +0200 Subject: [PATCH 4/6] remove x86 from condition --- .../Communications/NodeProviderOutOfProcTaskHost.cs | 8 ++------ src/Shared/CommunicationsUtilities.cs | 6 +----- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index dc0e1191300..81850b1cc0e 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -699,18 +699,14 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor // Determines whether node reuse should be enabled for the given host context. // Node reuse allows MSBuild to reuse existing task host processes for better performance, - // but is disabled for certain legacy runtime and architecture combinations. + // but is disabled for CLR2. bool EnableNodeReuse(HandshakeOptions hostContext) { - // Node reuse is not supported for x86 or CLR2 task hosts. - bool isX86 = !Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.X64) - && !Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.Arm64); bool isCLR2 = Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.CLR2); return ComponentHost.BuildParameters.EnableNodeReuse && Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.NodeReuse) - && !isCLR2 - && !isX86; + && !isCLR2; } } diff --git a/src/Shared/CommunicationsUtilities.cs b/src/Shared/CommunicationsUtilities.cs index ee6602c8865..a709e6475a2 100644 --- a/src/Shared/CommunicationsUtilities.cs +++ b/src/Shared/CommunicationsUtilities.cs @@ -921,11 +921,7 @@ internal static HandshakeOptions GetHandshakeOptions( break; } - if (nodeReuse - - // Don't set node reuse for legacy runtime and architecture combinations. - && clrVersion != 2 - && !architectureFlagToSet.Equals(XMakeAttributes.MSBuildArchitectureValues.x86)) + if (nodeReuse && clrVersion != 2) { context |= HandshakeOptions.NodeReuse; } From 2a54cb77f32b0d6149d58ad174ddab849ea023e7 Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Thu, 28 Aug 2025 18:13:53 +0200 Subject: [PATCH 5/6] respect nodereuse from build params --- src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs | 2 +- .../Communications/NodeProviderOutOfProcTaskHost.cs | 11 +++++------ .../Instance/TaskFactories/AssemblyTaskFactory.cs | 2 +- src/Build/Instance/TaskFactories/TaskHostTask.cs | 12 ++++++++---- src/MSBuild/XMake.cs | 3 +++ src/Shared/CommunicationsUtilities.cs | 1 + 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs b/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs index f07625e675f..6d9f78de3aa 100644 --- a/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs +++ b/src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs @@ -180,7 +180,7 @@ public void TransientAndSidecarNodeCanCoexist() } } } - } + } /// /// Verifies that various parameter types can be correctly transmitted to and received from diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index 81850b1cc0e..ac92cd0fb01 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -663,7 +663,7 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor // There is always one task host per host context so we always create just 1 one task host node here. nodeContexts = GetNodes( runtimeHostPath, - string.Format(commandLineArgsPlaceholder, Path.Combine(msbuildAssemblyPath, Constants.MSBuildAssemblyName), EnableNodeReuse(hostContext), ComponentHost.BuildParameters.LowPriority), + string.Format(commandLineArgsPlaceholder, Path.Combine(msbuildAssemblyPath, Constants.MSBuildAssemblyName), GetEnableNodeReuse(hostContext), ComponentHost.BuildParameters.LowPriority), nodeId, this, handshake, @@ -687,7 +687,7 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor nodeContexts = GetNodes( msbuildLocation, - string.Format(commandLineArgsPlaceholder, string.Empty, EnableNodeReuse(hostContext), ComponentHost.BuildParameters.LowPriority), + string.Format(commandLineArgsPlaceholder, string.Empty, GetEnableNodeReuse(hostContext), ComponentHost.BuildParameters.LowPriority), nodeId, this, new Handshake(hostContext), @@ -699,13 +699,12 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor // Determines whether node reuse should be enabled for the given host context. // Node reuse allows MSBuild to reuse existing task host processes for better performance, - // but is disabled for CLR2. - bool EnableNodeReuse(HandshakeOptions hostContext) + // but is disabled for CLR2 because it uses legacy MSBuildTaskHost. + bool GetEnableNodeReuse(HandshakeOptions hostContext) { bool isCLR2 = Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.CLR2); - return ComponentHost.BuildParameters.EnableNodeReuse - && Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.NodeReuse) + return Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.NodeReuse) && !isCLR2; } } diff --git a/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs b/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs index 1daf0873048..056bb45e954 100644 --- a/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs +++ b/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs @@ -393,7 +393,7 @@ internal ITask CreateTaskInstance( buildComponentHost, mergedParameters, _loadedType, - _isTaskHostFactory + taskHostFactoryExplicitlyRequested: _isTaskHostFactory #if FEATURE_APPDOMAIN , appDomainSetup #endif diff --git a/src/Build/Instance/TaskFactories/TaskHostTask.cs b/src/Build/Instance/TaskFactories/TaskHostTask.cs index 4f6927a1d65..6d90fa71380 100644 --- a/src/Build/Instance/TaskFactories/TaskHostTask.cs +++ b/src/Build/Instance/TaskFactories/TaskHostTask.cs @@ -124,7 +124,6 @@ internal class TaskHostTask : IGeneratedTask, ICancelableTask, INodePacketFactor /// private bool _taskExecutionSucceeded = false; - /// /// This separates the cause where we force all tasks to run in a task host via environment variables and TaskHostFactory /// The difference is that TaskHostFactory requires the TaskHost to be transient i.e. to expire after build. @@ -132,9 +131,8 @@ internal class TaskHostTask : IGeneratedTask, ICancelableTask, INodePacketFactor private bool _taskHostFactoryExplicitlyRequested = false; /// - /// Constructor + /// Constructor. /// - /// #pragma warning disable SA1111, SA1009 // Closing parenthesis should be on line of last parameter public TaskHostTask( IElementLocation taskLocation, @@ -301,7 +299,13 @@ public bool Execute() { lock (_taskHostLock) { - _requiredContext = CommunicationsUtilities.GetHandshakeOptions(taskHost: true, nodeReuse: !_taskHostFactoryExplicitlyRequested, taskHostParameters: _taskHostParameters); + _requiredContext = CommunicationsUtilities.GetHandshakeOptions( + taskHost: true, + + // Determine if we should use node reuse based on build parameters or user preferences (comes from UsingTask element). + // If the user explicitly requested the task host factory, then we always disable node reuse due to the transient nature of task host factory hosts. + nodeReuse: _buildComponentHost.BuildParameters.EnableNodeReuse && !_taskHostFactoryExplicitlyRequested, + taskHostParameters: _taskHostParameters); _connectedToTaskHost = _taskHostProvider.AcquireAndSetUpHost(_requiredContext, this, this, hostConfiguration, _taskHostParameters); } diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs index d76fff1454e..b633d8c810b 100644 --- a/src/MSBuild/XMake.cs +++ b/src/MSBuild/XMake.cs @@ -716,6 +716,9 @@ public static ExitType Execute( #endif GatherAllSwitches(commandLine, out var switchesFromAutoResponseFile, out var switchesNotFromAutoResponseFile, out _); + + CommunicationsUtilities.Trace($"Command line parameters: {commandLine}"); + bool buildCanBeInvoked = ProcessCommandLineSwitches( switchesFromAutoResponseFile, switchesNotFromAutoResponseFile, diff --git a/src/Shared/CommunicationsUtilities.cs b/src/Shared/CommunicationsUtilities.cs index 76f5a821237..aded7e1d3c0 100644 --- a/src/Shared/CommunicationsUtilities.cs +++ b/src/Shared/CommunicationsUtilities.cs @@ -920,6 +920,7 @@ internal static HandshakeOptions GetHandshakeOptions( break; } + // Node reuse is not supported in CLR2 because it's a legacy runtime. if (nodeReuse && clrVersion != 2) { context |= HandshakeOptions.NodeReuse; From cafdf6f5033e9c9020295e278b467fdec55219cc Mon Sep 17 00:00:00 2001 From: YuliiaKovalova Date: Thu, 28 Aug 2025 18:35:47 +0200 Subject: [PATCH 6/6] rename method --- .../Communications/NodeProviderOutOfProcTaskHost.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index ac92cd0fb01..30af960b986 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -663,7 +663,7 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor // There is always one task host per host context so we always create just 1 one task host node here. nodeContexts = GetNodes( runtimeHostPath, - string.Format(commandLineArgsPlaceholder, Path.Combine(msbuildAssemblyPath, Constants.MSBuildAssemblyName), GetEnableNodeReuse(hostContext), ComponentHost.BuildParameters.LowPriority), + string.Format(commandLineArgsPlaceholder, Path.Combine(msbuildAssemblyPath, Constants.MSBuildAssemblyName), NodeReuseIsEnabled(hostContext), ComponentHost.BuildParameters.LowPriority), nodeId, this, handshake, @@ -687,7 +687,7 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor nodeContexts = GetNodes( msbuildLocation, - string.Format(commandLineArgsPlaceholder, string.Empty, GetEnableNodeReuse(hostContext), ComponentHost.BuildParameters.LowPriority), + string.Format(commandLineArgsPlaceholder, string.Empty, NodeReuseIsEnabled(hostContext), ComponentHost.BuildParameters.LowPriority), nodeId, this, new Handshake(hostContext), @@ -700,7 +700,7 @@ internal bool CreateNode(HandshakeOptions hostContext, INodePacketFactory factor // Determines whether node reuse should be enabled for the given host context. // Node reuse allows MSBuild to reuse existing task host processes for better performance, // but is disabled for CLR2 because it uses legacy MSBuildTaskHost. - bool GetEnableNodeReuse(HandshakeOptions hostContext) + bool NodeReuseIsEnabled(HandshakeOptions hostContext) { bool isCLR2 = Handshake.IsHandshakeOptionEnabled(hostContext, HandshakeOptions.CLR2);