Scheduler: avoid infinite loop after CTRL-C
authorZac Medico <zmedico@gentoo.org>
Fri, 11 Mar 2011 03:29:57 +0000 (19:29 -0800)
committerZac Medico <zmedico@gentoo.org>
Mon, 14 Mar 2011 16:23:29 +0000 (09:23 -0700)
If CTRL-C was received at certain times, it was possible for discarded
tasks to be erroneously left in Scheduler._running_tasks, which would
cause the main loop to run infinitely. Thanks to David James
<davidjames@google.com> for reporting this issue and helping to devise
a solution.

pym/_emerge/Scheduler.py

index e9c1b6a5ed4a902909383df5a84890c46e58cea9..306c945d78f623081fa3dbef4314d83f064a13fa 100644 (file)
@@ -295,6 +295,13 @@ class Scheduler(PollScheduler):
 
        def _terminate_tasks(self):
                self._status_display.quiet = True
+               # Remove running_tasks that have been added to queues but
+               # haven't been started yet, since we're going to discard
+               # them and their start/exit handlers won't be called.
+               for build in self._task_queues.jobs._task_queue:
+                       self._running_tasks.remove(build.pkg)
+               for merge in self._task_queues.merge._task_queue:
+                       self._running_tasks.remove(merge.merge.pkg)
                for q in self._task_queues.values():
                        q.clear()
 
@@ -1469,7 +1476,13 @@ class Scheduler(PollScheduler):
                mtimedb.commit()
 
        def _build_exit(self, build):
-               if build.returncode == os.EX_OK:
+               if build.returncode == os.EX_OK and self._terminated.is_set():
+                       # We've been interrupted, so we won't
+                       # add this to the merge queue.
+                       self.curval += 1
+                       self._running_tasks.remove(build.pkg)
+                       self._deallocate_config(build.settings)
+               elif build.returncode == os.EX_OK:
                        self.curval += 1
                        merge = PackageMerge(merge=build)
                        if not build.build_opts.buildpkgonly and \