/// <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)));
 }
Пример #2
0
        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));
            }
        }
Пример #3
0
        /// <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));
        }
Пример #5
0
        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);
        }
Пример #6
0
 /// <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)));
 }
Пример #7
0
 /// <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)));
 }
Пример #10
0
 protected override Handshake GetHandshake()
 {
     return(new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, architectureFlagToSet: XMakeAttributes.GetCurrentMSBuildArchitecture(), nodeReuse: _enableReuse, lowPriority: _lowPriority)));
 }
Пример #11
0
 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)));
 }