summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2013-02-21 14:23:57 -0800
committerZac Medico <zmedico@gentoo.org>2013-02-21 14:24:35 -0800
commit2c7155b8419eb1b7ba99760a962093ad19e2ce8f (patch)
tree4256cfa35e89f96e8a5026feee1a3137bb33e58b
parentRemove "Starting parallel fetch" msg, bug #368297 (diff)
downloadportage-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.py19
-rw-r--r--pym/portage/_sets/files.py6
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