diff options
author | Zac Medico <zmedico@gentoo.org> | 2013-02-21 14:23:57 -0800 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2013-02-21 14:24:35 -0800 |
commit | 2c7155b8419eb1b7ba99760a962093ad19e2ce8f (patch) | |
tree | 4256cfa35e89f96e8a5026feee1a3137bb33e58b | |
parent | Remove "Starting parallel fetch" msg, bug #368297 (diff) | |
download | portage-2c7155b8419eb1b7ba99760a962093ad19e2ce8f.tar.gz portage-2c7155b8419eb1b7ba99760a962093ad19e2ce8f.tar.bz2 portage-2c7155b8419eb1b7ba99760a962093ad19e2ce8f.zip |
_world_atom: avoid world set lock reentrance
This fixes a case with FEATURE=parallel-install, where a call from
_world_atom to the global event loop could result in reentrace and
lock interference.
-rw-r--r-- | pym/_emerge/Scheduler.py | 19 | ||||
-rw-r--r-- | pym/portage/_sets/files.py | 6 |
2 files changed, 19 insertions, 6 deletions
diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py index 4b29c7110..5930550fa 100644 --- a/pym/_emerge/Scheduler.py +++ b/pym/_emerge/Scheduler.py @@ -1896,11 +1896,21 @@ class Scheduler(PollScheduler): root_config = pkg.root_config world_set = root_config.sets["selected"] world_locked = False - if hasattr(world_set, "lock"): - world_set.lock() - world_locked = True + atom = None + + if pkg.operation != "uninstall": + # Do this before acquiring the lock, since it queries the + # portdbapi which can call the global event loop, triggering + # a concurrent call to this method or something else that + # needs an exclusive (non-reentrant) lock on the world file. + atom = create_world_atom(pkg, args_set, root_config) try: + + if hasattr(world_set, "lock"): + world_set.lock() + world_locked = True + if hasattr(world_set, "load"): world_set.load() # maybe it's changed on disk @@ -1912,8 +1922,7 @@ class Scheduler(PollScheduler): for s in pkg.root_config.setconfig.active: world_set.remove(SETPREFIX+s) else: - atom = create_world_atom(pkg, args_set, root_config) - if atom: + if atom is not None: if hasattr(world_set, "add"): self._status_msg(('Recording %s in "world" ' + \ 'favorites file...') % atom) diff --git a/pym/portage/_sets/files.py b/pym/portage/_sets/files.py index b839582df..2fb64de87 100644 --- a/pym/portage/_sets/files.py +++ b/pym/portage/_sets/files.py @@ -1,4 +1,4 @@ -# Copyright 2007-2012 Gentoo Foundation +# Copyright 2007-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import errno @@ -296,10 +296,14 @@ class WorldSelectedSet(EditablePackageSet): ensure_dirs(os.path.dirname(self._filename), gid=portage_gid, mode=0o2750, mask=0o2) def lock(self): + if self._lock is not None: + raise AssertionError("already locked") self._ensure_dirs() self._lock = lockfile(self._filename, wantnewlockfile=1) def unlock(self): + if self._lock is None: + raise AssertionError("not locked") unlockfile(self._lock) self._lock = None |