/// <summary> /// Handles the NodeConfiguration packet. /// </summary> private void HandleNodeConfiguration(NodeConfiguration configuration) { // Set the culture. #if FEATURE_CULTUREINFO_SETTERS CultureInfo.CurrentCulture = configuration.BuildParameters.Culture; CultureInfo.CurrentUICulture = configuration.BuildParameters.UICulture; #else Thread.CurrentThread.CurrentCulture = configuration.BuildParameters.Culture; Thread.CurrentThread.CurrentUICulture = configuration.BuildParameters.UICulture; #endif // 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; #if FEATURE_APPDOMAIN // And the AppDomainSetup _componentHost.BuildParameters.AppDomainSetup = configuration.AppDomainSetup; #endif // 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; }
/// <summary> /// Copy constructor /// </summary> internal BuildParameters(BuildParameters other, bool resetEnvironment = false) { ErrorUtilities.VerifyThrowInternalNull(other, nameof(other)); _buildId = other._buildId; _culture = other._culture; _defaultToolsVersion = other._defaultToolsVersion; _enableNodeReuse = other._enableNodeReuse; _buildProcessEnvironment = resetEnvironment ? CommunicationsUtilities.GetEnvironmentVariables() : other._buildProcessEnvironment != null ? new Dictionary <string, string>(other._buildProcessEnvironment) : null; _environmentProperties = other._environmentProperties != null ? new PropertyDictionary <ProjectPropertyInstance>(other._environmentProperties) : null; _forwardingLoggers = other._forwardingLoggers != null ? new List <ForwardingLoggerRecord>(other._forwardingLoggers) : null; _globalProperties = other._globalProperties != null ? new PropertyDictionary <ProjectPropertyInstance>(other._globalProperties) : null; HostServices = other.HostServices; _loggers = other._loggers != null ? new List <ILogger>(other._loggers) : null; _maxNodeCount = other._maxNodeCount; _memoryUseLimit = other._memoryUseLimit; _nodeExeLocation = other._nodeExeLocation; NodeId = other.NodeId; _onlyLogCriticalEvents = other._onlyLogCriticalEvents; #if FEATURE_THREAD_PRIORITY BuildThreadPriority = other.BuildThreadPriority; #endif _toolsetProvider = other._toolsetProvider; ToolsetDefinitionLocations = other.ToolsetDefinitionLocations; _toolsetProvider = other._toolsetProvider; _uiCulture = other._uiCulture; DetailedSummary = other.DetailedSummary; _shutdownInProcNodeOnBuildFinish = other._shutdownInProcNodeOnBuildFinish; ProjectRootElementCache = other.ProjectRootElementCache; ResetCaches = other.ResetCaches; LegacyThreadingSemantics = other.LegacyThreadingSemantics; SaveOperatingEnvironment = other.SaveOperatingEnvironment; _useSynchronousLogging = other._useSynchronousLogging; _disableInProcNode = other._disableInProcNode; _logTaskInputs = other._logTaskInputs; _logInitialPropertiesAndItems = other._logInitialPropertiesAndItems; WarningsAsErrors = other.WarningsAsErrors == null ? null : new HashSet <string>(other.WarningsAsErrors, StringComparer.OrdinalIgnoreCase); WarningsAsMessages = other.WarningsAsMessages == null ? null : new HashSet <string>(other.WarningsAsMessages, StringComparer.OrdinalIgnoreCase); _projectLoadSettings = other._projectLoadSettings; _interactive = other._interactive; _isolateProjects = other._isolateProjects; _inputResultsCacheFiles = other._inputResultsCacheFiles; _outputResultsCacheFile = other._outputResultsCacheFile; DiscardBuildResults = other.DiscardBuildResults; LowPriority = other.LowPriority; ProjectCacheDescriptor = other.ProjectCacheDescriptor; }
/// <summary> /// Centralization of the common parts of construction. /// </summary> private void Initialize(PropertyDictionary <ProjectPropertyInstance> environmentProperties, ProjectRootElementCache projectRootElementCache, ToolsetProvider toolsetProvider) { _buildProcessEnvironment = CommunicationsUtilities.GetEnvironmentVariables(); _environmentProperties = environmentProperties; this.ProjectRootElementCache = projectRootElementCache; this.ResetCaches = true; _toolsetProvider = toolsetProvider; if (Environment.GetEnvironmentVariable("MSBUILDDISABLENODEREUSE") == "1") // For example to disable node reuse within Visual Studio { _enableNodeReuse = false; } if (Environment.GetEnvironmentVariable("MSBUILDDETAILEDSUMMARY") == "1") // For example to get detailed summary within Visual Studio { _detailedSummary = true; } _nodeExeLocation = FindMSBuildExe(); }
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); }
private void HandleNodeConfiguration(NodeConfiguration configuration) { // Grab the system parameters. _buildParameters = configuration.BuildParameters; _buildParameters.ProjectRootElementCache = s_projectRootElementCacheBase; // 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(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory); } // 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. CultureInfo.CurrentCulture = _buildParameters.Culture; CultureInfo.CurrentUICulture = _buildParameters.UICulture; // Get the node ID. _buildParameters.NodeId = configuration.NodeId; _buildParameters.IsOutOfProc = true; #if FEATURE_APPDOMAIN // And the AppDomainSetup _buildParameters.AppDomainSetup = configuration.AppDomainSetup; #endif // 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(SendPacket); _shutdownException = null; if (configuration.LoggingNodeConfiguration.IncludeEvaluationMetaprojects) { _loggingService.IncludeEvaluationMetaprojects = true; } if (configuration.LoggingNodeConfiguration.IncludeEvaluationProfiles) { _loggingService.IncludeEvaluationProfile = true; } if (configuration.LoggingNodeConfiguration.IncludeTaskInputs) { _loggingService.IncludeTaskInputs = true; } if (configuration.LoggingNodeConfiguration.IncludeEvaluationPropertiesAndItems) { _loggingService.IncludeEvaluationPropertiesAndItems = true; } try { // If there are no node loggers to initialize dont do anything if (configuration.LoggerDescriptions?.Length > 0) { _loggingService.InitializeNodeLoggers(configuration.LoggerDescriptions, sink, configuration.NodeId); } } catch (Exception ex) when(!ExceptionHandling.IsCriticalException(ex)) { OnEngineException(ex); } _loggingService.OnLoggingThreadException += 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(MSBuildConstants.SemicolonChar, 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) { HandleShutdown(out Exception exception); throw exception; } _buildRequestEngine.InitializeForBuild(_loggingContext); // Finally store off this configuration packet. _currentConfiguration = configuration; }
private NodeEngineShutdownReason HandleShutdown(out Exception exception) { CommunicationsUtilities.Trace("Shutting down with reason: {0}, and exception: {1}.", _shutdownReason, _shutdownException); // Clean up the engine if (_buildRequestEngine != null && _buildRequestEngine.Status != BuildRequestEngineStatus.Uninitialized) { _buildRequestEngine.CleanupForBuild(); if (_shutdownReason == NodeEngineShutdownReason.BuildCompleteReuse) { ((IBuildComponent)_buildRequestEngine).ShutdownComponent(); } } // Signal the SDK resolver service to shutdown ((IBuildComponent)_sdkResolverService).ShutdownComponent(); // Dispose of any build registered objects IRegisteredTaskObjectCache objectCache = (IRegisteredTaskObjectCache)(_componentFactories.GetComponent(BuildComponentType.RegisteredTaskObjectCache)); objectCache.DisposeCacheObjects(RegisteredTaskObjectLifetime.Build); if (_shutdownReason != NodeEngineShutdownReason.BuildCompleteReuse) { // Dispose of any node registered objects. ((IBuildComponent)objectCache).ShutdownComponent(); } // Shutdown any Out Of Proc Nodes Created _taskHostNodeManager.ShutdownConnectedNodes(_shutdownReason == NodeEngineShutdownReason.BuildCompleteReuse); // On Windows, a process holds a handle to the current directory, // so reset it away from a user-requested folder that may get deleted. NativeMethodsShared.SetCurrentDirectory(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory); // Restore the original environment. // If the node was never configured, this will be null. if (_savedEnvironment != null) { foreach (KeyValuePair <string, string> entry in CommunicationsUtilities.GetEnvironmentVariables()) { if (!_savedEnvironment.ContainsKey(entry.Key)) { Environment.SetEnvironmentVariable(entry.Key, null); } } foreach (KeyValuePair <string, string> entry in _savedEnvironment) { Environment.SetEnvironmentVariable(entry.Key, entry.Value); } } try { // Shut down logging, which will cause all queued logging messages to be sent. if (_loggingContext != null && _loggingService != null) { _loggingContext.LogBuildFinished(true); ((IBuildComponent)_loggingService).ShutdownComponent(); } } finally { // Shut down logging, which will cause all queued logging messages to be sent. if (_loggingContext != null && _loggingService != null) { _loggingContext.LoggingService.OnLoggingThreadException -= OnLoggingThreadException; _loggingContext = null; } exception = _shutdownException; if (_nodeEndpoint.LinkStatus == LinkStatus.Active) { // Notify the BuildManager that we are done. _nodeEndpoint.SendData(new NodeShutdown(_shutdownReason == NodeEngineShutdownReason.Error ? NodeShutdownReason.Error : NodeShutdownReason.Requested, exception)); // Flush all packets to the pipe and close it down. This blocks until the shutdown is complete. _nodeEndpoint.OnLinkStatusChanged -= OnLinkStatusChanged; } _nodeEndpoint.Disconnect(); CleanupCaches(); } CommunicationsUtilities.Trace("Shut down complete."); return(_shutdownReason); }
/// <summary> /// Perform necessary actions to shut down the node. /// </summary> private NodeEngineShutdownReason HandleShutdown(out Exception exception) { // Console.WriteLine("Node shutting down with reason {0} and exception: {1}", shutdownReason, shutdownException); try { // Clean up the engine if (_buildRequestEngine != null && _buildRequestEngine.Status != BuildRequestEngineStatus.Uninitialized) { _buildRequestEngine.CleanupForBuild(); } } catch (Exception ex) { if (ExceptionHandling.IsCriticalException(ex)) { throw; } // If we had some issue shutting down, don't reuse the node because we may be in some weird state. if (_shutdownReason == NodeEngineShutdownReason.BuildCompleteReuse) { _shutdownReason = NodeEngineShutdownReason.BuildComplete; } } // Dispose of any build registered objects IRegisteredTaskObjectCache objectCache = (IRegisteredTaskObjectCache)(_componentHost.GetComponent(BuildComponentType.RegisteredTaskObjectCache)); objectCache.DisposeCacheObjects(RegisteredTaskObjectLifetime.Build); if (_shutdownReason != NodeEngineShutdownReason.BuildCompleteReuse) { // Dispose of any node registered objects. ((IBuildComponent)objectCache).ShutdownComponent(); } if (_componentHost.BuildParameters.SaveOperatingEnvironment) { // Restore the original current directory. NativeMethodsShared.SetCurrentDirectory(_savedCurrentDirectory); // Restore the original environment. foreach (KeyValuePair <string, string> entry in CommunicationsUtilities.GetEnvironmentVariables()) { if (!_savedEnvironment.ContainsKey(entry.Key)) { Environment.SetEnvironmentVariable(entry.Key, null); } } foreach (KeyValuePair <string, string> entry in _savedEnvironment) { Environment.SetEnvironmentVariable(entry.Key, entry.Value); } } exception = _shutdownException; if (_loggingContext != null) { _loggingContext.LoggingService.OnLoggingThreadException -= OnLoggingThreadException; _loggingContext = null; } // Notify the BuildManager that we are done. if (_nodeEndpoint.LinkStatus == LinkStatus.Active) { _nodeEndpoint.SendData(new NodeShutdown(_shutdownReason == NodeEngineShutdownReason.Error ? NodeShutdownReason.Error : NodeShutdownReason.Requested, exception)); } _buildRequestEngine.OnEngineException -= _engineExceptionEventHandler; _buildRequestEngine.OnNewConfigurationRequest -= _newConfigurationRequestEventHandler; _buildRequestEngine.OnRequestBlocked -= _requestBlockedEventHandler; _buildRequestEngine.OnRequestComplete -= _requestCompleteEventHandler; _buildRequestEngine.OnResourceRequest -= _resourceRequestHandler; return(_shutdownReason); }
/// <summary> /// Perform necessary actions to shut down the node. /// </summary> private NodeEngineShutdownReason HandleShutdown(out Exception exception) { if (_debugCommunications) { using (StreamWriter writer = File.CreateText(String.Format(CultureInfo.CurrentCulture, Path.Combine(Path.GetTempPath(), @"MSBuild_NodeShutdown_{0}.txt"), Process.GetCurrentProcess().Id))) { writer.WriteLine("Node shutting down with reason {0} and exception: {1}", _shutdownReason, _shutdownException); } } // Clean up the engine if (null != _buildRequestEngine && _buildRequestEngine.Status != BuildRequestEngineStatus.Uninitialized) { _buildRequestEngine.CleanupForBuild(); if (_shutdownReason == NodeEngineShutdownReason.BuildCompleteReuse) { ((IBuildComponent)_buildRequestEngine).ShutdownComponent(); } } // Dispose of any build registered objects IRegisteredTaskObjectCache objectCache = (IRegisteredTaskObjectCache)(_componentFactories.GetComponent(BuildComponentType.RegisteredTaskObjectCache)); objectCache.DisposeCacheObjects(RegisteredTaskObjectLifetime.Build); if (_shutdownReason != NodeEngineShutdownReason.BuildCompleteReuse) { // Dispose of any node registered objects. ((IBuildComponent)objectCache).ShutdownComponent(); } // Shutdown any Out Of Proc Nodes Created _taskHostNodeManager.ShutdownConnectedNodes(_shutdownReason == NodeEngineShutdownReason.BuildCompleteReuse); // Restore the original current directory. NativeMethodsShared.SetCurrentDirectory(Environment.SystemDirectory); // Restore the original environment. // If the node was never configured, this will be null. if (_savedEnvironment != null) { foreach (KeyValuePair <string, string> entry in CommunicationsUtilities.GetEnvironmentVariables()) { if (!_savedEnvironment.ContainsKey(entry.Key)) { Environment.SetEnvironmentVariable(entry.Key, null); } } foreach (KeyValuePair <string, string> entry in _savedEnvironment) { Environment.SetEnvironmentVariable(entry.Key, entry.Value); } } try { // Shut down logging, which will cause all queued logging messages to be sent. if (null != _loggingContext && null != _loggingService) { _loggingContext.LogBuildFinished(true); ((IBuildComponent)_loggingService).ShutdownComponent(); } } finally { // Shut down logging, which will cause all queued logging messages to be sent. if (null != _loggingContext && null != _loggingService) { _loggingContext.LoggingService.OnLoggingThreadException -= new LoggingExceptionDelegate(OnLoggingThreadException); _loggingContext = null; } exception = _shutdownException; if (_nodeEndpoint.LinkStatus == LinkStatus.Active) { // Notify the BuildManager that we are done. _nodeEndpoint.SendData(new NodeShutdown(_shutdownReason == NodeEngineShutdownReason.Error ? NodeShutdownReason.Error : NodeShutdownReason.Requested, exception)); // Flush all packets to the pipe and close it down. This blocks until the shutdown is complete. _nodeEndpoint.OnLinkStatusChanged -= new LinkStatusChangedDelegate(OnLinkStatusChanged); } _nodeEndpoint.Disconnect(); CleanupCaches(); } return(_shutdownReason); }
/// <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(); } } }
/// <summary> /// Starts up the node and processes messages until the node is requested to shut down. /// </summary> /// <param name="shutdownException">The exception which caused shutdown, if any.</param> /// <returns>The reason for shutting down.</returns> public NodeEngineShutdownReason Run(out Exception shutdownException) { #if !CLR2COMPATIBILITY _registeredTaskObjectCache = new RegisteredTaskObjectCacheBase(); #endif shutdownException = null; // Snapshot the current environment _savedEnvironment = CommunicationsUtilities.GetEnvironmentVariables(); string pipeName = "MSBuild" + Process.GetCurrentProcess().Id; _nodeEndpoint = new NodeEndpointOutOfProcTaskHost(pipeName); _nodeEndpoint.OnLinkStatusChanged += new LinkStatusChangedDelegate(OnLinkStatusChanged); _nodeEndpoint.Listen(this); WaitHandle[] waitHandles = new WaitHandle[] { _shutdownEvent, _packetReceivedEvent, _taskCompleteEvent, _taskCancelledEvent }; while (true) { int index = WaitHandle.WaitAny(waitHandles); switch (index) { case 0: // shutdownEvent NodeEngineShutdownReason shutdownReason = HandleShutdown(); return(shutdownReason); case 1: // packetReceivedEvent INodePacket packet = null; int packetCount = _receivedPackets.Count; while (packetCount > 0) { lock (_receivedPackets) { if (_receivedPackets.Count > 0) { packet = _receivedPackets.Dequeue(); } else { break; } } if (packet != null) { HandlePacket(packet); } } break; case 2: // taskCompleteEvent CompleteTask(); break; case 3: // taskCancelledEvent CancelTask(); break; } } // UNREACHABLE }