public inbox for gentoo-portage-dev@lists.gentoo.org
 help / color / mirror / Atom feed
From: Zac Medico <zmedico@gentoo.org>
To: gentoo-portage-dev@lists.gentoo.org
Cc: Zac Medico <zmedico@gentoo.org>
Subject: [gentoo-portage-dev] [PATCH] BinpkgFetcher: use async lock (bug 614110)
Date: Sat, 21 Apr 2018 12:27:28 -0700	[thread overview]
Message-ID: <20180421192728.16056-1-zmedico@gentoo.org> (raw)

In order to avoid event loop recursion, convert the
_BinpkgFetcherProcess.lock() method to an async_lock
method for use by BinpkgFetcher.

Bug: https://bugs.gentoo.org/614110
---
 pym/_emerge/BinpkgFetcher.py | 53 +++++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 20 deletions(-)

diff --git a/pym/_emerge/BinpkgFetcher.py b/pym/_emerge/BinpkgFetcher.py
index 5ca7a45cf..2bbc0a26f 100644
--- a/pym/_emerge/BinpkgFetcher.py
+++ b/pym/_emerge/BinpkgFetcher.py
@@ -32,11 +32,24 @@ class BinpkgFetcher(CompositeTask):
 			pkg.cpv) + ".partial"
 
 	def _start(self):
-		self._start_task(
-			_BinpkgFetcherProcess(background=self.background,
-				logfile=self.logfile, pkg=self.pkg, pkg_path=self.pkg_path,
-				pretend=self.pretend, scheduler=self.scheduler),
-			self._fetcher_exit)
+		fetcher = _BinpkgFetcherProcess(background=self.background,
+			logfile=self.logfile, pkg=self.pkg, pkg_path=self.pkg_path,
+			pretend=self.pretend, scheduler=self.scheduler)
+
+		if not self.pretend:
+			portage.util.ensure_dirs(os.path.dirname(self.pkg_path))
+			if "distlocks" in self.pkg.root_config.settings.features:
+				self._start_task(
+					AsyncTaskFuture(future=fetcher.async_lock()),
+					functools.partial(self._start_locked, fetcher))
+				return
+
+		self._start_task(fetcher, self._fetcher_exit)
+
+	def _start_locked(self, fetcher, lock_task):
+		self._assert_current(lock_task)
+		lock_task.future.result()
+		self._start_task(fetcher, self._fetcher_exit)
 
 	def _fetcher_exit(self, fetcher):
 		self._assert_current(fetcher)
@@ -68,13 +81,8 @@ class _BinpkgFetcherProcess(SpawnProcess):
 		pretend = self.pretend
 		bintree = pkg.root_config.trees["bintree"]
 		settings = bintree.settings
-		use_locks = "distlocks" in settings.features
 		pkg_path = self.pkg_path
 
-		if not pretend:
-			portage.util.ensure_dirs(os.path.dirname(pkg_path))
-			if use_locks:
-				self.lock()
 		exists = os.path.exists(pkg_path)
 		resume = exists and os.path.basename(pkg_path) in bintree.invalids
 		if not (pretend or resume):
@@ -184,7 +192,7 @@ class _BinpkgFetcherProcess(SpawnProcess):
 								except OSError:
 									pass
 
-	def lock(self):
+	def async_lock(self):
 		"""
 		This raises an AlreadyLocked exception if lock() is called
 		while a lock is already held. In order to avoid this, call
@@ -194,17 +202,22 @@ class _BinpkgFetcherProcess(SpawnProcess):
 		if self._lock_obj is not None:
 			raise self.AlreadyLocked((self._lock_obj,))
 
-		async_lock = AsynchronousLock(path=self.pkg_path,
-			scheduler=self.scheduler)
-		async_lock.start()
+		result = self.scheduler.create_future()
 
-		if async_lock.wait() != os.EX_OK:
-			# TODO: Use CompositeTask for better handling, like in EbuildPhase.
-			raise AssertionError("AsynchronousLock failed with returncode %s" \
-				% (async_lock.returncode,))
+		def acquired_lock(async_lock):
+			if async_lock.wait() == os.EX_OK:
+				self.locked = True
+				result.set_result(None)
+			else:
+				result.set_exception(AssertionError(
+					"AsynchronousLock failed with returncode %s"
+					% (async_lock.returncode,)))
 
-		self._lock_obj = async_lock
-		self.locked = True
+		self._lock_obj = AsynchronousLock(path=self.pkg_path,
+			scheduler=self.scheduler)
+		self._lock_obj.addExitListener(acquired_lock)
+		self._lock_obj.start()
+		return result
 
 	class AlreadyLocked(portage.exception.PortageException):
 		pass
-- 
2.13.6



             reply	other threads:[~2018-04-21 19:30 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-21 19:27 Zac Medico [this message]
2018-04-21 22:07 ` [gentoo-portage-dev] [PATCH] BinpkgFetcher: use async lock (bug 614110) Brian Dolbec
2018-04-22 22:38   ` Zac Medico

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180421192728.16056-1-zmedico@gentoo.org \
    --to=zmedico@gentoo.org \
    --cc=gentoo-portage-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox