Exemple #1
0
        private bool InstantiateNode(INodePacketFactory factory)
        {
            ErrorUtilities.VerifyThrow(_inProcNode == null, "In Proc node already instantiated.");
            ErrorUtilities.VerifyThrow(_inProcNodeEndpoint == null, "In Proc node endpoint already instantiated.");

            NodeEndpointInProc.EndpointPair endpoints = NodeEndpointInProc.CreateInProcEndpoints(NodeEndpointInProc.EndpointMode.Synchronous, _componentHost);

            _inProcNodeEndpoint = endpoints.ManagerEndpoint;
            _inProcNodeEndpoint.OnLinkStatusChanged += new LinkStatusChangedDelegate(InProcNodeEndpoint_OnLinkStatusChanged);

            _packetFactory = factory;
            _inProcNode    = new InProcNode(_componentHost, endpoints.NodeEndpoint);
#if FEATURE_THREAD_CULTURE
            _inProcNodeThread = new Thread(InProcNodeThreadProc, BuildParameters.ThreadStackSize);
#else
            CultureInfo culture   = _componentHost.BuildParameters.Culture;
            CultureInfo uiCulture = _componentHost.BuildParameters.UICulture;
            _inProcNodeThread = new Thread(() =>
            {
                CultureInfo.CurrentCulture   = culture;
                CultureInfo.CurrentUICulture = uiCulture;
                InProcNodeThreadProc();
            });
#endif
            _inProcNodeThread.Name         = String.Format(CultureInfo.CurrentCulture, "In-proc Node ({0})", _componentHost.Name);
            _inProcNodeThread.IsBackground = true;
#if FEATURE_THREAD_CULTURE
            _inProcNodeThread.CurrentCulture   = _componentHost.BuildParameters.Culture;
            _inProcNodeThread.CurrentUICulture = _componentHost.BuildParameters.UICulture;
#endif
            _inProcNodeThread.Start();

            _inProcNodeEndpoint.Connect(this);

            int  connectionTimeout = CommunicationsUtilities.NodeConnectionTimeout;
            bool connected         = _endpointConnectedEvent.WaitOne(connectionTimeout);
            ErrorUtilities.VerifyThrow(connected, "In-proc node failed to start up within {0}ms", connectionTimeout);
            return(true);
        }
        /// <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);

            long        hostHandShake = NodeProviderOutOfProc.GetHostHandshake(ComponentHost.BuildParameters.EnableNodeReuse, ComponentHost.BuildParameters.LowPriority);
            NodeContext context       = GetNode(null, commandLineArgs, nodeId, factory, hostHandShake, NodeProviderOutOfProc.GetClientHandshake(ComponentHost.BuildParameters.EnableNodeReuse, ComponentHost.BuildParameters.LowPriority), 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));
        }
        /// <summary>
        /// Routes a packet.
        /// </summary>
        /// <param name="nodeId">The id of the node from which the packet is being routed.</param>
        /// <param name="packet">The packet to route.</param>
        public void RoutePacket(int nodeId, INodePacket packet)
        {
            INodePacketFactory factory = _packetFactory;

            if (_inProcNodeId != InvalidInProcNodeId)
            {
                // If this was a shutdown packet, we are done with the node.  Release all context associated with it.  Do this here, rather
                // than after we route the packet, because otherwise callbacks to the NodeManager to determine if we have available nodes
                // will report that the in-proc node is still in use when it has actually shut down.
                int savedInProcNodeId = _inProcNodeId;
                if (packet.Type == NodePacketType.NodeShutdown)
                {
                    _inProcNodeId = InvalidInProcNodeId;

                    // Release the operating environment semaphore if we were holding it.
                    if ((_componentHost.BuildParameters.SaveOperatingEnvironment) &&
                        (_inProcNodeOwningOperatingEnvironment != null))
                    {
                        _inProcNodeOwningOperatingEnvironment.Release();
                        _inProcNodeOwningOperatingEnvironment.Close();
                        _inProcNodeOwningOperatingEnvironment = null;
                    }

                    if (!_componentHost.BuildParameters.EnableNodeReuse)
                    {
                        _inProcNode         = null;
                        _inProcNodeEndpoint = null;
                        _inProcNodeThread   = null;
                        _packetFactory      = null;
                    }
                }

                // Route the packet back to the NodeManager.
                factory.RoutePacket(savedInProcNodeId, packet);
            }
        }
        /// <summary>
        /// Routes a packet.
        /// </summary>
        /// <param name="nodeId">The id of the node from which the packet is being routed.</param>
        /// <param name="packet">The packet to route.</param>
        public void RoutePacket(int nodeId, INodePacket packet)
        {
            INodePacketFactory factory = _packetFactory;

            if (_inProcNodeId != InvalidInProcNodeId)
            {
                // If this was a shutdown packet, we are done with the node.  Release all context associated with it.  Do this here, rather
                // than after we route the packet, because otherwise callbacks to the NodeManager to determine if we have available nodes
                // will report that the in-proc node is still in use when it has actually shut down.
                int savedInProcNodeId = _inProcNodeId;
                if (packet.Type == NodePacketType.NodeShutdown)
                {
                    _inProcNodeId = InvalidInProcNodeId;

                    // Release the operating environment semaphore if we were holding it.
                    if ((_componentHost.BuildParameters.SaveOperatingEnvironment) &&
                        (_inProcNodeOwningOperatingEnvironment != null))
                    {
                        _inProcNodeOwningOperatingEnvironment.Release();
                        _inProcNodeOwningOperatingEnvironment.Close();
                        _inProcNodeOwningOperatingEnvironment = null;
                    }

                    if (!_componentHost.BuildParameters.EnableNodeReuse)
                    {
                        _inProcNode = null;
                        _inProcNodeEndpoint = null;
                        _inProcNodeThread = null;
                        _packetFactory = null;
                    }
                }

                // Route the packet back to the NodeManager.
                factory.RoutePacket(savedInProcNodeId, packet);
            }
        }
        /// <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;
        }
        /// <summary>
        /// Instantiates a new MSBuild or MSBuildTaskHost process acting as a child node.
        /// </summary>
        internal bool CreateNode(TaskHostContext hostContext, INodePacketFactory factory, INodePacketHandler handler, TaskHostConfiguration configuration)
        {
            ErrorUtilities.VerifyThrowArgumentNull(factory, "factory");
            ErrorUtilities.VerifyThrow(!_nodeIdToPacketFactory.ContainsKey((int)hostContext), "We should not already have a factory for this context!  Did we forget to call DisconnectFromHost somewhere?");

            if (AvailableNodes == 0)
            {
                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 2, to indicate that we 
            // want to start up an MSBuild task host node. 
            string commandLineArgs = " /nologo /nodemode:2 ";
            string msbuildLocation = GetMSBuildLocationFromHostContext(hostContext);

            // we couldn't even figure out the location we're trying to launch ... just go ahead and fail.  
            if (msbuildLocation == null)
            {
                return false;
            }

            CommunicationsUtilities.Trace("For a host context of {0}, spawning executable from {1}.", hostContext.ToString(), msbuildLocation ?? "MSBuild.exe");

            // Make it here.
            NodeContext context = GetNode
                                    (
                                        msbuildLocation,
                                        commandLineArgs,
                                        (int)hostContext,
                                        this,
                                        CommunicationsUtilities.GetTaskHostHostHandshake(hostContext),
                                        CommunicationsUtilities.GetTaskHostClientHandshake(hostContext),
                                        NodeContextTerminated
                                    );

            if (null != context)
            {
                _nodeContexts[hostContext] = context;

                // Start the asynchronous read.
                context.BeginAsyncPacketRead();

                _activeNodes.Add((int)hostContext);
                _noNodesActiveEvent.Reset();

                return true;
            }

            return false;
        }
Exemple #7
0
        /// <summary>
        /// Finds or creates a child process which can act as a node.
        /// </summary>
        /// <returns>The pipe stream representing the node.</returns>
        protected NodeContext GetNode(string msbuildLocation, string commandLineArgs, int nodeId, INodePacketFactory factory, Handshake hostHandshake, NodeContextTerminateDelegate terminateNode)
        {
#if DEBUG
            if (Execution.BuildManager.WaitForDebugger)
            {
                commandLineArgs += " /wfd";
            }
#endif

            if (String.IsNullOrEmpty(msbuildLocation))
            {
                msbuildLocation = _componentHost.BuildParameters.NodeExeLocation;
            }

            if (String.IsNullOrEmpty(msbuildLocation))
            {
                string msbuildExeName = Environment.GetEnvironmentVariable("MSBUILD_EXE_NAME");

                if (!String.IsNullOrEmpty(msbuildExeName))
                {
                    // we assume that MSBUILD_EXE_NAME is, in fact, just the name.
                    msbuildLocation = Path.Combine(msbuildExeName, ".exe");
                }
            }

#if FEATURE_NODE_REUSE
            // Try to connect to idle nodes if node reuse is enabled.
            if (_componentHost.BuildParameters.EnableNodeReuse)
            {
                (string expectedProcessName, List <Process> processes)runningNodesTuple = GetPossibleRunningNodes(msbuildLocation);

                CommunicationsUtilities.Trace("Attempting to connect to each existing {1} process in turn to establish node {0}...", nodeId, runningNodesTuple.expectedProcessName);
                foreach (Process nodeProcess in runningNodesTuple.processes)
                {
                    if (nodeProcess.Id == Process.GetCurrentProcess().Id)
                    {
                        continue;
                    }

                    // Get the full context of this inspection so that we can always skip this process when we have the same taskhost context
                    string nodeLookupKey = GetProcessesToIgnoreKey(hostHandshake, nodeProcess.Id);
                    if (_processesToIgnore.Contains(nodeLookupKey))
                    {
                        continue;
                    }

                    // We don't need to check this again
                    _processesToIgnore.Add(nodeLookupKey);

                    // Attempt to connect to each process in turn.
                    Stream nodeStream = TryConnectToProcess(nodeProcess.Id, 0 /* poll, don't wait for connections */, hostHandshake);
                    if (nodeStream != null)
                    {
                        // Connection successful, use this node.
                        CommunicationsUtilities.Trace("Successfully connected to existed node {0} which is PID {1}", nodeId, nodeProcess.Id);
                        return(new NodeContext(nodeId, nodeProcess, nodeStream, factory, terminateNode));
                    }
                }
            }
#endif

            // None of the processes we tried to connect to allowed a connection, so create a new one.
            // We try this in a loop because it is possible that there is another MSBuild multiproc
            // host process running somewhere which is also trying to create nodes right now.  It might
            // find our newly created node and connect to it before we get a chance.
            CommunicationsUtilities.Trace("Could not connect to existing process, now creating a process...");
            int retries = NodeCreationRetries;
            while (retries-- > 0)
            {
#if FEATURE_NET35_TASKHOST
                // We will also check to see if .NET 3.5 is installed in the case where we need to launch a CLR2 OOP TaskHost.
                // Failure to detect this has been known to stall builds when Windows pops up a related dialog.
                // It's also a waste of time when we attempt several times to launch multiple MSBuildTaskHost.exe (CLR2 TaskHost)
                // nodes because we should never be able to connect in this case.
                string taskHostNameForClr2TaskHost = Path.GetFileNameWithoutExtension(NodeProviderOutOfProcTaskHost.TaskHostNameForClr2TaskHost);
                if (Path.GetFileNameWithoutExtension(msbuildLocation).Equals(taskHostNameForClr2TaskHost, StringComparison.OrdinalIgnoreCase))
                {
                    if (FrameworkLocationHelper.GetPathToDotNetFrameworkV35(DotNetFrameworkArchitecture.Current) == null)
                    {
                        CommunicationsUtilities.Trace
                        (
                            "Failed to launch node from {0}. The required .NET Framework v3.5 is not installed or enabled. CommandLine: {1}",
                            msbuildLocation,
                            commandLineArgs
                        );

                        string nodeFailedToLaunchError = ResourceUtilities.GetResourceString("TaskHostNodeFailedToLaunchErrorCodeNet35NotInstalled");
                        throw new NodeFailedToLaunchException(null, nodeFailedToLaunchError);
                    }
                }
#endif

                // Create the node process
                Process msbuildProcess = LaunchNode(msbuildLocation, commandLineArgs);
                _processesToIgnore.Add(GetProcessesToIgnoreKey(hostHandshake, msbuildProcess.Id));

                // Note, when running under IMAGEFILEEXECUTIONOPTIONS registry key to debug, the process ID
                // gotten back from CreateProcess is that of the debugger, which causes this to try to connect
                // to the debugger process. Instead, use MSBUILDDEBUGONSTART=1

                // Now try to connect to it.
                Stream nodeStream = TryConnectToProcess(msbuildProcess.Id, TimeoutForNewNodeCreation, hostHandshake);
                if (nodeStream != null)
                {
                    // Connection successful, use this node.
                    CommunicationsUtilities.Trace("Successfully connected to created node {0} which is PID {1}", nodeId, msbuildProcess.Id);
                    return(new NodeContext(nodeId, msbuildProcess, nodeStream, factory, terminateNode));
                }
            }

            // We were unable to launch a node.
            CommunicationsUtilities.Trace("FAILED TO CONNECT TO A CHILD NODE");
            return(null);
        }
 /// <summary>
 /// Causes this node to connect to the matched endpoint.
 /// </summary>
 /// <param name="factory">The factory used to create packets.</param>
 public void Connect(INodePacketFactory factory)
 {
     ErrorUtilities.ThrowInternalError("Connect() not valid on the out of proc endpoint.");
 }
        /// <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));
        }
        /// <summary>
        /// Finds or creates a child process which can act as a node.
        /// </summary>
        /// <returns>The pipe stream representing the node.</returns>
        protected NodeContext GetNode(string msbuildLocation, string commandLineArgs, int nodeId, INodePacketFactory factory, long hostHandshake, long clientHandshake, NodeContextTerminateDelegate terminateNode)
        {
            if (String.IsNullOrEmpty(msbuildLocation))
            {
                msbuildLocation = _componentHost.BuildParameters.NodeExeLocation;
            }

            if (String.IsNullOrEmpty(msbuildLocation))
            {
                string msbuildExeName = Environment.GetEnvironmentVariable("MSBUILD_EXE_NAME");

                if (!String.IsNullOrEmpty(msbuildExeName))
                {
                    // we assume that MSBUILD_EXE_NAME is, in fact, just the name.  
                    msbuildLocation = Path.Combine(msbuildExeName, ".exe");
                }
            }

            if (String.IsNullOrEmpty(msbuildLocation))
            {
                msbuildLocation = "MSBuild.exe";
            }

            string msbuildName = Path.GetFileNameWithoutExtension(msbuildLocation);

            List<Process> nodeProcesses = new List<Process>(Process.GetProcessesByName(msbuildName));

            // Trivial sort to try to prefer most recently used nodes
            nodeProcesses.Sort
                (
                delegate (Process left, Process right)
                {
                    return left.Id - right.Id;
                }

                );

            CommunicationsUtilities.Trace("Attempting to connect to each existing msbuild.exe process in turn to establish node {0}...", nodeId);
            foreach (Process nodeProcess in nodeProcesses)
            {
                if (nodeProcess.Id == Process.GetCurrentProcess().Id)
                {
                    continue;
                }

                // Get the full context of this inspection so that we can always skip this process when we have the same taskhost context
                string nodeLookupKey = GetProcessesToIgnoreKey(hostHandshake, clientHandshake, nodeProcess.Id);
                if (_processesToIgnore.Contains(nodeLookupKey))
                {
                    continue;
                }

                // We don't need to check this again
                _processesToIgnore.Add(nodeLookupKey);

                // Attempt to connect to each process in turn.
                NamedPipeClientStream nodeStream = TryConnectToProcess(nodeProcess.Id, 0 /* poll, don't wait for connections */, hostHandshake, clientHandshake);
                if (nodeStream != null)
                {
                    // Connection successful, use this node.   
                    CommunicationsUtilities.Trace("Successfully connected to existed node {0} which is PID {1}", nodeId, nodeProcess.Id);
                    return new NodeContext(nodeId, nodeProcess.Id, nodeStream, factory, terminateNode);
                }
            }

            // None of the processes we tried to connect to allowed a connection, so create a new one.
            // We try this in a loop because it is possible that there is another MSBuild multiproc
            // host process running somewhere which is also trying to create nodes right now.  It might
            // find our newly created node and connect to it before we get a chance.
            CommunicationsUtilities.Trace("Could not connect to existing process, now creating a process...");
            int retries = NodeCreationRetries;
            while (retries-- > 0)
            {
                // We will also check to see if .NET 3.5 is installed in the case where we need to launch a CLR2 OOP TaskHost.
                // Failure to detect this has been known to stall builds when Windows pops up a related dialog.
                // It's also a waste of time when we attempt several times to launch multiple MSBuildTaskHost.exe (CLR2 TaskHost)
                // nodes because we should never be able to connect in this case.
                string taskHostNameForClr2TaskHost = Path.GetFileNameWithoutExtension(NodeProviderOutOfProcTaskHost.TaskHostNameForClr2TaskHost);
                if (msbuildName.Equals(taskHostNameForClr2TaskHost, StringComparison.OrdinalIgnoreCase))
                {
                    if (FrameworkLocationHelper.GetPathToDotNetFrameworkV35(DotNetFrameworkArchitecture.Current) == null)
                    {
                        CommunicationsUtilities.Trace
                            (
                                "Failed to launch node from {0}. The required .NET Framework v3.5 is not installed or enabled. CommandLine: {1}",
                                msbuildLocation,
                                commandLineArgs
                            );

                        string nodeFailedToLaunchError = ResourceUtilities.FormatResourceString("TaskHostNodeFailedToLaunchErrorCodeNet35NotInstalled");
                        throw new NodeFailedToLaunchException(null, nodeFailedToLaunchError);
                    }
                }

                // Create the node process
                int msbuildProcessId = LaunchNode(msbuildLocation, commandLineArgs);
                _processesToIgnore.Add(GetProcessesToIgnoreKey(hostHandshake, clientHandshake, msbuildProcessId));

                // Note, when running under IMAGEFILEEXECUTIONOPTIONS registry key to debug, the process ID
                // gotten back from CreateProcess is that of the debugger, which causes this to try to connect
                // to the debugger process. Instead, use MSBUILDDEBUGONSTART=1

                // Now try to connect to it.
                NamedPipeClientStream nodeStream = TryConnectToProcess(msbuildProcessId, TimeoutForNewNodeCreation, hostHandshake, clientHandshake);
                if (nodeStream != null)
                {
                    // Connection successful, use this node.
                    CommunicationsUtilities.Trace("Successfully connected to created node {0} which is PID {1}", nodeId, msbuildProcessId);
                    return new NodeContext(nodeId, msbuildProcessId, nodeStream, factory, terminateNode);
                }
            }

            // We were unable to launch a node.
            CommunicationsUtilities.Trace("FAILED TO CONNECT TO A CHILD NODE");
            return null;
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 public NodeContext(int nodeId, int processId, NamedPipeClientStream nodePipe, INodePacketFactory factory, NodeContextTerminateDelegate terminateDelegate)
 {
     _nodeId = nodeId;
     _processId = processId;
     _nodePipe = nodePipe;
     _packetFactory = factory;
     _headerByte = new byte[5]; // 1 for the packet type, 4 for the body length
     _smallReadBuffer = new byte[1000]; // 1000 was just an average seen on one profile run.
     _nodeTerminated = new ManualResetEvent(false);
     _terminateDelegate = terminateDelegate;
     _sharedReadBuffer = InterningBinaryReader.CreateSharedBuffer();
 }
        /// <summary>
        /// Causes this endpoint to wait for the remote endpoint to connect
        /// </summary>
        /// <param name="factory">The factory used to create packets.</param>
        public void Listen(INodePacketFactory factory)
        {
            ErrorUtilities.VerifyThrow(_status == LinkStatus.Inactive, "Link not inactive.  Status is {0}", _status);
            ErrorUtilities.VerifyThrowArgumentNull(factory, "factory");
            _packetFactory = factory;

            InitializeAsyncPacketThread();
        }
 /// <summary>
 /// Causes this node to connect to the matched endpoint.  
 /// </summary>
 /// <param name="factory">The factory used to create packets.</param>
 public void Connect(INodePacketFactory factory)
 {
     ErrorUtilities.ThrowInternalError("Connect() not valid on the out of proc endpoint.");
 }
 public IList <NodeInfo> CreateNodes(int nextNodeId, INodePacketFactory packetFactory, Func <NodeInfo, NodeConfiguration> configurationFactory, int numberOfNodesToCreate)
 {
     throw new NotImplementedException("Use the other overload of CreateNode instead");
 }
        /// <summary>
        /// Causes this node to connect to the matched endpoint.  
        /// </summary>
        /// <param name="factory">Unused</param>
        public void Connect(INodePacketFactory factory)
        {
            ErrorUtilities.VerifyThrowInternalNull(factory, "factory");
            _packetFactory = factory;

            // Set up asynchronous packet pump, if necessary.
            if (_mode == EndpointMode.Asynchronous)
            {
                InitializeAsyncPacketThread();
            }

            // Notify the Build Manager-side endpoint that the connection is now active.
            _peerEndpoint.SetPeerNodeConnected();
        }
        /// <summary>
        /// Causes this endpoint to wait for the remote endpoint to connect
        /// </summary>
        /// <param name="factory">Unused</param>
        public void Listen(INodePacketFactory factory)
        {
            ErrorUtilities.VerifyThrowInternalNull(factory, "factory");
            _packetFactory = factory;

            // Initialize our thread in async mode so we are ready when the Node-side endpoint "connects".
            if (_mode == EndpointMode.Asynchronous)
            {
                InitializeAsyncPacketThread();
            }

            _peerEndpoint.SetPeerNodeConnected();
        }
        /// <summary>
        /// Creates a new in-proc node.
        /// </summary>
        private bool InstantiateNode(INodePacketFactory factory)
        {
            ErrorUtilities.VerifyThrow(null == _inProcNode, "In Proc node already instantiated.");
            ErrorUtilities.VerifyThrow(null == _inProcNodeEndpoint, "In Proc node endpoint already instantiated.");

            NodeEndpointInProc.EndpointPair endpoints = NodeEndpointInProc.CreateInProcEndpoints(NodeEndpointInProc.EndpointMode.Synchronous, _componentHost);

            _inProcNodeEndpoint = endpoints.ManagerEndpoint;
            _inProcNodeEndpoint.OnLinkStatusChanged += new LinkStatusChangedDelegate(InProcNodeEndpoint_OnLinkStatusChanged);

            _packetFactory = factory;
            _inProcNode = new InProcNode(_componentHost, endpoints.NodeEndpoint);

            _inProcNodeThread = new Thread(InProcNodeThreadProc, BuildParameters.ThreadStackSize);
            _inProcNodeThread.Name = String.Format(CultureInfo.CurrentCulture, "In-proc Node ({0})", _componentHost.Name);
            _inProcNodeThread.IsBackground = true;
            _inProcNodeThread.CurrentCulture = _componentHost.BuildParameters.Culture;
            _inProcNodeThread.CurrentUICulture = _componentHost.BuildParameters.UICulture;
            _inProcNodeThread.Start();

            _inProcNodeEndpoint.Connect(this);

            int connectionTimeout = CommunicationsUtilities.NodeConnectionTimeout;
            bool connected = _endpointConnectedEvent.WaitOne(connectionTimeout, false);
            ErrorUtilities.VerifyThrow(connected, "In-proc node failed to start up within {0}ms", connectionTimeout);
            return true;
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 public NodeContext(int nodeId, int processId, NamedPipeClientStream nodePipe, INodePacketFactory factory, NodeContextTerminateDelegate terminateDelegate)
 {
     _nodeId            = nodeId;
     _processId         = processId;
     _nodePipe          = nodePipe;
     _packetFactory     = factory;
     _headerByte        = new byte[5];    // 1 for the packet type, 4 for the body length
     _smallReadBuffer   = new byte[1000]; // 1000 was just an average seen on one profile run.
     _nodeTerminated    = new ManualResetEvent(false);
     _terminateDelegate = terminateDelegate;
     _sharedReadBuffer  = InterningBinaryReader.CreateSharedBuffer();
 }
Exemple #19
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>
        /// Make sure a node in the requested context exists.  
        /// </summary>
        internal bool AcquireAndSetUpHost(TaskHostContext hostContext, INodePacketFactory factory, INodePacketHandler handler, TaskHostConfiguration configuration)
        {
            NodeContext context = null;
            bool nodeCreationSucceeded = false;

            if (!(_nodeContexts.TryGetValue(hostContext, out context)))
            {
                nodeCreationSucceeded = CreateNode(hostContext, factory, handler, configuration);
            }
            else
            {
                // node already exists, so "creation" automatically succeeded
                nodeCreationSucceeded = true;
            }

            if (nodeCreationSucceeded)
            {
                context = _nodeContexts[hostContext];
                _nodeIdToPacketFactory[(int)hostContext] = factory;
                _nodeIdToPacketHandler[(int)hostContext] = handler;

                // Configure the node.
                context.SendData(configuration);
                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)
 {
     throw new NotImplementedException("Use the other overload of CreateNode instead");
 }
Exemple #22
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;
        }