Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion src/Build/BackEnd/BuildManager/BuildManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,7 @@ public void EndBuild()
Reset();
_buildManagerState = BuildManagerState.Idle;

if (Traits.Instance.ForceTaskFactoryOutOfProc)
if (Traits.Instance.ForceTaskFactoryOutOfProc || _buildParameters.MultiThreaded)
Comment thread
JanProvaznik marked this conversation as resolved.
{
TaskFactoryUtilities.CleanCurrentProcessInlineTaskDirectory();
}
Expand Down
23 changes: 14 additions & 9 deletions src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -890,18 +890,18 @@ private TaskFactoryWrapper FindTaskInRegistry(IDictionary<string, string> taskId
{
if (!_intrinsicTasks.TryGetValue(_taskName, out TaskFactoryWrapper returnClass))
{
returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, taskIdentityParameters, true /* exact match */, _targetLoggingContext, _taskLocation);
returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, taskIdentityParameters, true /* exact match */, _targetLoggingContext, _taskLocation, _buildComponentHost?.BuildParameters);
if (returnClass == null)
{
returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, taskIdentityParameters, false /* fuzzy match */, _targetLoggingContext, _taskLocation);
returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, taskIdentityParameters, false /* fuzzy match */, _targetLoggingContext, _taskLocation, _buildComponentHost?.BuildParameters);

if (returnClass == null)
{
returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, null, true /* exact match */, _targetLoggingContext, _taskLocation);
returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, null, true /* exact match */, _targetLoggingContext, _taskLocation, _buildComponentHost?.BuildParameters);

if (returnClass == null)
{
returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, null, false /* fuzzy match */, _targetLoggingContext, _taskLocation);
returnClass = _projectInstance.TaskRegistry.GetRegisteredTask(_taskName, null, null, false /* fuzzy match */, _targetLoggingContext, _taskLocation, _buildComponentHost?.BuildParameters);

if (returnClass == null)
{
Expand Down Expand Up @@ -980,13 +980,17 @@ private ITask InstantiateTask(int scheduledNodeId, IDictionary<string, string> t
}
else
{
TaskFactoryLoggingHost loggingHost = new TaskFactoryLoggingHost(_buildEngine.IsRunningMultipleNodes, _taskLocation, _taskLoggingContext);
TaskFactoryEngineContext loggingHost = new TaskFactoryEngineContext(_buildEngine.IsRunningMultipleNodes, _taskLocation, _taskLoggingContext, _buildComponentHost?.BuildParameters?.MultiThreaded ?? false, Traits.Instance.ForceTaskFactoryOutOfProc);
bool isTaskHost = false;
try
{
// Check if we should force out-of-process execution for non-AssemblyTaskFactory instances
// This happens when: 1) Environment variable is set, OR 2) MultiThreaded build is enabled
// IntrinsicTaskFactory tasks run in proc always
if (Traits.Instance.ForceTaskFactoryOutOfProc && _taskFactoryWrapper.TaskFactory is not IntrinsicTaskFactory)
bool shouldRunOutOfProc = (Traits.Instance.ForceTaskFactoryOutOfProc || (_buildComponentHost?.BuildParameters?.MultiThreaded ?? false))
Comment thread
JanProvaznik marked this conversation as resolved.
Outdated
&& _taskFactoryWrapper.TaskFactory is not IntrinsicTaskFactory;

if (shouldRunOutOfProc)
{
// Custom Task factories are not supported, internal TaskFactories implement this marker interface
if (_taskFactoryWrapper.TaskFactory is not IOutOfProcTaskFactory outOfProcTaskFactory)
Expand Down Expand Up @@ -1730,14 +1734,14 @@ private void DisplayCancelWaitMessage()

/// <summary>
/// Creates a <see cref="TaskHostTask"/> wrapper to run a non-AssemblyTaskFactory task out of process.
/// This is used when Traits.Instance.ForceTaskFactoryOutOfProc is true to ensure
/// This is used when Traits.Instance.ForceTaskFactoryOutOfProc=1 is true or the multi-threaded mode is active to ensure
/// non-AssemblyTaskFactory tasks run in isolation.
/// </summary>
/// <param name="taskIdentityParameters">Task identity parameters.</param>
/// <param name="loggingHost">The logging host to use for the task.</param>
/// <param name="outOfProcTaskFactory">The out-of-process task factory instance.</param>
/// <returns>A TaskHostTask that will execute the inner task out of process, or <code>null</code> if task creation fails.</returns>
private ITask CreateTaskHostTaskForOutOfProcFactory(IDictionary<string, string> taskIdentityParameters, TaskFactoryLoggingHost loggingHost, IOutOfProcTaskFactory outOfProcTaskFactory)
private ITask CreateTaskHostTaskForOutOfProcFactory(IDictionary<string, string> taskIdentityParameters, TaskFactoryEngineContext loggingHost, IOutOfProcTaskFactory outOfProcTaskFactory)
{
ITask innerTask;

Expand All @@ -1758,7 +1762,8 @@ private ITask CreateTaskHostTaskForOutOfProcFactory(IDictionary<string, string>
string resolvedAssemblyLocation = outOfProcTaskFactory.GetAssemblyPath();

// This should never happen - if the factory can create a task, it should know where the assembly is
ErrorUtilities.VerifyThrow(!string.IsNullOrEmpty(resolvedAssemblyLocation),
ErrorUtilities.VerifyThrow(
!string.IsNullOrEmpty(resolvedAssemblyLocation),
$"IOutOfProcTaskFactory {_taskFactoryWrapper.TaskFactory.FactoryName} created a task but returned null/empty assembly path");

LoadedType taskLoadedType = new LoadedType(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ namespace Microsoft.Build.BackEnd
/// <summary>
/// The host allows task factories access to method to allow them to log message during the construction of the task factories.
/// </summary>
internal class TaskFactoryLoggingHost :
internal class TaskFactoryEngineContext :
#if FEATURE_APPDOMAIN
MarshalByRefObject,
#endif
IBuildEngine
IBuildEngine,
ITaskFactoryBuildParameterProvider
{
/// <summary>
/// Location of the task node in the original file
Expand All @@ -36,6 +37,16 @@ internal class TaskFactoryLoggingHost :
/// </summary>
private BuildLoggingContext _loggingContext;

/// <summary>
/// Whether the build is running in multi-threaded mode.
/// </summary>
private readonly bool _isMultiThreadedBuild;

/// <summary>
/// Whether task factories should be forced to compile for out-of-process execution.
/// </summary>
private readonly bool _forceOutOfProcessExecution;

/// <summary>
/// Is the system running in multi-process mode and requires events to be serializable
/// </summary>
Expand All @@ -58,7 +69,7 @@ internal class TaskFactoryLoggingHost :
/// <summary>
/// Constructor
/// </summary>
public TaskFactoryLoggingHost(bool isRunningWithMultipleNodes, ElementLocation elementLocation, BuildLoggingContext loggingContext)
public TaskFactoryEngineContext(bool isRunningWithMultipleNodes, ElementLocation elementLocation, BuildLoggingContext loggingContext, bool isMultiThreadedBuild = false, bool forceOutOfProcessExecution = false)
{
ErrorUtilities.VerifyThrowArgumentNull(loggingContext);
ErrorUtilities.VerifyThrowInternalNull(elementLocation);
Expand All @@ -67,6 +78,8 @@ public TaskFactoryLoggingHost(bool isRunningWithMultipleNodes, ElementLocation e
_isRunningWithMultipleNodes = isRunningWithMultipleNodes;
_loggingContext = loggingContext;
_elementLocation = elementLocation;
_isMultiThreadedBuild = isMultiThreadedBuild;
_forceOutOfProcessExecution = forceOutOfProcessExecution;
}

/// <summary>
Expand Down Expand Up @@ -146,6 +159,37 @@ internal BuildLoggingContext LoggingContext
{ return _loggingContext; }
}

/// <summary>
/// Gets a value indicating whether the build is running in multi-threaded mode (/mt flag).
/// </summary>
/// <remarks>
/// This property implements ITaskFactoryBuildParameterProvider to allow task factories to determine
/// if they should compile for out-of-process execution during their Initialize() method.
/// </remarks>
public bool IsMultiThreadedBuild
{
get
{
VerifyActiveProxy();
return _isMultiThreadedBuild;
}
}

/// <summary>
/// Gets a value indicating whether task factories should be forced to compile for out-of-process execution.
/// </summary>
/// <remarks>
/// This is controlled by the MSBUILDFORCEINLINETASKFACTORIESOUTOFPROC environment variable.
/// </remarks>
public bool ForceOutOfProcessExecution
{
get
{
VerifyActiveProxy();
return _forceOutOfProcessExecution;
}
}

#region IBuildEngine Members

/// <summary>
Expand Down
Loading