提交 252b7709 authored 作者: Olivier Delalleau's avatar Olivier Delalleau

Fixed potential issue where compiledir lock could be released too early (before writing into it)

上级 17912cb5
...@@ -301,7 +301,8 @@ class ModuleCache(object): ...@@ -301,7 +301,8 @@ class ModuleCache(object):
# add entries that are not in the entry_from_key dictionary # add entries that are not in the entry_from_key dictionary
time_now = time.time() time_now = time.time()
for root, dirs, files in os.walk(self.dirname): for root, dirs, files in os.walk(self.dirname):
if os.path.join(root, 'key.pkl') in self.loaded_key_pkl: key_pkl = os.path.join(root, 'key.pkl')
if key_pkl in self.loaded_key_pkl:
continue continue
elif 'delete.me' in files or len(files)==0: elif 'delete.me' in files or len(files)==0:
# On NFS filesystems, it is impossible to delete a directory with open # On NFS filesystems, it is impossible to delete a directory with open
...@@ -314,13 +315,12 @@ class ModuleCache(object): ...@@ -314,13 +315,12 @@ class ModuleCache(object):
# the directory is still in use?? We just leave it for future removal. # the directory is still in use?? We just leave it for future removal.
pass pass
elif 'key.pkl' in files: elif 'key.pkl' in files:
key_pkl = os.path.join(root, 'key.pkl')
try: try:
entry = module_name_from_dir(root) entry = module_name_from_dir(root)
except ValueError: # there is a key but no dll! except ValueError: # there is a key but no dll!
if not root.startswith("/tmp"): if not root.startswith("/tmp"):
# Under /tmp, file are removed periodically by the os. # Under /tmp, file are removed periodically by the os.
# So it is normal that this happen from time to time. # So it is normal that this happens from time to time.
warning("ModuleCache.refresh() Found key without dll in cache, deleting it.", key_pkl) warning("ModuleCache.refresh() Found key without dll in cache, deleting it.", key_pkl)
info("Erasing broken cache directory", key_pkl) info("Erasing broken cache directory", key_pkl)
shutil.rmtree(root) shutil.rmtree(root)
...@@ -419,37 +419,36 @@ class ModuleCache(object): ...@@ -419,37 +419,36 @@ class ModuleCache(object):
rval = self.module_from_name[name] rval = self.module_from_name[name]
else: else:
hash_key = hash(key) hash_key = hash(key)
# we have never seen this key before # We have never seen this key before.
# Acquire lock before creating things in the compile cache, # Acquire lock before creating things in the compile cache,
# to avoid that other processes remove the compile dire while it # to avoid that other processes remove the compile dir while it
# is still empty # is still empty.
compilelock.get_lock() compilelock.get_lock()
# This try/finally block ensures that the lock is released once we
# are done writing in the cache file or after raising an exception.
try:
location = dlimport_workdir(self.dirname) location = dlimport_workdir(self.dirname)
#debug("LOCATION*", location) #debug("LOCATION*", location)
try: try:
module = fn(location=location) # WILL FAIL FOR BAD C CODE module = fn(location=location) # WILL FAIL FOR BAD C CODE
except Exception, e: except Exception, e:
_rmtree(location) _rmtree(location)
if not keep_lock:
compilelock.release_lock()
#try: #try:
#except Exception, ee: #except Exception, ee:
#error('failed to cleanup location', location, ee) #error('failed to cleanup location', location, ee)
raise raise
if not keep_lock:
compilelock.release_lock()
name = module.__file__ name = module.__file__
debug("Adding module to cache", key, name) debug("Adding module to cache", key, name)
assert name.startswith(location) assert name.startswith(location)
assert name not in self.module_from_name assert name not in self.module_from_name
#Changing the hash of the key is not allowed during compilation # Changing the hash of the key is not allowed during
#That is the only cause found that make the last assert fail. # compilation. That is the only cause found that makes the
assert hash(key)==hash_key # following assert fail.
assert hash(key) == hash_key
assert key not in self.entry_from_key assert key not in self.entry_from_key
assert key not in self.entry_from_key
if _version: # save they key if _version: # save they key
key_pkl = os.path.join(location, 'key.pkl') key_pkl = os.path.join(location, 'key.pkl')
# Note that using a binary file is important under Windows. # Note that using a binary file is important under Windows.
...@@ -468,10 +467,21 @@ class ModuleCache(object): ...@@ -468,10 +467,21 @@ class ModuleCache(object):
try: try:
key_from_file = cPickle.load(open(key_pkl, 'rb')) key_from_file = cPickle.load(open(key_pkl, 'rb'))
if key != key_from_file: if key != key_from_file:
raise Exception("key not equal to unpickled version (Hint: verify the __eq__ and __hash__ functions for your Ops", (key, key_from_file)) raise Exception(
self.loaded_key_pkl.add(key_pkl) # adding the key file to this set means it is a versioned key "key not equal to unpickled version (Hint:"
" verify the __eq__ and __hash__ functions"
" for your Ops", (key, key_from_file))
# Adding the key file to this set measn it is a
# versioned key.
self.loaded_key_pkl.add(key_pkl)
except cPickle.UnpicklingError: except cPickle.UnpicklingError:
warning('Cache failure due to un-loadable key', key) warning('Cache failure due to un-loadable key',
key)
finally:
# Release lock if needed.
if not keep_lock:
compilelock.release_lock()
self.entry_from_key[key] = name self.entry_from_key[key] = name
self.module_from_name[name] = module self.module_from_name[name] = module
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论