Ejemplo n.º 1
0
        /// <summary>
        /// Factory for deserialization.
        /// </summary>
        internal static INodePacket FactoryForDeserialization(INodePacketTranslator translator)
        {
            TaskHostTaskComplete taskComplete = new TaskHostTaskComplete();

            taskComplete.Translate(translator);
            return(taskComplete);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Task completed executing in the task host
        /// </summary>
        private void HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
        {
            // If it crashed, or if it failed, it didn't succeed.
            _taskExecutionSucceeded = taskHostTaskComplete.TaskResult == TaskCompleteType.Success ? true : false;

            // reset the environment, as though the task were executed in this process all along.
            CommunicationsUtilities.SetEnvironment(taskHostTaskComplete.BuildProcessEnvironment);

            // If it crashed during the execution phase, then we can effectively replicate the inproc task execution
            // behaviour by just throwing here and letting the taskbuilder code take care of it the way it would
            // have normally.
            // We will also replicate the same behaviour if the TaskHost caught some exceptions after execution of the task.
            if ((taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedDuringExecution) ||
                (taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedAfterExecution))
            {
                throw new TargetInvocationException(taskHostTaskComplete.TaskException);
            }

            // On the other hand, if it crashed during initialization, there's not really a way to effectively replicate
            // the inproc behavior -- in the inproc case, the task would have failed to load and crashed long before now.
            // Furthermore, if we were just to throw here like in the execution case, we'd lose the ability to log
            // different messages based on the circumstances of the initialization failure -- whether it was a setter failure,
            // the task just could not be loaded, etc.

            // So instead, when we catch the exception in the task host, we'll also record what message we want it to use
            // when the error is logged; and given that information, log that error here.  This has the effect of differing
            // from the inproc case insofar as ContinueOnError is now respected, instead of forcing a stop here.
            if (taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedDuringInitialization)
            {
                string   exceptionMessage;
                string[] exceptionMessageArgs;

                if (taskHostTaskComplete.TaskExceptionMessage != null)
                {
                    exceptionMessage     = taskHostTaskComplete.TaskExceptionMessage;
                    exceptionMessageArgs = taskHostTaskComplete.TaskExceptionMessageArgs;
                }
                else
                {
                    exceptionMessage     = "TaskInstantiationFailureError";
                    exceptionMessageArgs = new string[] { _taskType.Type.Name,
                                                          AssemblyUtilities.GetAssemblyLocation(_taskType.Type.GetTypeInfo().Assembly),
                                                          string.Empty };
                }

                _taskLoggingContext.LogFatalError(taskHostTaskComplete.TaskException, new BuildEventFileInfo(_taskLocation), taskHostTaskComplete.TaskExceptionMessage, taskHostTaskComplete.TaskExceptionMessageArgs);
            }

            // Set the output parameters for later
            foreach (KeyValuePair <string, TaskParameter> outputParam in taskHostTaskComplete.TaskOutputParameters)
            {
                _setParameters[outputParam.Key] = outputParam.Value?.WrappedParameter;
            }
        }
        public void TestTranslationWithNullDictionary()
        {
            TaskHostTaskComplete complete = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.Success), null);

            ((INodePacketTranslatable)complete).Translate(TranslationHelpers.GetWriteTranslator());
            INodePacket packet = TaskHostTaskComplete.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());

            TaskHostTaskComplete deserializedComplete = packet as TaskHostTaskComplete;

            Assert.AreEqual(complete.TaskResult, deserializedComplete.TaskResult);
            Assert.IsNotNull(deserializedComplete.TaskOutputParameters);
            Assert.AreEqual(0, deserializedComplete.TaskOutputParameters.Count);
        }
        public void TestConstructors()
        {
            TaskHostTaskComplete complete = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.Success), null);
            TaskHostTaskComplete complete2 = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.Failure), null);
            TaskHostTaskComplete complete3 = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedDuringInitialization, new ArgumentOutOfRangeException()), null);
            TaskHostTaskComplete complete4 = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedDuringExecution, new ArgumentNullException()), null);

            IDictionary<string, object> parameters = new Dictionary<string, object>();
            TaskHostTaskComplete complete5 = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.Success, parameters), null);

            IDictionary<string, object> parameters2 = new Dictionary<string, object>();
            parameters2.Add("Text", "Hello!");
            parameters2.Add("MyBoolValue", true);
            parameters2.Add("MyITaskItem", new TaskItem("ABC"));
            parameters2.Add("ItemArray", new ITaskItem[] { new TaskItem("DEF"), new TaskItem("GHI"), new TaskItem("JKL") });

            TaskHostTaskComplete complete6 = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.Success, parameters2), null);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Task runner method
        /// </summary>
        private void RunTask(object state)
        {
            _isTaskExecuting = true;
            OutOfProcTaskHostTaskResult taskResult = null;
            TaskHostConfiguration taskConfiguration = state as TaskHostConfiguration;
            IDictionary<string, TaskParameter> taskParams = taskConfiguration.TaskParameters;

            // We only really know the values of these variables for sure once we see what we received from our parent 
            // environment -- otherwise if this was a completely new build, we could lose out on expected environment 
            // variables.  
            _debugCommunications = taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBUILDDEBUGCOMM", "1", StringComparison.OrdinalIgnoreCase);
            _updateEnvironment = !taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBuildTaskHostDoNotUpdateEnvironment", "1", StringComparison.OrdinalIgnoreCase);
            _updateEnvironmentAndLog = taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBuildTaskHostUpdateEnvironmentAndLog", "1", StringComparison.OrdinalIgnoreCase);

            try
            {
                // Change to the startup directory
                NativeMethodsShared.SetCurrentDirectory(taskConfiguration.StartupDirectory);

                if (_updateEnvironment)
                {
                    InitializeMismatchedEnvironmentTable(taskConfiguration.BuildProcessEnvironment);
                }

                // Now set the new environment
                SetTaskHostEnvironment(taskConfiguration.BuildProcessEnvironment);

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

                string taskName = taskConfiguration.TaskName;
                string taskLocation = taskConfiguration.TaskLocation;

                // We will not create an appdomain now because of a bug
                // As a fix, we will create the class directly without wrapping it in a domain
                _taskWrapper = new OutOfProcTaskAppDomainWrapper();

                taskResult = _taskWrapper.ExecuteTask
                (
                    this as IBuildEngine,
                    taskName,
                    taskLocation,
                    taskConfiguration.ProjectFileOfTask,
                    taskConfiguration.LineNumberOfTask,
                    taskConfiguration.ColumnNumberOfTask,
                    taskConfiguration.AppDomainSetup,
                    taskParams
                );
            }
            catch (Exception e)
            {
                if (e is ThreadAbortException)
                {
                    // This thread was aborted as part of Cancellation, we will return a failure task result
                    taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.Failure);
                }
                else if (ExceptionHandling.IsCriticalException(e))
                {
                    throw;
                }
                else
                {
                    taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedDuringExecution, e);
                }
            }
            finally
            {
                try
                {
                    _isTaskExecuting = false;

                    IDictionary<string, string> currentEnvironment = CommunicationsUtilities.GetEnvironmentVariables();
                    currentEnvironment = UpdateEnvironmentForMainNode(currentEnvironment);

                    if (taskResult == null)
                    {
                        taskResult = new OutOfProcTaskHostTaskResult(TaskCompleteType.Failure);
                    }

                    lock (_taskCompleteLock)
                    {
                        _taskCompletePacket = new TaskHostTaskComplete
                                                    (
                                                        taskResult,
                                                        currentEnvironment
                                                    );
                    }

                    foreach (TaskParameter param in taskParams.Values)
                    {
                        // Tell remoting to forget connections to the parameter
                        RemotingServices.Disconnect(param);
                    }

                    // Restore the original clean environment
                    CommunicationsUtilities.SetEnvironment(_savedEnvironment);
                }
                catch (Exception e)
                {
                    lock (_taskCompleteLock)
                    {
                        // Create a minimal taskCompletePacket to carry the exception so that the TaskHostTask does not hang while waiting
                        _taskCompletePacket = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.CrashedAfterExecution, e), null);
                    }
                }
                finally
                {
                    // Call CleanupTask to unload any domains and other necessary cleanup in the taskWrapper
                    _taskWrapper.CleanupTask();

                    // The task has now fully completed executing
                    _taskCompleteEvent.Set();
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// The task has been completed
        /// </summary>
        private void CompleteTask()
        {
            ErrorUtilities.VerifyThrow(_isTaskExecuting == false, "The task should be done executing before CompleteTask.");
            if (_nodeEndpoint.LinkStatus == LinkStatus.Active)
            {
                TaskHostTaskComplete taskCompletePacketToSend;

                lock (_taskCompleteLock)
                {
                    ErrorUtilities.VerifyThrowInternalNull(_taskCompletePacket, "taskCompletePacket");
                    taskCompletePacketToSend = _taskCompletePacket;
                    _taskCompletePacket = null;
                }

                _nodeEndpoint.SendData(taskCompletePacketToSend);
            }

            _currentConfiguration = null;

            // If the task has been canceled, the event will still be set.  
            // If so, now that we've completed the task, we want to shut down 
            // this node -- with no reuse, since we don't know whether the 
            // task we canceled left the node in a good state or not. 
            if (_taskCancelledEvent.WaitOne(0, false))
            {
                _shutdownReason = NodeEngineShutdownReason.BuildComplete;
                _shutdownEvent.Set();
            }
        }
        /// <summary>
        /// Helper method for testing invalid constructors
        /// </summary>
        private void AssertInvalidConstructorThrows(Type expectedExceptionType, TaskCompleteType taskResult, Exception taskException, string taskExceptionMessage, string[] taskExceptionMessageArgs, IDictionary<string, object> taskOutputParameters, IDictionary<string, string> buildProcessEnvironment)
        {
            bool exceptionCaught = false;

            try
            {
                TaskHostTaskComplete complete = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(taskResult, taskOutputParameters, taskException, taskExceptionMessage, taskExceptionMessageArgs), buildProcessEnvironment);
            }
            catch (Exception e)
            {
                exceptionCaught = true;
                Assert.IsInstanceOfType(e, expectedExceptionType, "Wrong exception was thrown!");
            }

            Assert.IsTrue(exceptionCaught, "No exception was caught when one was expected!");
        }
        public void TestTranslationWithITaskItemArrayInDictionary()
        {
            IDictionary<string, object> parameters = new Dictionary<string, object>();
            parameters.Add("TaskItemArrayValue", new ITaskItem[] { new TaskItem("Foo"), new TaskItem("Baz") });
            TaskHostTaskComplete complete = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.Success, parameters), null);

            ((INodePacketTranslatable)complete).Translate(TranslationHelpers.GetWriteTranslator());
            INodePacket packet = TaskHostTaskComplete.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());

            TaskHostTaskComplete deserializedComplete = packet as TaskHostTaskComplete;

            Assert.AreEqual(complete.TaskResult, deserializedComplete.TaskResult);
            Assert.IsNotNull(deserializedComplete.TaskOutputParameters);
            Assert.AreEqual(complete.TaskOutputParameters.Count, deserializedComplete.TaskOutputParameters.Count);

            ITaskItem[] itemArray = (ITaskItem[])complete.TaskOutputParameters["TaskItemArrayValue"].WrappedParameter;
            ITaskItem[] deserializedItemArray = (ITaskItem[])deserializedComplete.TaskOutputParameters["TaskItemArrayValue"].WrappedParameter;

            TaskHostPacketHelpers.AreEqual(itemArray, deserializedItemArray);
        }
        public void TestTranslationWithValueTypesInDictionary()
        {
            IDictionary<string, object> parameters = new Dictionary<string, object>();
            parameters.Add("Text", "Foo");
            parameters.Add("BoolValue", false);
            TaskHostTaskComplete complete = new TaskHostTaskComplete(new OutOfProcTaskHostTaskResult(TaskCompleteType.Success, parameters), null);

            ((INodePacketTranslatable)complete).Translate(TranslationHelpers.GetWriteTranslator());
            INodePacket packet = TaskHostTaskComplete.FactoryForDeserialization(TranslationHelpers.GetReadTranslator());

            TaskHostTaskComplete deserializedComplete = packet as TaskHostTaskComplete;

            Assert.AreEqual(complete.TaskResult, deserializedComplete.TaskResult);
            Assert.IsNotNull(deserializedComplete.TaskOutputParameters);
            Assert.AreEqual(complete.TaskOutputParameters.Count, deserializedComplete.TaskOutputParameters.Count);
            Assert.AreEqual(complete.TaskOutputParameters["Text"].WrappedParameter, deserializedComplete.TaskOutputParameters["Text"].WrappedParameter);
            Assert.AreEqual(complete.TaskOutputParameters["BoolValue"].WrappedParameter, deserializedComplete.TaskOutputParameters["BoolValue"].WrappedParameter);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Task completed executing in the task host
        /// </summary>
        private void HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
        {
            // If it crashed, or if it failed, it didn't succeed.   
            _taskExecutionSucceeded = taskHostTaskComplete.TaskResult == TaskCompleteType.Success ? true : false;

            // reset the environment, as though the task were executed in this process all along.
            CommunicationsUtilities.SetEnvironment(taskHostTaskComplete.BuildProcessEnvironment);

            // If it crashed during the execution phase, then we can effectively replicate the inproc task execution 
            // behaviour by just throwing here and letting the taskbuilder code take care of it the way it would 
            // have normally.
            // We will also replicate the same behaviour if the TaskHost caught some exceptions after execution of the task.
            if ((taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedDuringExecution) ||
                (taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedAfterExecution))
            {
                throw new TargetInvocationException(taskHostTaskComplete.TaskException);
            }

            // On the other hand, if it crashed during initialization, there's not really a way to effectively replicate
            // the inproc behavior -- in the inproc case, the task would have failed to load and crashed long before now.  
            // Furthermore, if we were just to throw here like in the execution case, we'd lose the ability to log 
            // different messages based on the circumstances of the initialization failure -- whether it was a setter failure, 
            // the task just could not be loaded, etc.  

            // So instead, when we catch the exception in the task host, we'll also record what message we want it to use 
            // when the error is logged; and given that information, log that error here.  This has the effect of differing 
            // from the inproc case insofar as ContinueOnError is now respected, instead of forcing a stop here.  
            if (taskHostTaskComplete.TaskResult == TaskCompleteType.CrashedDuringInitialization)
            {
                string exceptionMessage;
                string[] exceptionMessageArgs;

                if (taskHostTaskComplete.TaskExceptionMessage != null)
                {
                    exceptionMessage = taskHostTaskComplete.TaskExceptionMessage;
                    exceptionMessageArgs = taskHostTaskComplete.TaskExceptionMessageArgs;
                }
                else
                {
                    exceptionMessage = "TaskInstantiationFailureError";
                    exceptionMessageArgs = new string[] { _taskType.Type.Name, _taskType.Type.Assembly.Location, String.Empty };
                }

                _taskLoggingContext.LogFatalError(new BuildEventFileInfo(_taskLocation), taskHostTaskComplete.TaskException, taskHostTaskComplete.TaskExceptionMessage, taskHostTaskComplete.TaskExceptionMessageArgs);
            }

            // Set the output parameters for later
            foreach (KeyValuePair<string, TaskParameter> outputParam in taskHostTaskComplete.TaskOutputParameters)
            {
                _setParameters[outputParam.Key] = (outputParam.Value == null) ? null : outputParam.Value.WrappedParameter;
            }
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Factory for deserialization.
 /// </summary>
 internal static INodePacket FactoryForDeserialization(INodePacketTranslator translator)
 {
     TaskHostTaskComplete taskComplete = new TaskHostTaskComplete();
     taskComplete.Translate(translator);
     return taskComplete;
 }