Skip to content
Merged
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
39 changes: 36 additions & 3 deletions src/Build/BackEnd/Node/OutOfProcServerNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Build.BackEnd;
using Microsoft.Build.Shared;
using Microsoft.Build.Internal;
using System.Threading.Tasks;

namespace Microsoft.Build.Execution
{
Expand All @@ -19,6 +20,8 @@ public sealed class OutOfProcServerNode : INode, INodePacketFactory, INodePacket
{
private readonly Func<string, (int exitCode, string exitType)> _buildFunction;

private readonly Action _onCancel;

/// <summary>
/// The endpoint used to talk to the host.
/// </summary>
Expand Down Expand Up @@ -59,11 +62,14 @@ public sealed class OutOfProcServerNode : INode, INodePacketFactory, INodePacket
/// </summary>
private readonly bool _debugCommunications;

private Task? _buildTask;

private string _serverBusyMutexName = default!;

public OutOfProcServerNode(Func<string, (int exitCode, string exitType)> buildFunction)
public OutOfProcServerNode(Func<string, (int exitCode, string exitType)> buildFunction, Action onCancel)
{
_buildFunction = buildFunction;
_onCancel = onCancel;
new Dictionary<string, string>();
_debugCommunications = (Environment.GetEnvironmentVariable("MSBUILDDEBUGCOMM") == "1");

Expand All @@ -74,6 +80,7 @@ public OutOfProcServerNode(Func<string, (int exitCode, string exitType)> buildFu

(this as INodePacketFactory).RegisterPacketHandler(NodePacketType.ServerNodeBuildCommand, ServerNodeBuildCommand.FactoryForDeserialization, this);
(this as INodePacketFactory).RegisterPacketHandler(NodePacketType.NodeBuildComplete, NodeBuildComplete.FactoryForDeserialization, this);
(this as INodePacketFactory).RegisterPacketHandler(NodePacketType.ServerNodeBuildCancel, ServerNodeBuildCancel.FactoryForDeserialization, this);
}

#region INode Members
Expand Down Expand Up @@ -105,7 +112,7 @@ public NodeEngineShutdownReason Run(out Exception? shutdownException)
_nodeEndpoint.Listen(this);

var waitHandles = new WaitHandle[] { _shutdownEvent, _packetReceivedEvent };

// Get the current directory before doing any work. We need this so we can restore the directory when the node shutsdown.
while (true)
{
Expand Down Expand Up @@ -269,11 +276,35 @@ private void HandlePacket(INodePacket packet)
switch (packet.Type)
{
case NodePacketType.ServerNodeBuildCommand:
HandleServerNodeBuildCommand((ServerNodeBuildCommand)packet);
HandleServerNodeBuildCommandAsync((ServerNodeBuildCommand)packet);
break;
case NodePacketType.ServerNodeBuildCancel:
_onCancel();
break;
}
}

private void HandleServerNodeBuildCommandAsync(ServerNodeBuildCommand command)
{
_buildTask = Task.Run(() =>
{
try
{
HandleServerNodeBuildCommand(command);
}
catch(Exception e)
{
_shutdownException = e;
_shutdownReason = NodeEngineShutdownReason.Error;
_shutdownEvent.Set();
}
finally
{
_buildTask = null;
}
});
}

private void HandleServerNodeBuildCommand(ServerNodeBuildCommand command)
{
CommunicationsUtilities.Trace("Building with MSBuild server with command line {0}", command.CommandLine);
Expand All @@ -285,6 +316,8 @@ private void HandleServerNodeBuildCommand(ServerNodeBuildCommand command)
_shutdownException = new InvalidOperationException("Client requested build while server is busy processing previous client build request.");
_shutdownReason = NodeEngineShutdownReason.Error;
_shutdownEvent.Set();

return;
}

// set build process context
Expand Down
20 changes: 20 additions & 0 deletions src/Build/BackEnd/Node/ServerNodeBuildCancel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//

namespace Microsoft.Build.BackEnd
{
internal sealed class ServerNodeBuildCancel : INodePacket
{
public NodePacketType Type => NodePacketType.ServerNodeBuildCancel;

public void Translate(ITranslator translator)
{
}

internal static INodePacket FactoryForDeserialization(ITranslator translator)
{
return new ServerNodeBuildCancel();
}
}
}
1 change: 1 addition & 0 deletions src/Build/Microsoft.Build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
<Compile Include="FileSystem\*.cs" />
<Compile Include="BackEnd\Node\ConsoleOutput.cs" />
<Compile Include="BackEnd\Node\ServerNamedMutex.cs" />
<Compile Include="BackEnd\Node\ServerNodeBuildCancel.cs" />
<Compile Include="BackEnd\Node\ServerNodeBuildCommand.cs" />
<Compile Include="BackEnd\Node\ServerNodeConsoleWrite.cs" />
<Compile Include="BackEnd\Node\ServerNodeBuildResult.cs" />
Expand Down
4 changes: 2 additions & 2 deletions src/Build/PublicAPI/net/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ Microsoft.Build.Execution.MSBuildClientExitType.ServerBusy = 1 -> Microsoft.Buil
Microsoft.Build.Execution.MSBuildClientExitType.Success = 0 -> Microsoft.Build.Execution.MSBuildClientExitType
Microsoft.Build.Execution.MSBuildClientExitType.Unexpected = 4 -> Microsoft.Build.Execution.MSBuildClientExitType
Microsoft.Build.Execution.OutOfProcServerNode
Microsoft.Build.Execution.OutOfProcServerNode.OutOfProcServerNode(System.Func<string, (int exitCode, string exitType)> buildFunction) -> void
Microsoft.Build.Execution.OutOfProcServerNode.Run(out System.Exception shutdownException) -> Microsoft.Build.Execution.NodeEngineShutdownReason
Microsoft.Build.Execution.OutOfProcServerNode.OutOfProcServerNode(System.Func<string, (int exitCode, string exitType)> buildFunction, System.Action onCancel) -> void
Microsoft.Build.Execution.OutOfProcServerNode.Run(out System.Exception shutdownException) -> Microsoft.Build.Execution.NodeEngineShutdownReason
2 changes: 1 addition & 1 deletion src/Build/PublicAPI/netstandard/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ Microsoft.Build.Execution.MSBuildClientExitType.ServerBusy = 1 -> Microsoft.Buil
Microsoft.Build.Execution.MSBuildClientExitType.Success = 0 -> Microsoft.Build.Execution.MSBuildClientExitType
Microsoft.Build.Execution.MSBuildClientExitType.Unexpected = 4 -> Microsoft.Build.Execution.MSBuildClientExitType
Microsoft.Build.Execution.OutOfProcServerNode
Microsoft.Build.Execution.OutOfProcServerNode.OutOfProcServerNode(System.Func<string, (int exitCode, string exitType)> buildFunction) -> void
Microsoft.Build.Execution.OutOfProcServerNode.OutOfProcServerNode(System.Func<string, (int exitCode, string exitType)> buildFunction, System.Action onCancel) -> void
Microsoft.Build.Execution.OutOfProcServerNode.Run(out System.Exception shutdownException) -> Microsoft.Build.Execution.NodeEngineShutdownReason
9 changes: 8 additions & 1 deletion src/MSBuild/XMake.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2684,7 +2684,14 @@ private static void StartLocalNode(CommandLineSwitches commandLineSwitches, bool
return (exitCode, exitType.ToString());
};

OutOfProcServerNode node = new(buildFunction);
Action onCancel = () =>
{
Console.WriteLine(ResourceUtilities.GetResourceString("AbortingBuild"));

BuildManager.DefaultBuildManager.CancelAllSubmissions();
};

OutOfProcServerNode node = new(buildFunction, onCancel);

s_isServerNode = true;
shutdownReason = node.Run(out nodeException);
Expand Down
6 changes: 6 additions & 0 deletions src/Shared/INodePacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ internal enum NodePacketType : byte
/// Keep this enum value constant intact as this is part of contract with dotnet CLI
/// </summary>
ServerNodeConsoleWrite = 0xF2,

/// <summary>
/// Command to cancel ongoing build.
/// Keep this enum value constant intact as this is part of contract with dotnet CLI
/// </summary>
ServerNodeBuildCancel = 0xF3,
}
#endregion

Expand Down