Added RunningQueue to keep track of running build thread to avoid dead loop when...
authorjwang36 <jwang36@7335b38e-4728-0410-8992-fb3ffe349368>
Mon, 22 Oct 2007 06:34:47 +0000 (06:34 +0000)
committerjwang36 <jwang36@7335b38e-4728-0410-8992-fb3ffe349368>
Mon, 22 Oct 2007 06:34:47 +0000 (06:34 +0000)
git-svn-id: https://buildtools.tianocore.org/svn/buildtools/trunk/BaseTools@842 7335b38e-4728-0410-8992-fb3ffe349368

Source/Python/build/build.py

index c4d7181..d6a58ce 100644 (file)
@@ -296,13 +296,13 @@ class BuildTask:
     _ReadyQueue = sdict()\r
     _ReadyQueueLock = threading.Lock()\r
 \r
+    # queue for run tasks\r
+    _RunningQueue = sdict()\r
+    _RunningQueueLock = threading.Lock()\r
+\r
     # queue containing all build tasks, in case duplicate build\r
     _TaskQueue = sdict()\r
 \r
-    # flag indicating no thread is running\r
-    _CompleteFlag = threading.Event()\r
-    _CompleteFlag.clear()\r
-\r
     # flag indicating error occurs in a running thread\r
     _ErrorFlag = threading.Event()\r
     _ErrorFlag.clear()\r
@@ -312,7 +312,8 @@ class BuildTask:
     _Thread = None\r
 \r
     # flag indicating if the scheduler is started or not\r
-    _SchedulerStarted = False\r
+    _SchedulerStopped = threading.Event()\r
+    _SchedulerStopped.set()\r
 \r
     ## Start the task scheduler thread\r
     #\r
@@ -325,7 +326,6 @@ class BuildTask:
         SchedulerThread.setName("Build-Task-Scheduler")\r
         SchedulerThread.setDaemon(False)\r
         SchedulerThread.start()\r
-        BuildTask._SchedulerStarted = True\r
 \r
     ## Scheduler method\r
     #\r
@@ -334,6 +334,7 @@ class BuildTask:
     #\r
     @staticmethod\r
     def Scheduler(MaxThreadNumber, ExitFlag):\r
+        BuildTask._SchedulerStopped.clear()\r
         try:\r
             # use BoundedSemaphore to control the maximum running threads\r
             BuildTask._Thread = BoundedSemaphore(MaxThreadNumber)\r
@@ -343,7 +344,7 @@ class BuildTask:
             #\r
             while (len(BuildTask._PendingQueue) > 0 or len(BuildTask._ReadyQueue) > 0 \\r
                    or not ExitFlag.isSet()) and not BuildTask._ErrorFlag.isSet():\r
-                EdkLogger.debug(EdkLogger.DEBUG_5, "Pending Queue (%d), Ready Queue (%d)"\r
+                EdkLogger.debug(EdkLogger.DEBUG_9, "Pending Queue (%d), Ready Queue (%d)"\r
                                 % (len(BuildTask._PendingQueue), len(BuildTask._ReadyQueue)))\r
                 # get all pending tasks\r
                 BuildTask._PendingQueueLock.acquire()\r
@@ -366,29 +367,33 @@ class BuildTask:
                     # empty ready queue, do nothing further\r
                     if len(BuildTask._ReadyQueue) == 0:\r
                         break\r
+\r
                     # wait for active thread(s) exit\r
                     BuildTask._Thread.acquire(True)\r
+\r
                     # start a new build thread\r
-                    Bo = BuildTask._ReadyQueue.keys()\r
-                    Bt = BuildTask._ReadyQueue.pop(Bo[0])\r
+                    Bo = BuildTask._ReadyQueue.keys()[0]\r
+                    Bt = BuildTask._ReadyQueue.pop(Bo)\r
+\r
+                    # move into running queue\r
+                    BuildTask._RunningQueueLock.acquire()\r
+                    BuildTask._RunningQueue[Bo] = Bt\r
+                    BuildTask._RunningQueueLock.release()\r
+\r
                     Bt.Start()\r
+\r
                 # avoid tense loop\r
                 time.sleep(0.01)\r
 \r
-            # wait for all running threads exit if no error occured\r
+            # wait for all running threads exit\r
             if BuildTask._ErrorFlag.isSet():\r
                 EdkLogger.quiet("\nWaiting for all Command-Threads exit...")\r
             # while not BuildTask._ErrorFlag.isSet() and \\r
-            while BuildTask._Thread._Semaphore__value < BuildTask._Thread._initial_value:\r
-                EdkLogger.verbose("Waiting for thread ending...(%d)" %\r
-                                  (BuildTask._Thread._initial_value - BuildTask._Thread._Semaphore__value)\r
-                                 )\r
-                EdkLogger.debug(EdkLogger.DEBUG_9, "Threads [%s]" %\r
-                                ", ".join([Th.getName() for Th in threading.enumerate()]))\r
+            while len(BuildTask._RunningQueue) > 0:\r
+                EdkLogger.verbose("Waiting for thread ending...(%d)" % len(BuildTask._RunningQueue))\r
+                EdkLogger.debug(EdkLogger.DEBUG_9, "Threads [%s]" % ", ".join([Th.getName() for Th in threading.enumerate()]))\r
                 # avoid tense loop\r
                 time.sleep(0.1)\r
-            BuildTask._CompleteFlag.set()\r
-            BuildTask._SchedulerStarted = False\r
         except BaseException, X:\r
             #\r
             # TRICK: hide the output of threads left runing, so that the user can\r
@@ -396,28 +401,27 @@ class BuildTask:
             #\r
             EdkLogger.SetLevel(EdkLogger.QUIET)\r
             BuildTask._ErrorFlag.set()\r
-            BuildTask._ErrorMessage = "build thread scheduler error\n\t%s" % str(e)\r
-            BuildTask._CompleteFlag.set()\r
-            BuildTask._SchedulerStarted = False\r
+            BuildTask._ErrorMessage = "build thread scheduler error\n\t%s" % str(X)\r
+        BuildTask._SchedulerStopped.set()\r
 \r
     ## Wait for all running method exit\r
     #\r
     @staticmethod\r
     def WaitForComplete():\r
-        BuildTask._CompleteFlag.wait()\r
+        BuildTask._SchedulerStopped.wait()\r
 \r
     ## Check if the scheduler is running or not\r
     #\r
     @staticmethod\r
     def IsOnGoing():\r
-        return BuildTask._SchedulerStarted\r
+        return not BuildTask._SchedulerStopped.isSet()\r
 \r
     ## Abort the build\r
     @staticmethod\r
     def Abort():\r
-        if not BuildTask._CompleteFlag.isSet():\r
+        if BuildTask.IsOnGoing():\r
             BuildTask._ErrorFlag.set()\r
-            BuildTask._CompleteFlag.wait()\r
+            BuildTask.WaitForComplete()\r
 \r
     ## Check if there's error in running thread\r
     #\r
@@ -509,7 +513,7 @@ class BuildTask:
         try:\r
             LaunchCommand(Command, WorkingDir)\r
             self.CompleteFlag = True\r
-        except Exception, X:\r
+        except:\r
             #\r
             # TRICK: hide the output of threads left runing, so that the user can\r
             #        catch the error message easily\r
@@ -519,6 +523,9 @@ class BuildTask:
             BuildTask._ErrorMessage = "%s broken\n    %s [%s]" % \\r
                                       (threading.currentThread().getName(), Command, WorkingDir)\r
         # indicate there's a thread is available for another build task\r
+        BuildTask._RunningQueueLock.acquire()\r
+        BuildTask._RunningQueue.pop(self.BuildItem)\r
+        BuildTask._RunningQueueLock.release()\r
         BuildTask._Thread.release()\r
 \r
     ## Start build task thread\r