From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1Rwpe5-0002rI-TX for garchives@archives.gentoo.org; Mon, 13 Feb 2012 06:44:18 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id C461DE0978; Mon, 13 Feb 2012 06:44:07 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id 84393E0978 for ; Mon, 13 Feb 2012 06:44:07 +0000 (UTC) Received: from hornbill.gentoo.org (hornbill.gentoo.org [94.100.119.163]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id C4AC864C5D for ; Mon, 13 Feb 2012 06:44:06 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by hornbill.gentoo.org (Postfix) with ESMTP id 8DFE6E5400 for ; Mon, 13 Feb 2012 06:44:04 +0000 (UTC) From: "Zac Medico" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" Message-ID: <8346a62a08c91de8b7672faa0ebfb91d0e647fa0.zmedico@gentoo> Subject: [gentoo-commits] proj/portage:master commit in: pym/_emerge/ X-VCS-Repository: proj/portage X-VCS-Files: pym/_emerge/PollScheduler.py pym/_emerge/QueueScheduler.py X-VCS-Directories: pym/_emerge/ X-VCS-Committer: zmedico X-VCS-Committer-Name: Zac Medico X-VCS-Revision: 8346a62a08c91de8b7672faa0ebfb91d0e647fa0 Date: Mon, 13 Feb 2012 06:44:04 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: 3ffdedcd-15d9-4365-a38d-31e0e5c432a8 X-Archives-Hash: 014592156edaf3cb700efa7caf302067 commit: 8346a62a08c91de8b7672faa0ebfb91d0e647fa0 Author: Zac Medico gentoo org> AuthorDate: Mon Feb 13 06:43:46 2012 +0000 Commit: Zac Medico gentoo org> CommitDate: Mon Feb 13 06:43:46 2012 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/portage.git;a= =3Dcommit;h=3D8346a62a PollScheduler: use idle_add to check termination This fixes a regression in termination signal handling since commit 8c1fcf5a9ba9fa4d406a4d0cc284fe73a84f5a63, which cause termination signals to be ignored until a running job had exited. This regression is not really noticeable for Ctrl-C handling, since in that case the SIGINT propagets to subprocesses, causing them to exit and trigger a _schedule() call whichtriggers a termination check. --- pym/_emerge/PollScheduler.py | 61 ++++++++++++++++++++++++++---------= ------ pym/_emerge/QueueScheduler.py | 2 + 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/pym/_emerge/PollScheduler.py b/pym/_emerge/PollScheduler.py index e270e6a..1db6807 100644 --- a/pym/_emerge/PollScheduler.py +++ b/pym/_emerge/PollScheduler.py @@ -59,11 +59,30 @@ class PollScheduler(object): """ self._terminated.set() =20 + def _termination_check(self): + """ + Calls _terminate_tasks() if appropriate. It's guaranteed not to + call it while _schedule_tasks() is being called. The check should + be executed for each iteration of the event loop, for response to + termination signals at the earliest opportunity. It always returns + True, for continuous scheduling via idle_add. + """ + if not self._scheduling and \ + self._terminated.is_set() and \ + not self._terminated_tasks: + self._scheduling =3D True + try: + self._terminated_tasks =3D True + self._terminate_tasks() + finally: + self._scheduling =3D False + return True + def _terminate_tasks(self): """ Send signals to terminate all tasks. This is called once - from self._schedule() in the event dispatching thread. This - prevents it from being called while the _schedule_tasks() + from _keep_scheduling() or _is_work_scheduled() in the event + dispatching thread. It will not be called while the _schedule_tasks() implementation is running, in order to avoid potential interference. All tasks should be cleaned up at the earliest opportunity, but not necessarily before this method returns. @@ -107,31 +126,29 @@ class PollScheduler(object): return False self._scheduling =3D True try: - - if self._terminated.is_set() and \ - not self._terminated_tasks: - self._terminated_tasks =3D True - self._terminate_tasks() - self._schedule_tasks() finally: self._scheduling =3D False =20 def _main_loop(self): - # Populate initial event sources. We only need to do - # this once here, since it can be called during the - # loop from within event handlers. - self._schedule() - - # Loop while there are jobs to be scheduled. - while self._keep_scheduling(): - self.sched_iface.iteration() - - # Clean shutdown of previously scheduled jobs. In the - # case of termination, this allows for basic cleanup - # such as flushing of buffered output to logs. - while self._is_work_scheduled(): - self.sched_iface.iteration() + term_check_id =3D self.sched_iface.idle_add(self._termination_check) + try: + # Populate initial event sources. We only need to do + # this once here, since it can be called during the + # loop from within event handlers. + self._schedule() + + # Loop while there are jobs to be scheduled. + while self._keep_scheduling(): + self.sched_iface.iteration() + + # Clean shutdown of previously scheduled jobs. In the + # case of termination, this allows for basic cleanup + # such as flushing of buffered output to logs. + while self._is_work_scheduled(): + self.sched_iface.iteration() + finally: + self.sched_iface.source_remove(term_check_id) =20 def _is_work_scheduled(self): return bool(self._running_job_count()) diff --git a/pym/_emerge/QueueScheduler.py b/pym/_emerge/QueueScheduler.p= y index 731a677..730bd78 100644 --- a/pym/_emerge/QueueScheduler.py +++ b/pym/_emerge/QueueScheduler.py @@ -43,6 +43,7 @@ class QueueScheduler(PollScheduler): timeout_callback.timeout_id =3D self.sched_iface.timeout_add( timeout, timeout_callback) =20 + term_check_id =3D self.sched_iface.idle_add(self._termination_check) try: while not (timeout_callback is not None and timeout_callback.timed_out): @@ -59,6 +60,7 @@ class QueueScheduler(PollScheduler): timeout_callback.timed_out): self.sched_iface.iteration() finally: + self.sched_iface.source_remove(term_check_id) if timeout_callback is not None: self.sched_iface.unregister(timeout_callback.timeout_id) =20