/// <summary> /// Perform necessary actions to shut down the node. /// </summary> private NodeEngineShutdownReason HandleShutdown() { // Wait for the RunTask task runner thread before shutting down so that we can cleanly dispose all WaitHandles. if (_taskRunnerThread != null) { _taskRunnerThread.Join(); } 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}.", _shutdownReason); } } #if !CLR2COMPATIBILITY _registeredTaskObjectCache.DisposeCacheObjects(RegisteredTaskObjectLifetime.Build); _registeredTaskObjectCache = null; #endif // 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. CommunicationsUtilities.SetEnvironment(_savedEnvironment); if (_nodeEndpoint.LinkStatus == LinkStatus.Active) { // Notify the BuildManager that we are done. _nodeEndpoint.SendData(new NodeShutdown(_shutdownReason == NodeEngineShutdownReason.Error ? NodeShutdownReason.Error : NodeShutdownReason.Requested)); // Flush all packets to the pipe and close it down. This blocks until the shutdown is complete. _nodeEndpoint.OnLinkStatusChanged -= new LinkStatusChangedDelegate(OnLinkStatusChanged); } _nodeEndpoint.Disconnect(); // Dispose these WaitHandles #if CLR2COMPATIBILITY _packetReceivedEvent.Close(); _shutdownEvent.Close(); _taskCompleteEvent.Close(); _taskCancelledEvent.Close(); #else _packetReceivedEvent.Dispose(); _shutdownEvent.Dispose(); _taskCompleteEvent.Dispose(); _taskCancelledEvent.Dispose(); #endif return(_shutdownReason); }