/// <summary>
        /// Expected to be called when TaskHostTask is done with host of the given context.  
        /// </summary>
        internal void DisconnectFromHost(TaskHostContext hostContext)
        {
            ErrorUtilities.VerifyThrow(_nodeIdToPacketFactory.ContainsKey((int)hostContext) && _nodeIdToPacketHandler.ContainsKey((int)hostContext), "Why are we trying to disconnect from a context that we already disconnected from?  Did we call DisconnectFromHost twice?");

            _nodeIdToPacketFactory.Remove((int)hostContext);
            _nodeIdToPacketHandler.Remove((int)hostContext);
        }
        /// <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;
        }
        /// <summary>
        /// Given a TaskHostContext, return the appropriate location of the 
        /// executable (MSBuild or MSBuildTaskHost) that we wish to use, or null
        /// if that location cannot be resolved.  
        /// </summary>
        internal static string GetMSBuildLocationFromHostContext(TaskHostContext hostContext)
        {
            string toolName = GetTaskHostNameFromHostContext(hostContext);
            string toolPath = null;

            if (s_baseTaskHostPath == null)
            {
                Toolset currentToolset = ProjectCollection.GlobalProjectCollection.GetToolset(MSBuildConstants.CurrentToolsVersion);

                if (currentToolset != null)
                {
                    ProjectPropertyInstance toolsPath32 = null;

                    if (!currentToolset.Properties.TryGetValue("MSBuildToolsPath32", out toolsPath32))
                    {
                        // ... This is a very weird toolset.  But try falling back to the base ToolsPath since we 
                        // know for a fact that that will always exist. 
                        s_baseTaskHostPath = currentToolset.ToolsPath;
                    }
                    else
                    {
                        s_baseTaskHostPath = toolsPath32.EvaluatedValue;
                    }
                }
            }

            if (s_baseTaskHostPath64 == null && s_baseTaskHostPath != null)
            {
                s_baseTaskHostPath64 = Path.Combine(s_baseTaskHostPath, "amd64");
                if (!Directory.Exists(s_baseTaskHostPath64))
                {
                    // time to give up
                    s_baseTaskHostPath64 = null;
                }
            }

            switch (hostContext)
            {
                case TaskHostContext.X32CLR2:
                    if (s_pathToX32Clr2 == null)
                    {
                        s_pathToX32Clr2 = Environment.GetEnvironmentVariable("MSBUILDTASKHOSTLOCATION");
                        if (s_pathToX32Clr2 == null || !FileUtilities.FileExistsNoThrow(Path.Combine(s_pathToX32Clr2, toolName)))
                        {
                            s_pathToX32Clr2 = s_baseTaskHostPath;
                        }
                    }

                    toolPath = s_pathToX32Clr2;
                    break;
                case TaskHostContext.X64CLR2:
                    if (s_pathToX64Clr2 == null)
                    {
                        s_pathToX64Clr2 = Environment.GetEnvironmentVariable("MSBUILDTASKHOSTLOCATION64");

                        if (s_pathToX64Clr2 == null || !FileUtilities.FileExistsNoThrow(Path.Combine(s_pathToX64Clr2, toolName)))
                        {
                            s_pathToX64Clr2 = s_baseTaskHostPath64;
                        }
                    }

                    toolPath = s_pathToX64Clr2;
                    break;
                case TaskHostContext.X32CLR4:
                    if (s_pathToX32Clr4 == null)
                    {
                        s_pathToX32Clr4 = s_baseTaskHostPath;
                    }

                    toolPath = s_pathToX32Clr4;
                    break;
                case TaskHostContext.X64CLR4:
                    if (s_pathToX64Clr4 == null)
                    {
                        s_pathToX64Clr4 = s_baseTaskHostPath64;
                    }

                    toolPath = s_pathToX64Clr4;
                    break;
                default:
                    ErrorUtilities.ThrowInternalErrorUnreachable();
                    break;
            }

            if (toolName != null && toolPath != null)
            {
                return Path.Combine(toolPath, toolName);
            }
            else
            {
                return null;
            }
        }
        /// <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>
        /// Sends data to the specified node.
        /// </summary>
        /// <param name="hostContext">The node to which data shall be sent.</param>
        /// <param name="packet">The packet to send.</param>
        public void SendData(TaskHostContext hostContext, INodePacket packet)
        {
            ErrorUtilities.VerifyThrow(_nodeContexts.ContainsKey(hostContext), "Invalid host context specified: {0}.", hostContext.ToString());

            SendData(_nodeContexts[hostContext], packet);
        }
        /// <summary>
        /// Given a TaskHostContext, returns the name of the executable we should be searching for. 
        /// </summary>
        internal static string GetTaskHostNameFromHostContext(TaskHostContext hostContext)
        {
            if (hostContext == TaskHostContext.X64CLR4 || hostContext == TaskHostContext.X32CLR4)
            {
                if (s_msbuildName == null)
                {
                    s_msbuildName = Environment.GetEnvironmentVariable("MSBUILD_EXE_NAME");

                    if (s_msbuildName == null)
                    {
                        s_msbuildName = "MSBuild.exe";
                    }
                }

                return s_msbuildName;
            }
            else if (hostContext == TaskHostContext.X32CLR2 || hostContext == TaskHostContext.X64CLR2)
            {
                return TaskHostNameForClr2TaskHost;
            }
            else
            {
                ErrorUtilities.ThrowInternalErrorUnreachable();
                return null;
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Add the task host context to this handshake, to make sure that task hosts with different contexts 
 /// will have different handshakes.  Shift it into the upper 32-bits to avoid running into the 
 /// session ID.
 /// </summary>
 /// <param name="hostContext">TaskHostContext</param>
 /// <returns>Base Handshake</returns>
 private static long GetBaseHandshakeForContext(TaskHostContext hostContext)
 {
     long baseHandshake = ((long)hostContext << 40) | ((long)FileVersionHash << 8);
     return baseHandshake;
 }
        /// <summary>
        /// Given a TaskHostContext, return the appropriate location of the 
        /// executable (MSBuild or MSBuildTaskHost) that we wish to use, or null
        /// if that location cannot be resolved.  
        /// </summary>
        internal static string GetMSBuildLocationFromHostContext(TaskHostContext hostContext)
        {
            string toolName = GetTaskHostNameFromHostContext(hostContext);
            string toolPath = null;

            s_baseTaskHostPath = BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32;
            s_baseTaskHostPath64 = BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64;

            switch (hostContext)
            {
                case TaskHostContext.X32CLR2:
                    if (s_pathToX32Clr2 == null)
                    {
                        s_pathToX32Clr2 = Environment.GetEnvironmentVariable("MSBUILDTASKHOSTLOCATION");
                        if (s_pathToX32Clr2 == null || !FileUtilities.FileExistsNoThrow(Path.Combine(s_pathToX32Clr2, toolName)))
                        {
                            s_pathToX32Clr2 = s_baseTaskHostPath;
                        }
                    }

                    toolPath = s_pathToX32Clr2;
                    break;
                case TaskHostContext.X64CLR2:
                    if (s_pathToX64Clr2 == null)
                    {
                        s_pathToX64Clr2 = Environment.GetEnvironmentVariable("MSBUILDTASKHOSTLOCATION64");

                        if (s_pathToX64Clr2 == null || !FileUtilities.FileExistsNoThrow(Path.Combine(s_pathToX64Clr2, toolName)))
                        {
                            s_pathToX64Clr2 = s_baseTaskHostPath64;
                        }
                    }

                    toolPath = s_pathToX64Clr2;
                    break;
                case TaskHostContext.X32CLR4:
                    if (s_pathToX32Clr4 == null)
                    {
                        s_pathToX32Clr4 = s_baseTaskHostPath;
                    }

                    toolPath = s_pathToX32Clr4;
                    break;
                case TaskHostContext.X64CLR4:
                    if (s_pathToX64Clr4 == null)
                    {
                        s_pathToX64Clr4 = s_baseTaskHostPath64;
                    }

                    toolPath = s_pathToX64Clr4;
                    break;
                default:
                    ErrorUtilities.ThrowInternalErrorUnreachable();
                    break;
            }

            if (toolName != null && toolPath != null)
            {
                return Path.Combine(toolPath, toolName);
            }

            return null;
        }
Exemplo n.º 9
0
 /// <summary>
 /// Magic number sent by the host to the client during the handshake.
 /// Derived from the binary timestamp to avoid mixing binary versions.
 /// </summary>
 internal static long GetTaskHostHostHandshake(TaskHostContext hostContext)
 {
     long baseHandshake = GenerateHostHandshakeFromBase(GetBaseHandshakeForContext(hostContext), GetTaskHostClientHandshake(hostContext));
     return baseHandshake;
 }
Exemplo n.º 10
0
 /// <summary>
 /// Magic number sent by the client to the host during the handshake.
 /// Munged version of the host handshake.
 /// </summary>
 internal static long GetTaskHostClientHandshake(TaskHostContext hostContext)
 {
     // Mask out the first byte. That's because old
     // builds used a single, non zero initial byte,
     // and we don't want to risk communicating with them
     long clientHandshake = ((GetBaseHandshakeForContext(hostContext) ^ Int64.MaxValue) & 0x00FFFFFFFFFFFFFF);
     return clientHandshake;
 }
Exemplo n.º 11
0
        /// <summary>
        /// Since we log that we weren't able to connect to the task host in a couple of different places,
        /// extract it out into a separate method. 
        /// </summary>
        private void LogErrorUnableToCreateTaskHost(TaskHostContext requiredContext, string runtime, string architecture, NodeFailedToLaunchException e)
        {
            string msbuildLocation = NodeProviderOutOfProcTaskHost.GetMSBuildLocationFromHostContext(requiredContext);

            if (msbuildLocation == null)
            {
                // We don't know the path -- probably we're trying to get a 64-bit assembly on a 
                // 32-bit machine.  At least give them the exe name to look for, though ...
                switch (requiredContext)
                {
                    case TaskHostContext.X32CLR2:
                    case TaskHostContext.X64CLR2:
                        msbuildLocation = "MSBuildTaskHost.exe";
                        break;
                    case TaskHostContext.X32CLR4:
                    case TaskHostContext.X64CLR4:
                        msbuildLocation = "MSBuild.exe";
                        break;
                    case TaskHostContext.Invalid:
                    default:
                        ErrorUtilities.ThrowInternalErrorUnreachable();
                        break;
                }
            }

            if (e == null)
            {
                _taskLoggingContext.LogError(new BuildEventFileInfo(_taskLocation), "TaskHostAcquireFailed", _taskType.Type.Name, runtime, architecture, msbuildLocation);
            }
            else
            {
                _taskLoggingContext.LogError(new BuildEventFileInfo(_taskLocation), "TaskHostNodeFailedToLaunch", _taskType.Type.Name, runtime, architecture, msbuildLocation, e.ErrorCode, e.Message);
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Executes the task.
        /// </summary>
        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,
                        _appDomainSetup,
                        BuildEngine.LineNumberOfTaskNode,
                        BuildEngine.ColumnNumberOfTaskNode,
                        BuildEngine.ProjectFileOfTaskNode,
                        BuildEngine.ContinueOnError,
                        _taskType.Type.FullName,
                        _taskType.Type.Assembly.Location,
                        _setParameters
                    );

            try
            {
                lock (_taskHostLock)
                {
                    _requiredContext = CommunicationsUtilities.GetTaskHostContext(_taskHostParameters);
                    _connectedToTaskHost = _taskHostProvider.AcquireAndSetUpHost(_requiredContext, this, this, hostConfiguration);
                }

                if (_connectedToTaskHost)
                {
                    try
                    {
                        bool taskFinished = false;

                        while (!taskFinished)
                        {
                            _packetReceivedEvent.WaitOne();

                            INodePacket packet = null;

                            int packetCount = _receivedPackets.Count;

                            // Handle the packet that's coming in
                            while (packetCount > 0)
                            {
                                lock (_receivedPackets)
                                {
                                    if (_receivedPackets.Count > 0)
                                    {
                                        packet = _receivedPackets.Dequeue();
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                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;
        }
Exemplo n.º 13
0
        /// <summary>
        /// Add the task host context to this handshake, to make sure that task hosts with different contexts
        /// will have different handshakes.  Shift it into the upper 32-bits to avoid running into the
        /// session ID.
        /// </summary>
        /// <param name="hostContext">TaskHostContext</param>
        /// <returns>Base Handshake</returns>
        private static long GetBaseHandshakeForContext(TaskHostContext hostContext)
        {
            long baseHandshake = ((long)hostContext << 40) | ((long)FileVersionHash << 8);

            return(baseHandshake);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Magic number sent by the host to the client during the handshake.
        /// Derived from the binary timestamp to avoid mixing binary versions.
        /// </summary>
        internal static long GetTaskHostHostHandshake(TaskHostContext hostContext)
        {
            long baseHandshake = GenerateHostHandshakeFromBase(GetBaseHandshakeForContext(hostContext), GetTaskHostClientHandshake(hostContext));

            return(baseHandshake);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Executes the task.
        /// </summary>
        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),
                    _setParameters,
                    new Dictionary <string, string>(_buildComponentHost.BuildParameters.GlobalProperties)
                );

            try
            {
                lock (_taskHostLock)
                {
                    _requiredContext     = CommunicationsUtilities.GetTaskHostContext(_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);
        }