summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTom Scogland <scogland1@llnl.gov>2021-12-22 07:25:05 -0800
committerGitHub <noreply@github.com>2021-12-22 16:25:05 +0100
commitb7b654280485c0e84692b4706abe0ef97f01535c (patch)
tree1f90f968639533e39296a88ec0d78db9ffb2141f /lib
parent34873f5fe72ca244df63307b4a19efea42f2dac3 (diff)
downloadspack-b7b654280485c0e84692b4706abe0ef97f01535c.tar.gz
spack-b7b654280485c0e84692b4706abe0ef97f01535c.tar.bz2
spack-b7b654280485c0e84692b4706abe0ef97f01535c.tar.xz
spack-b7b654280485c0e84692b4706abe0ef97f01535c.zip
locks: allow locks to work under high contention (#27846)
* locks: allow locks to work under high contention This is a bug found by Harshitha Menon. The `lock=None` line shouldn't be a release but should be ``` return (lock_type, None) ``` to inform the caller it couldn't get the lock type requested without disturbing the existing lock object in the database. There were also a couple of bugs due to taking write locks at the beginning without any checking or release, and not releasing read locks before requeueing. This version no longer gives me read upgrade to write errors, even running 200 instances on one box. * Change lock in check_deps_status to read, release if not installed, not sure why this was ever write, but read definitely is more appropriate here, and the read lock is only held out of the scope if the package is installed. * Release read lock before requeueing to reduce chance of livelock, the timeout that caused the original issue now happens in roughly 3 of 200 workers instead of 199 on average.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/installer.py9
1 files changed, 6 insertions, 3 deletions
diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py
index d464817f92..d70f535a89 100644
--- a/lib/spack/spack/installer.py
+++ b/lib/spack/spack/installer.py
@@ -794,10 +794,10 @@ class PackageInstaller(object):
.format(dep_id, action)
raise InstallError(err.format(request.pkg_id, msg))
- # Attempt to get a write lock to ensure another process does not
+ # Attempt to get a read lock to ensure another process does not
# uninstall the dependency while the requested spec is being
# installed
- ltype, lock = self._ensure_locked('write', dep_pkg)
+ ltype, lock = self._ensure_locked('read', dep_pkg)
if lock is None:
msg = '{0} is write locked by another process'.format(dep_id)
raise InstallError(err.format(request.pkg_id, msg))
@@ -816,6 +816,8 @@ class PackageInstaller(object):
tty.debug('Flagging {0} as installed per the database'
.format(dep_id))
self._flag_installed(dep_pkg)
+ else:
+ lock.release_read()
def _prepare_for_install(self, task):
"""
@@ -1027,7 +1029,7 @@ class PackageInstaller(object):
except (lk.LockDowngradeError, lk.LockTimeoutError) as exc:
tty.debug(err.format(op, desc, pkg_id, exc.__class__.__name__,
str(exc)))
- lock = None
+ return (lock_type, None)
except (Exception, KeyboardInterrupt, SystemExit) as exc:
tty.error(err.format(op, desc, pkg_id, exc.__class__.__name__,
@@ -1627,6 +1629,7 @@ class PackageInstaller(object):
# established by the other process -- failed, installed, or
# uninstalled -- on the next pass.
if ltype == 'read':
+ lock.release_read()
self._requeue_task(task)
continue