Example #1
0
 /// <summary>
 /// This function attempts to find out a node number for which
 /// the event named Node_x_ProviderMutex doesn't exist. The existance
 /// of the event indicates that some other node provider is using the node.
 /// </summary>
 private void ReserveNextAvailableNodeNumber(int currentNodeNumber)
 {
     while (nodeReserveHandle == null)
     {
         bool createdNew = false;
         nodeReserveHandle =
             new EventWaitHandle(false, EventResetMode.ManualReset, LocalNodeProviderGlobalNames.NodeReserveEventName(currentNodeNumber), out createdNew);
         if (!createdNew)
         {
             nodeReserveHandle.Close();
             nodeReserveHandle = null;
             currentNodeNumber++;
         }
         else
         {
             nodeNumber = currentNodeNumber;
             // Create the shared memory resources
             if (!CreateSharedMemoryBuffers())
             {
                 nodeReserveHandle.Close();
                 nodeReserveHandle = null;
                 currentNodeNumber++;
             }
         }
     }
 }
Example #2
0
        /// <summary>
        /// This function starts local node when process is launched and shuts it down on time out
        /// Called by msbuild.exe.
        /// </summary>
        public static void StartLocalNodeServer(int nodeNumber)
        {
            // Create global events necessary for handshaking with the parent
            if (!CreateGlobalEvents(nodeNumber))
            {
                return;
            }

            LocalNode localNode = new LocalNode(nodeNumber);

            WaitHandle[] waitHandles = new WaitHandle[4];
            waitHandles[0] = shutdownEvent;
            waitHandles[1] = globalNodeErrorShutdown;
            waitHandles[2] = inUseEvent;
            waitHandles[3] = globalInitiateActivationEvent;

            // This is necessary to make build.exe finish promptly. Dont remove.
            if (!Engine.debugMode)
            {
                // Create null streams for the current input/output/error streams
                Console.SetOut(new StreamWriter(Stream.Null));
                Console.SetError(new StreamWriter(Stream.Null));
                Console.SetIn(new StreamReader(Stream.Null));
            }

            bool continueRunning = true;

            while (continueRunning)
            {
                int eventType = WaitHandle.WaitAny(waitHandles, inactivityTimeout, false);

                if (eventType == 0 || eventType == 1 || eventType == WaitHandle.WaitTimeout)
                {
                    continueRunning = false;
                    localNode.ShutdownNode(eventType != 1 ?
                                           Node.NodeShutdownLevel.PoliteShutdown :
                                           Node.NodeShutdownLevel.ErrorShutdown, true, true);
                }
                else if (eventType == 2)
                {
                    // reset the event as we do not want it to go into this state again when we are done with this if statement.
                    inUseEvent.Reset();
                    // The parent knows at this point the child process has been launched
                    globalNodeActivate.Reset();
                    // Set the global inuse event so other parent processes know this node is now initialized
                    globalNodeInUse.Set();
                    // Make a copy of the parents handle to protect ourselves in case the parent dies,
                    // this is to prevent a parent from reserving a node another parent is trying to use.
                    globalNodeReserveHandle =
                        new EventWaitHandle(false, EventResetMode.ManualReset, LocalNodeProviderGlobalNames.NodeReserveEventName(nodeNumber));
                    WaitHandle[] waitHandlesActive = new WaitHandle[3];
                    waitHandlesActive[0] = shutdownEvent;
                    waitHandlesActive[1] = globalNodeErrorShutdown;
                    waitHandlesActive[2] = notInUseEvent;

                    eventType = WaitHandle.WaitTimeout;
                    while (eventType == WaitHandle.WaitTimeout && continueRunning == true)
                    {
                        eventType = WaitHandle.WaitAny(waitHandlesActive, parentCheckInterval, false);

                        if (eventType == 0 || /* nice shutdown due to shutdownEvent */
                            eventType == 1 || /* error shutdown due to globalNodeErrorShutdown */
                            eventType == WaitHandle.WaitTimeout && !localNode.IsParentProcessAlive())
                        {
                            continueRunning = false;
                            // If the exit is not triggered by running of shutdown method
                            if (eventType != 0)
                            {
                                localNode.ShutdownNode(Node.NodeShutdownLevel.ErrorShutdown, true, true);
                            }
                        }
                        else if (eventType == 2)
                        {
                            // Trigger a collection before the node goes idle to insure that
                            // the memory is released to the system as soon as possible
                            GC.Collect();
                            // Change the current directory to a safe one so that the directory
                            // last used by the build can be safely deleted. We must have read
                            // access to the safe directory so use SystemDirectory for this purpose.
                            Directory.SetCurrentDirectory(Environment.SystemDirectory);
                            notInUseEvent.Reset();
                            globalNodeInUse.Reset();
                        }
                    }

                    ErrorUtilities.VerifyThrow(localNode.node == null,
                                               "Expected either node to be null or continueRunning to be false.");

                    // Stop the communication threads and release the shared memory object so that the next parent can create it
                    localNode.StopCommunicationThreads();
                    // Close the local copy of the reservation handle (this allows another parent to reserve
                    // the node)
                    globalNodeReserveHandle.Close();
                    globalNodeReserveHandle = null;
                }
                else if (eventType == 3)
                {
                    globalInitiateActivationEvent.Reset();
                    localNode.StartCommunicationThreads();
                    globalNodeActivate.Set();
                }
            }
            // Stop the communication threads and release the shared memory object so that the next parent can create it
            localNode.StopCommunicationThreads();

            globalNodeActive.Close();
            globalNodeInUse.Close();
        }