summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2016-08-20 15:18:23 -0700
committerTodd Gamblin <tgamblin@llnl.gov>2016-10-11 01:55:32 -0700
commit907fe912ef62501d4379635ff1dfe9cea921cec3 (patch)
tree59d9af6d60161454baac6b64c326c43af34273a8
parentf22929088074ca2b5c52862184b447eb98a17f4d (diff)
downloadspack-907fe912ef62501d4379635ff1dfe9cea921cec3.tar.gz
spack-907fe912ef62501d4379635ff1dfe9cea921cec3.tar.bz2
spack-907fe912ef62501d4379635ff1dfe9cea921cec3.tar.xz
spack-907fe912ef62501d4379635ff1dfe9cea921cec3.zip
Make llnl.util.lock use file objects instead of low-level OS fds.
- Make sure we write, truncate, flush when setting PID and owning host in the file.
-rw-r--r--lib/spack/llnl/util/lock.py36
-rw-r--r--lib/spack/spack/test/lock.py2
2 files changed, 20 insertions, 18 deletions
diff --git a/lib/spack/llnl/util/lock.py b/lib/spack/llnl/util/lock.py
index 2cde389bd2..ce31a59d62 100644
--- a/lib/spack/llnl/util/lock.py
+++ b/lib/spack/llnl/util/lock.py
@@ -54,7 +54,7 @@ class Lock(object):
def __init__(self, file_path):
self._file_path = file_path
- self._fd = None
+ self._file = None
self._reads = 0
self._writes = 0
@@ -75,21 +75,23 @@ class Lock(object):
try:
# If this is already open read-only and we want to
# upgrade to an exclusive write lock, close first.
- if self._fd is not None:
- flags = fcntl.fcntl(self._fd, fcntl.F_GETFL)
- if op == fcntl.LOCK_EX and flags | os.O_RDONLY:
- os.close(self._fd)
- self._fd = None
-
- if self._fd is None:
- mode = os.O_RDWR if op == fcntl.LOCK_EX else os.O_RDONLY
- self._fd = os.open(self._file_path, mode)
-
- fcntl.lockf(self._fd, op | fcntl.LOCK_NB)
+ if self._file is not None:
+ if op == fcntl.LOCK_EX and self._file.mode == 'r':
+ self._file.close()
+ self._file = None
+
+ # Open reader locks read-only if possible.
+ # lock doesn't exist, open RW + create if it doesn't exist.
+ if self._file is None:
+ mode = 'r+' if op == fcntl.LOCK_EX else 'r'
+ self._file = open(self._file_path, mode)
+
+ fcntl.lockf(self._file, op | fcntl.LOCK_NB)
if op == fcntl.LOCK_EX:
- os.write(
- self._fd,
+ self._file.write(
"pid=%s,host=%s" % (os.getpid(), socket.getfqdn()))
+ self._file.truncate()
+ self._file.flush()
return
except IOError as error:
@@ -108,9 +110,9 @@ class Lock(object):
be masquerading as write locks, but this removes either.
"""
- fcntl.lockf(self._fd, fcntl.LOCK_UN)
- os.close(self._fd)
- self._fd = None
+ fcntl.lockf(self._file, fcntl.LOCK_UN)
+ self._file.close()
+ self._file = None
def acquire_read(self, timeout=_default_timeout):
"""Acquires a recursive, shared lock for reading.
diff --git a/lib/spack/spack/test/lock.py b/lib/spack/spack/test/lock.py
index 32cbe13ce1..30b7dbce0e 100644
--- a/lib/spack/spack/test/lock.py
+++ b/lib/spack/spack/test/lock.py
@@ -184,7 +184,7 @@ class LockTest(unittest.TestCase):
lock.release_read()
self.assertTrue(lock._reads == 0)
self.assertTrue(lock._writes == 0)
- self.assertTrue(lock._fd is None)
+ self.assertTrue(lock._file is None)
#
# Longer test case that ensures locks are reusable. Ordering is