/// <summary>
 /// Instantiates a new MSBuild process acting as a child node.
 /// </summary>
 public bool CreateNode(int nodeId, INodePacketFactory factory, NodeConfiguration configuration)
 {
     throw new NotImplementedException("Use the other overload of CreateNode instead");
 }
Example #2
0
        /// <summary>
        /// Requests that a node be created on the specified machine.
        /// </summary>
        /// <param name="nodeId">The id of the node to create.</param>
        /// <param name="factory">The factory to use to create packets from this node.</param>
        /// <param name="configuration">The configuration for the node.</param>
        public bool CreateNode(int nodeId, INodePacketFactory factory, NodeConfiguration configuration)
        {
            ErrorUtilities.VerifyThrow(nodeId != InvalidInProcNodeId, "Cannot create in-proc node.");

            // Attempt to get the operating environment semaphore if requested.
            if (_componentHost.BuildParameters.SaveOperatingEnvironment)
            {
                // We can only create additional in-proc nodes if we have decided not to save the operating environment.  This is the global
                // DTAR case in Visual Studio, but other clients might enable this as well under certain special circumstances.
                ErrorUtilities.VerifyThrow(_inProcNodeOwningOperatingEnvironment == null, "Unexpected non-null in-proc node semaphore.");

                // Blend.exe v4.x or earlier launches two nodes that co-own the same operating environment
                // and they will not patch this
                var p = Process.GetCurrentProcess();
                {
                    // This should be reasonably sufficient to assume MS Expression Blend 4 or earlier
                    if ((FileUtilities.CurrentExecutableName.Equals("Blend", StringComparison.OrdinalIgnoreCase)) &&
                        (p.MainModule.FileVersionInfo.OriginalFilename.Equals("Blend.exe", StringComparison.OrdinalIgnoreCase)) &&
                        (p.MainModule.FileVersionInfo.ProductMajorPart < 5))
                    {
                        _exclusiveOperatingEnvironment = false;
                    }
                }

                if (Environment.GetEnvironmentVariable("MSBUILDINPROCENVCHECK") == "1")
                {
                    _exclusiveOperatingEnvironment = true;
                }

                if (_exclusiveOperatingEnvironment)
                {
                    _inProcNodeOwningOperatingEnvironment = new Semaphore(1, 1, "MSBuildIPN_" + Process.GetCurrentProcess().Id);
                    if (!_inProcNodeOwningOperatingEnvironment.WaitOne(0))
                    {
                        // Can't take the operating environment.
                        return false;
                    }
                }
            }

            // If it doesn't already exist, create it.
            if (_inProcNode == null)
            {
                if (!InstantiateNode(factory))
                {
                    return false;
                }
            }

            _inProcNodeEndpoint.SendData(configuration);
            _inProcNodeId = nodeId;

            return true;
        }
Example #3
0
 /// <summary>
 /// Instantiates a new MSBuild process acting as a child node.
 /// </summary>
 public bool CreateNode(int nodeId, INodePacketFactory factory, NodeConfiguration configuration)
 {
     throw new NotImplementedException("Use the other overload of CreateNode instead");
 }
 /// <summary>
 /// Creates a node on an available NodeProvider, if any..
 /// </summary>
 /// <param name="configuration">The configuration to use for the remote node.</param>
 /// <returns>A NodeInfo describing the node created, or null if none could be created.</returns>
 public NodeInfo CreateNode(NodeConfiguration configuration, NodeAffinity nodeAffinity)
 {
     throw new NotSupportedException("not used");
 }
Example #5
0
 public NodeInfo CreateNode(NodeConfiguration configuration, NodeAffinity nodeAffinity)
 {
     throw new NotSupportedException("not used");
 }
Example #6
0
        /// <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 = ComponentHost.BuildParameters.EnableNodeReuse ? 
                "/nologo /nodemode:1 /nodeReuse:true" : 
                "/nologo /nodemode:1 /nodeReuse:false";

            // Make it here.
            CommunicationsUtilities.Trace("Starting to acquire a new or existing node to establish node ID {0}...", nodeId);
            NodeContext context = GetNode(null, commandLineArgs, nodeId, factory, NodeProviderOutOfProc.GetHostHandshake(ComponentHost.BuildParameters.EnableNodeReuse), NodeProviderOutOfProc.GetClientHandshake(), 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.FormatResourceString("CouldNotConnectToMSBuildExe", ComponentHost.BuildParameters.NodeExeLocation));
        }
Example #7
0
        /// <summary>
        /// Requests that a node be created on the specified machine.
        /// </summary>
        /// <param name="nodeId">The id of the node to create.</param>
        /// <param name="factory">The factory to use to create packets from this node.</param>
        /// <param name="configuration">The configuration for the node.</param>
        public bool CreateNode(int nodeId, INodePacketFactory factory, NodeConfiguration configuration)
        {
            ErrorUtilities.VerifyThrow(nodeId != InvalidInProcNodeId, "Cannot create in-proc node.");

            // Attempt to get the operating environment semaphore if requested.
            if (_componentHost.BuildParameters.SaveOperatingEnvironment)
            {
                // We can only create additional in-proc nodes if we have decided not to save the operating environment.  This is the global
                // DTAR case in Visual Studio, but other clients might enable this as well under certain special circumstances.
                ErrorUtilities.VerifyThrow(_inProcNodeOwningOperatingEnvironment == null, "Unexpected non-null in-proc node semaphore.");

                if (Environment.GetEnvironmentVariable("MSBUILDINPROCENVCHECK") == "1")
                {
                    _exclusiveOperatingEnvironment = true;
                }

                if (_exclusiveOperatingEnvironment)
                {
                    _inProcNodeOwningOperatingEnvironment = new Semaphore(1, 1, "MSBuildIPN_" + Process.GetCurrentProcess().Id);
                    if (!_inProcNodeOwningOperatingEnvironment.WaitOne(0))
                    {
                        // Can't take the operating environment.
                        return false;
                    }
                }
            }

            // If it doesn't already exist, create it.
            if (_inProcNode == null)
            {
                if (!InstantiateNode(factory))
                {
                    return false;
                }
            }

            _inProcNodeEndpoint.SendData(configuration);
            _inProcNodeId = nodeId;

            return true;
        }
Example #8
0
        /// <summary>
        /// Handles the NodeConfiguration packet.
        /// </summary>
        private void HandleNodeConfiguration(NodeConfiguration configuration)
        {
            // Set the culture.
            Thread.CurrentThread.CurrentCulture = configuration.BuildParameters.Culture;
            Thread.CurrentThread.CurrentUICulture = configuration.BuildParameters.UICulture;

            // Snapshot the initial environment.
            _savedEnvironment = CommunicationsUtilities.GetEnvironmentVariables();

            // Save the current directory.
            _savedCurrentDirectory = NativeMethodsShared.GetCurrentDirectory();

            // Set the node id.
            _componentHost.BuildParameters.NodeId = configuration.NodeId;
            _shutdownException = null;

            // And the AppDomainSetup
            _componentHost.BuildParameters.AppDomainSetup = configuration.AppDomainSetup;

            // Declare in-proc
            _componentHost.BuildParameters.IsOutOfProc = false;

            // Set the logging exception handler
            ILoggingService loggingService = _componentHost.LoggingService;
            loggingService.OnLoggingThreadException += new LoggingExceptionDelegate(OnLoggingThreadException);

            // Now prep the buildRequestEngine for the build.
            _loggingContext = new NodeLoggingContext(loggingService, configuration.NodeId, true /* inProcNode */);

            _buildRequestEngine.OnEngineException += _engineExceptionEventHandler;
            _buildRequestEngine.OnNewConfigurationRequest += _newConfigurationRequestEventHandler;
            _buildRequestEngine.OnRequestBlocked += _requestBlockedEventHandler;
            _buildRequestEngine.OnRequestComplete += _requestCompleteEventHandler;

            if (_shutdownException != null)
            {
                Exception exception;
                HandleShutdown(out exception);
                throw exception;
            }

            _buildRequestEngine.InitializeForBuild(_loggingContext);

            // Finally store off this configuration packet.
            _currentConfiguration = configuration;
        }
Example #9
0
        /// <summary>
        /// Attempts to create a node on the specified machine using the specified provider.
        /// </summary>
        /// <param name="nodeProvider">The provider used to create the node.</param>
        /// <returns>The id of the node created.</returns>
        private int AttemptCreateNode(INodeProvider nodeProvider, NodeConfiguration nodeConfiguration)
        {
            // If no provider was passed in, we obviously can't create a node.
            if (null == nodeProvider)
            {
                ErrorUtilities.ThrowInternalError("No node provider provided.");
                return InvalidNodeId;
            }

            // Are there any free slots on this provider?
            if (nodeProvider.AvailableNodes == 0)
            {
                return InvalidNodeId;
            }

            // Assign a global ID to the node we are about to create.
            int nodeId = InvalidNodeId;

            if (nodeProvider is NodeProviderInProc)
            {
                nodeId = _inprocNodeId;
            }
            else
            {
                nodeId = _nextNodeId;
                _nextNodeId++;
            }

            NodeConfiguration configToSend = nodeConfiguration.Clone();
            configToSend.NodeId = nodeId;

            // Create the node and add it to our mapping.
            bool createdNode = nodeProvider.CreateNode(nodeId, this, configToSend);

            if (!createdNode)
            {
                return InvalidNodeId;
            }

            _nodeIdToProvider.Add(nodeId, nodeProvider);
            return nodeId;
        }
Example #10
0
        /// <summary>
        /// Creates a node on an available NodeProvider, if any..
        /// </summary>
        /// <param name="configuration">The configuration to use for the remote node.</param>
        /// <returns>A NodeInfo describing the node created, or null if none could be created.</returns>
        public NodeInfo CreateNode(NodeConfiguration configuration, NodeAffinity nodeAffinity)
        {
            // We will prefer to make nodes on the "closest" providers first; in-proc, then
            // out-of-proc, then remote.
            // When we support distributed build, we will also consider the remote provider.
            int nodeId = InvalidNodeId;
            if ((nodeAffinity == NodeAffinity.Any || nodeAffinity == NodeAffinity.InProc) && !_componentHost.BuildParameters.DisableInProcNode)
            {
                nodeId = AttemptCreateNode(_inProcNodeProvider, configuration);
            }

            if (nodeId == InvalidNodeId && (nodeAffinity == NodeAffinity.Any || nodeAffinity == NodeAffinity.OutOfProc))
            {
                nodeId = AttemptCreateNode(_outOfProcNodeProvider, configuration);
            }

            if (nodeId == InvalidNodeId)
            {
                return null;
            }

            // If we created a node, they should no longer be considered shut down.
            _nodesShutdown = false;

            return new NodeInfo(nodeId, _nodeIdToProvider[nodeId].ProviderType);
        }
Example #11
0
        /// <summary>
        /// Handles the NodeConfiguration packet.
        /// </summary>
        private void HandleNodeConfiguration(NodeConfiguration configuration)
        {
            // Grab the system parameters.
            _buildParameters = configuration.BuildParameters;

            _buildParameters.ProjectRootElementCache = s_projectRootElementCache;

            // Snapshot the current environment
            _savedEnvironment = CommunicationsUtilities.GetEnvironmentVariables();

            // Change to the startup directory
            try
            {
                NativeMethodsShared.SetCurrentDirectory(BuildParameters.StartupDirectory);
            }
            catch (DirectoryNotFoundException)
            {
                // Somehow the startup directory vanished. This can happen if build was started from a USB Key and it was removed.
                NativeMethodsShared.SetCurrentDirectory(Environment.SystemDirectory);
            }

            // Replicate the environment.  First, unset any environment variables set by the previous configuration.
            if (_currentConfiguration != null)
            {
                foreach (string key in _currentConfiguration.BuildParameters.BuildProcessEnvironment.Keys)
                {
                    Environment.SetEnvironmentVariable(key, null);
                }
            }

            // Now set the new environment
            foreach (KeyValuePair<string, string> environmentPair in _buildParameters.BuildProcessEnvironment)
            {
                Environment.SetEnvironmentVariable(environmentPair.Key, environmentPair.Value);
            }

            // We want to make sure the global project collection has the toolsets which were defined on the parent
            // so that any custom toolsets defined can be picked up by tasks who may use the global project collection but are 
            // executed on the child node.
            ICollection<Toolset> parentToolSets = _buildParameters.ToolsetProvider.Toolsets;
            if (parentToolSets != null)
            {
                ProjectCollection.GlobalProjectCollection.RemoveAllToolsets();

                foreach (Toolset toolSet in parentToolSets)
                {
                    ProjectCollection.GlobalProjectCollection.AddToolset(toolSet);
                }
            }

            // Set the culture.
            Thread.CurrentThread.CurrentCulture = _buildParameters.Culture;
            Thread.CurrentThread.CurrentUICulture = _buildParameters.UICulture;

            // Get the node ID.
            _buildParameters.NodeId = configuration.NodeId;
            _buildParameters.IsOutOfProc = true;

            // And the AppDomainSetup
            _buildParameters.AppDomainSetup = configuration.AppDomainSetup;

            // Set up the logging service.
            LoggingServiceFactory loggingServiceFactory = new LoggingServiceFactory(LoggerMode.Asynchronous, configuration.NodeId);
            _componentFactories.ReplaceFactory(BuildComponentType.LoggingService, loggingServiceFactory.CreateInstance);

            _loggingService = _componentFactories.GetComponent(BuildComponentType.LoggingService) as ILoggingService;

            BuildEventArgTransportSink sink = new BuildEventArgTransportSink(SendLoggingPacket);

            _shutdownException = null;

            try
            {
                // If there are no node loggers to initialize dont do anything
                if (configuration.LoggerDescriptions != null && configuration.LoggerDescriptions.Length > 0)
                {
                    _loggingService.InitializeNodeLoggers(configuration.LoggerDescriptions, sink, configuration.NodeId);
                }
            }
            catch (Exception ex)
            {
                if (ExceptionHandling.IsCriticalException(ex))
                {
                    throw;
                }

                OnEngineException(ex);
            }

            _loggingService.OnLoggingThreadException += new LoggingExceptionDelegate(OnLoggingThreadException);

            string forwardPropertiesFromChild = Environment.GetEnvironmentVariable("MSBUILDFORWARDPROPERTIESFROMCHILD");
            string[] propertyListToSerialize = null;

            // Get a list of properties which should be serialized
            if (!String.IsNullOrEmpty(forwardPropertiesFromChild))
            {
                propertyListToSerialize = forwardPropertiesFromChild.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            }

            _loggingService.PropertiesToSerialize = propertyListToSerialize;
            _loggingService.RunningOnRemoteNode = true;

            string forwardAllProperties = Environment.GetEnvironmentVariable("MSBUILDFORWARDALLPROPERTIESFROMCHILD");
            if (String.Equals(forwardAllProperties, "1", StringComparison.OrdinalIgnoreCase) || _buildParameters.LogInitialPropertiesAndItems)
            {
                _loggingService.SerializeAllProperties = true;
            }
            else
            {
                _loggingService.SerializeAllProperties = false;
            }

            // Now prep the buildRequestEngine for the build.
            _loggingContext = new NodeLoggingContext(_loggingService, configuration.NodeId, false /* inProcNode */);

            if (_shutdownException != null)
            {
                Exception exception;
                HandleShutdown(out exception);
                throw exception;
            }

            _buildRequestEngine.InitializeForBuild(_loggingContext);

            // Finally store off this configuration packet.
            _currentConfiguration = configuration;
        }
Example #12
0
 public IList <NodeInfo> CreateNodes(NodeConfiguration configuration, NodeAffinity affinity, int numberOfNodesToCreate)
 => throw new NotSupportedException("not used");
Example #13
0
 /// <summary>
 /// Factory for deserialization.
 /// </summary>
 internal static INodePacket FactoryForDeserialization(INodePacketTranslator translator)
 {
     NodeConfiguration configuration = new NodeConfiguration();
     configuration.Translate(translator);
     return configuration;
 }