From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 8D353139694 for ; Mon, 27 Mar 2017 21:41:23 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 4023821C012; Mon, 27 Mar 2017 21:41:21 +0000 (UTC) Received: from smtp.gentoo.org (mail.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 0E05C21C012 for ; Mon, 27 Mar 2017 21:41:20 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id B4141341673 for ; Mon, 27 Mar 2017 21:41:19 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id E965B70B7 for ; Mon, 27 Mar 2017 21:41:17 +0000 (UTC) From: "Zac Medico" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" Message-ID: <1490650838.eaf22a6d88ad8e0b7a3a1e21f3234c6b7037018a.zmedico@gentoo> Subject: [gentoo-commits] proj/portage:master commit in: pym/_emerge/ X-VCS-Repository: proj/portage X-VCS-Files: pym/_emerge/SpawnProcess.py pym/_emerge/SubProcess.py X-VCS-Directories: pym/_emerge/ X-VCS-Committer: zmedico X-VCS-Committer-Name: Zac Medico X-VCS-Revision: eaf22a6d88ad8e0b7a3a1e21f3234c6b7037018a X-VCS-Branch: master Date: Mon, 27 Mar 2017 21:41:17 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 5165dbb4-64f5-4fa0-9ea0-5683247311bd X-Archives-Hash: d04dc5021c3186fdac926f1891a3b090 commit: eaf22a6d88ad8e0b7a3a1e21f3234c6b7037018a Author: Zac Medico gentoo org> AuthorDate: Mon Mar 27 06:44:02 2017 +0000 Commit: Zac Medico gentoo org> CommitDate: Mon Mar 27 21:40:38 2017 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=eaf22a6d SpawnProcess: fix event loop recursion in _pipe_logger_exit (bug 613990) Fix SpawnProcess._pipe_logger_exit to wait for process exit status asynchronously, in order to avoid event loop recursion. This is required for asyncio compatibility, and also protects emerge from exceeding the maximum recursion depth limit like in bug 402335. X-Gentoo-bug: 613990 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=613990 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/SpawnProcess.py | 3 +-- pym/_emerge/SubProcess.py | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/pym/_emerge/SpawnProcess.py b/pym/_emerge/SpawnProcess.py index e046640ea..7326254ca 100644 --- a/pym/_emerge/SpawnProcess.py +++ b/pym/_emerge/SpawnProcess.py @@ -170,8 +170,7 @@ class SpawnProcess(SubProcess): def _pipe_logger_exit(self, pipe_logger): self._pipe_logger = None - self._unregister() - self.wait() + self._async_waitpid() def _waitpid_loop(self): SubProcess._waitpid_loop(self) diff --git a/pym/_emerge/SubProcess.py b/pym/_emerge/SubProcess.py index 13d938297..b81cfd5f6 100644 --- a/pym/_emerge/SubProcess.py +++ b/pym/_emerge/SubProcess.py @@ -12,7 +12,7 @@ import errno class SubProcess(AbstractPollTask): __slots__ = ("pid",) + \ - ("_dummy_pipe_fd", "_files", "_reg_id") + ("_dummy_pipe_fd", "_files", "_reg_id", "_waitpid_id") # This is how much time we allow for waitpid to succeed after # we've sent a kill signal to our subprocess. @@ -101,6 +101,23 @@ class SubProcess(AbstractPollTask): return self.returncode + def _async_waitpid(self): + """ + Wait for exit status of self.pid asynchronously, and then + set the returncode and notify exit listeners. This is + prefered over _waitpid_loop, since the synchronous nature + of _waitpid_loop can cause event loop recursion. + """ + if self._waitpid_id is None: + self._waitpid_id = self.scheduler.child_watch_add( + self.pid, self._async_waitpid_cb) + + def _async_waitpid_cb(self, pid, condition, user_data=None): + if pid != self.pid: + raise AssertionError("expected pid %s, got %s" % (self.pid, pid)) + self._set_returncode((pid, condition)) + self.wait() + def _waitpid_loop(self): source_id = self.scheduler.child_watch_add( self.pid, self._waitpid_cb) @@ -129,6 +146,10 @@ class SubProcess(AbstractPollTask): self.scheduler.source_remove(self._reg_id) self._reg_id = None + if self._waitpid_id is not None: + self.scheduler.source_remove(self._waitpid_id) + self._waitpid_id = None + if self._files is not None: for f in self._files.values(): if isinstance(f, int):