/// <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 bool Execute() { // log that we are about to spawn the task host string runtime = _taskHostParameters[XMakeAttributes.runtime]; string architecture = _taskHostParameters[XMakeAttributes.architecture]; _taskLoggingContext.LogComment(MessageImportance.Low, "ExecutingTaskInTaskHost", _taskType.Type.Name, _taskType.Assembly.AssemblyLocation, runtime, architecture); // set up the node lock (_taskHostLock) { _taskHostProvider = (NodeProviderOutOfProcTaskHost)_buildComponentHost.GetComponent(BuildComponentType.OutOfProcTaskHostNodeProvider); ErrorUtilities.VerifyThrowInternalNull(_taskHostProvider, "taskHostProvider"); } TaskHostConfiguration hostConfiguration = new TaskHostConfiguration ( _buildComponentHost.BuildParameters.NodeId, NativeMethodsShared.GetCurrentDirectory(), CommunicationsUtilities.GetEnvironmentVariables(), _buildComponentHost.BuildParameters.Culture, _buildComponentHost.BuildParameters.UICulture, #if FEATURE_APPDOMAIN _appDomainSetup, #endif BuildEngine.LineNumberOfTaskNode, BuildEngine.ColumnNumberOfTaskNode, BuildEngine.ProjectFileOfTaskNode, BuildEngine.ContinueOnError, _taskType.Type.FullName, AssemblyUtilities.GetAssemblyLocation(_taskType.Type.GetTypeInfo().Assembly), _buildComponentHost.BuildParameters.LogTaskInputs, _setParameters, new Dictionary <string, string>(_buildComponentHost.BuildParameters.GlobalProperties), _taskLoggingContext.GetWarningsAsErrors(), _taskLoggingContext.GetWarningsAsMessages() ); try { lock (_taskHostLock) { _requiredContext = CommunicationsUtilities.GetHandshakeOptions(taskHost: true, taskHostParameters: _taskHostParameters); _connectedToTaskHost = _taskHostProvider.AcquireAndSetUpHost(_requiredContext, this, this, hostConfiguration); } if (_connectedToTaskHost) { try { bool taskFinished = false; while (!taskFinished) { _packetReceivedEvent.WaitOne(); INodePacket packet = null; // Handle the packet that's coming in while (_receivedPackets.TryDequeue(out packet)) { if (packet != null) { HandlePacket(packet, out taskFinished); } } } } finally { lock (_taskHostLock) { _taskHostProvider.DisconnectFromHost(_requiredContext); _connectedToTaskHost = false; } } } else { LogErrorUnableToCreateTaskHost(_requiredContext, runtime, architecture, null); } } catch (BuildAbortedException) { LogErrorUnableToCreateTaskHost(_requiredContext, runtime, architecture, null); } catch (NodeFailedToLaunchException e) { LogErrorUnableToCreateTaskHost(_requiredContext, runtime, architecture, e); } return(_taskExecutionSucceeded); }