diff options
Diffstat (limited to 'lib/_emerge/Scheduler.py')
-rw-r--r-- | lib/_emerge/Scheduler.py | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/lib/_emerge/Scheduler.py b/lib/_emerge/Scheduler.py index ee8f3dd5e..2c0483230 100644 --- a/lib/_emerge/Scheduler.py +++ b/lib/_emerge/Scheduler.py @@ -27,6 +27,7 @@ bad = create_color_func("BAD") from portage._sets import SETPREFIX from portage._sets.base import InternalPackageSet from portage.util import ensure_dirs, writemsg, writemsg_level +from portage.util.futures import asyncio from portage.util.SlotObject import SlotObject from portage.util._async.SchedulerInterface import SchedulerInterface from portage.util._eventloop.EventLoop import EventLoop @@ -241,6 +242,7 @@ class Scheduler(PollScheduler): self._completed_tasks = set() self._main_exit = None self._main_loadavg_handle = None + self._schedule_merge_wakeup_task = None self._failed_pkgs = [] self._failed_pkgs_all = [] @@ -1440,6 +1442,9 @@ class Scheduler(PollScheduler): if self._job_delay_timeout_id is not None: self._job_delay_timeout_id.cancel() self._job_delay_timeout_id = None + if self._schedule_merge_wakeup_task is not None: + self._schedule_merge_wakeup_task.cancel() + self._schedule_merge_wakeup_task = None def _choose_pkg(self): """ @@ -1614,6 +1619,24 @@ class Scheduler(PollScheduler): self._main_loadavg_handle = self._event_loop.call_later( self._loadavg_latency, self._schedule) + # Failure to schedule *after* self._task_queues.merge becomes + # empty will cause the scheduler to hang as in bug 711322. + # Do not rely on scheduling which occurs via the _merge_exit + # method, since the order of callback invocation may cause + # self._task_queues.merge to appear non-empty when it is + # about to become empty. + if (self._task_queues.merge and (self._schedule_merge_wakeup_task is None + or self._schedule_merge_wakeup_task.done())): + self._schedule_merge_wakeup_task = asyncio.ensure_future( + self._task_queues.merge.wait(), loop=self._event_loop) + self._schedule_merge_wakeup_task.add_done_callback( + self._schedule_merge_wakeup) + + def _schedule_merge_wakeup(self, future): + if not future.cancelled(): + future.result() + self._schedule() + def _sigcont_handler(self, signum, frame): self._sigcont_time = time.time() |