/// <summary> /// Returns the host handshake for this node endpoint /// </summary> protected override Handshake GetHandshake() { return(new Handshake(CommunicationsUtilities.GetHandshakeOptions( taskHost: false, is64Bit: EnvironmentUtilities.Is64BitProcess, nodeReuse: _enableReuse, lowPriority: _lowPriority))); }
public IList <NodeInfo> CreateNodes(int nextNodeId, INodePacketFactory factory, Func <NodeInfo, NodeConfiguration> configurationFactory, int numberOfNodesToCreate) { ErrorUtilities.VerifyThrowArgumentNull(factory, nameof(factory)); // This can run concurrently. To be properly detect internal bug when we create more nodes than allowed // we add into _nodeContexts premise of future node and verify that it will not cross limits. if (_nodeContexts.Count + numberOfNodesToCreate > ComponentHost.BuildParameters.MaxNodeCount) { ErrorUtilities.ThrowInternalError("Exceeded max node count of '{0}', current count is '{1}' ", ComponentHost.BuildParameters.MaxNodeCount, _nodeContexts.Count); return(new List <NodeInfo>()); } ConcurrentBag <NodeInfo> nodes = new(); // Start the new process. We pass in a node mode with a node number of 1, to indicate that we // want to start up just a standard MSBuild out-of-proc node. // Note: We need to always pass /nodeReuse to ensure the value for /nodeReuse from msbuild.rsp // (next to msbuild.exe) is ignored. string commandLineArgs = $"/nologo /nodemode:1 /nodeReuse:{ComponentHost.BuildParameters.EnableNodeReuse.ToString().ToLower()} /low:{ComponentHost.BuildParameters.LowPriority.ToString().ToLower()}"; CommunicationsUtilities.Trace("Starting to acquire {1} new or existing node(s) to establish nodes from ID {0} to {2}...", nextNodeId, numberOfNodesToCreate, nextNodeId + numberOfNodesToCreate - 1); Handshake hostHandshake = new(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, architectureFlagToSet: XMakeAttributes.GetCurrentMSBuildArchitecture(), nodeReuse: ComponentHost.BuildParameters.EnableNodeReuse, lowPriority: ComponentHost.BuildParameters.LowPriority)); IList <NodeContext> nodeContexts = GetNodes(null, commandLineArgs, nextNodeId, factory, hostHandshake, NodeContextCreated, NodeContextTerminated, numberOfNodesToCreate); if (nodeContexts.Count > 0) { return(nodeContexts .Select(nc => new NodeInfo(nc.NodeId, ProviderType)) .ToList()); } throw new BuildAbortedException(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("CouldNotConnectToMSBuildExe", ComponentHost.BuildParameters.NodeExeLocation)); void NodeContextCreated(NodeContext context) { NodeInfo nodeInfo = new NodeInfo(context.NodeId, ProviderType); _nodeContexts[context.NodeId] = context; // Start the asynchronous read. context.BeginAsyncPacketRead(); // Configure the node. context.SendData(configurationFactory(nodeInfo)); } }
/// <summary> /// Returns true if a task host exists that can service the requested runtime and architecture /// values, and false otherwise. /// </summary> internal static bool DoesTaskHostExist(string runtime, string architecture) { if (runtime != null) { runtime = runtime.Trim(); } if (architecture != null) { architecture = architecture.Trim(); } if (!XMakeAttributes.IsValidMSBuildRuntimeValue(runtime)) { ErrorUtilities.ThrowArgument("InvalidTaskHostFactoryParameter", runtime, "Runtime", XMakeAttributes.MSBuildRuntimeValues.clr2, XMakeAttributes.MSBuildRuntimeValues.clr4, XMakeAttributes.MSBuildRuntimeValues.currentRuntime, XMakeAttributes.MSBuildRuntimeValues.any); } if (!XMakeAttributes.IsValidMSBuildArchitectureValue(architecture)) { ErrorUtilities.ThrowArgument("InvalidTaskHostFactoryParameter", architecture, "Architecture", XMakeAttributes.MSBuildArchitectureValues.x86, XMakeAttributes.MSBuildArchitectureValues.x64, XMakeAttributes.MSBuildArchitectureValues.currentArchitecture, XMakeAttributes.MSBuildArchitectureValues.any); } runtime = XMakeAttributes.GetExplicitMSBuildRuntime(runtime); architecture = XMakeAttributes.GetExplicitMSBuildArchitecture(architecture); IDictionary <string, string> parameters = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); parameters.Add(XMakeAttributes.runtime, runtime); parameters.Add(XMakeAttributes.architecture, architecture); HandshakeOptions desiredContext = CommunicationsUtilities.GetHandshakeOptions(taskHost: true, taskHostParameters: parameters); string taskHostLocation = NodeProviderOutOfProcTaskHost.GetMSBuildLocationFromHostContext(desiredContext); if (taskHostLocation != null && FileUtilities.FileExistsNoThrow(taskHostLocation)) { return(true); } return(false); }
/// <summary> /// Instantiates a new MSBuild process acting as a child node. /// </summary> public bool CreateNode(int nodeId, INodePacketFactory factory, NodeConfiguration configuration) { ErrorUtilities.VerifyThrowArgumentNull(factory, "factory"); if (_nodeContexts.Count == ComponentHost.BuildParameters.MaxNodeCount) { ErrorUtilities.ThrowInternalError("All allowable nodes already created ({0}).", _nodeContexts.Count); return(false); } // Start the new process. We pass in a node mode with a node number of 1, to indicate that we // want to start up just a standard MSBuild out-of-proc node. // Note: We need to always pass /nodeReuse to ensure the value for /nodeReuse from msbuild.rsp // (next to msbuild.exe) is ignored. string commandLineArgs = $"/nologo /nodemode:1 /nodeReuse:{ComponentHost.BuildParameters.EnableNodeReuse.ToString().ToLower()} /low:{ComponentHost.BuildParameters.LowPriority.ToString().ToLower()}"; // Make it here. CommunicationsUtilities.Trace("Starting to acquire a new or existing node to establish node ID {0}...", nodeId); Handshake hostHandshake = new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, nodeReuse: ComponentHost.BuildParameters.EnableNodeReuse, lowPriority: ComponentHost.BuildParameters.LowPriority, is64Bit: EnvironmentUtilities.Is64BitProcess)); NodeContext context = GetNode(null, commandLineArgs, nodeId, factory, hostHandshake, NodeContextTerminated); if (null != context) { _nodeContexts[nodeId] = context; // Start the asynchronous read. context.BeginAsyncPacketRead(); // Configure the node. context.SendData(configuration); return(true); } throw new BuildAbortedException(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("CouldNotConnectToMSBuildExe", ComponentHost.BuildParameters.NodeExeLocation)); }
public bool Execute() { // log that we are about to spawn the task host string runtime = _taskHostParameters[XMakeAttributes.runtime]; string architecture = _taskHostParameters[XMakeAttributes.architecture]; _taskLoggingContext.LogComment(MessageImportance.Low, "ExecutingTaskInTaskHost", _taskType.Type.Name, _taskType.Assembly.AssemblyLocation, runtime, architecture); // set up the node lock (_taskHostLock) { _taskHostProvider = (NodeProviderOutOfProcTaskHost)_buildComponentHost.GetComponent(BuildComponentType.OutOfProcTaskHostNodeProvider); ErrorUtilities.VerifyThrowInternalNull(_taskHostProvider, "taskHostProvider"); } TaskHostConfiguration hostConfiguration = new TaskHostConfiguration ( _buildComponentHost.BuildParameters.NodeId, NativeMethodsShared.GetCurrentDirectory(), CommunicationsUtilities.GetEnvironmentVariables(), _buildComponentHost.BuildParameters.Culture, _buildComponentHost.BuildParameters.UICulture, #if FEATURE_APPDOMAIN _appDomainSetup, #endif BuildEngine.LineNumberOfTaskNode, BuildEngine.ColumnNumberOfTaskNode, BuildEngine.ProjectFileOfTaskNode, BuildEngine.ContinueOnError, _taskType.Type.FullName, AssemblyUtilities.GetAssemblyLocation(_taskType.Type.GetTypeInfo().Assembly), _buildComponentHost.BuildParameters.LogTaskInputs, _setParameters, new Dictionary <string, string>(_buildComponentHost.BuildParameters.GlobalProperties), _taskLoggingContext.GetWarningsAsErrors(), _taskLoggingContext.GetWarningsAsMessages() ); try { lock (_taskHostLock) { _requiredContext = CommunicationsUtilities.GetHandshakeOptions(taskHost: true, taskHostParameters: _taskHostParameters); _connectedToTaskHost = _taskHostProvider.AcquireAndSetUpHost(_requiredContext, this, this, hostConfiguration); } if (_connectedToTaskHost) { try { bool taskFinished = false; while (!taskFinished) { _packetReceivedEvent.WaitOne(); INodePacket packet = null; // Handle the packet that's coming in while (_receivedPackets.TryDequeue(out packet)) { if (packet != null) { HandlePacket(packet, out taskFinished); } } } } finally { lock (_taskHostLock) { _taskHostProvider.DisconnectFromHost(_requiredContext); _connectedToTaskHost = false; } } } else { LogErrorUnableToCreateTaskHost(_requiredContext, runtime, architecture, null); } } catch (BuildAbortedException) { LogErrorUnableToCreateTaskHost(_requiredContext, runtime, architecture, null); } catch (NodeFailedToLaunchException e) { LogErrorUnableToCreateTaskHost(_requiredContext, runtime, architecture, e); } return(_taskExecutionSucceeded); }
/// <summary> /// Magic number sent by the client to the host during the handshake. /// Munged version of the host handshake. /// </summary> internal static long GetClientHandshake(bool enableNodeReuse, bool enableLowPriority) { return(CommunicationsUtilities.GetClientHandshake(CommunicationsUtilities.GetHandshakeOptions(false, nodeReuse: enableNodeReuse, lowPriority: enableLowPriority, is64Bit: EnvironmentUtilities.Is64BitProcess))); }
/// <summary> /// Magic number sent by the host to the client during the handshake. /// Derived from the binary timestamp to avoid mixing binary versions, /// Is64BitProcess to avoid mixing bitness, and enableNodeReuse to /// ensure that a /nr:false build doesn't reuse clients left over from /// a prior /nr:true build. The enableLowPriority flag is to ensure that /// a build with /low:false doesn't reuse clients left over for a prior /// /low:true build. /// </summary> /// <param name="enableNodeReuse">Is reuse of build nodes allowed?</param> /// <param name="enableLowPriority">Is the build running at low priority?</param> internal static long GetHostHandshake(bool enableNodeReuse, bool enableLowPriority) { CommunicationsUtilities.Trace("MSBUILDNODEHANDSHAKESALT=\"{0}\", msbuildDirectory=\"{1}\", enableNodeReuse={2}, enableLowPriority={3}", Traits.MSBuildNodeHandshakeSalt, BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32, enableNodeReuse, enableLowPriority); return(CommunicationsUtilities.GetHostHandshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, nodeReuse: enableNodeReuse, lowPriority: enableLowPriority, is64Bit: EnvironmentUtilities.Is64BitProcess))); }
/// <summary> /// Returns the client handshake for this node endpoint /// </summary> protected override long GetClientHandshake() { return(CommunicationsUtilities.GetClientHandshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: true))); }
protected override Handshake GetHandshake() { return(new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: true))); }
protected override Handshake GetHandshake() { return(new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, architectureFlagToSet: XMakeAttributes.GetCurrentMSBuildArchitecture(), nodeReuse: _enableReuse, lowPriority: _lowPriority))); }
internal static Handshake GetHandshake(bool enableNodeReuse, bool enableLowPriority) { CommunicationsUtilities.Trace("MSBUILDNODEHANDSHAKESALT=\"{0}\", msbuildDirectory=\"{1}\", enableNodeReuse={2}, enableLowPriority={3}", Traits.MSBuildNodeHandshakeSalt, BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32, enableNodeReuse, enableLowPriority); return(new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, architectureFlagToSet: XMakeAttributes.GetCurrentMSBuildArchitecture(), nodeReuse: enableNodeReuse, lowPriority: enableLowPriority))); }