bugfix: ensure all bootstrap context managers are exception-safe

When context managers are used to save and restore values, we need to remember
to use try/finally around the yield in case an exception is thrown.  Otherwise,
the cleanup will be skipped.
This commit is contained in:
Todd Gamblin 2021-08-02 21:51:33 -07:00 committed by Massimiliano Culpo
parent 693c4d8f3a
commit 0a0338ddfa
4 changed files with 37 additions and 27 deletions

View file

@ -593,17 +593,20 @@ def use_platform(new_platform):
assert isinstance(new_platform, Platform), msg.format(new_platform)
original_platform_fn, original_all_platforms_fn = platform, all_platforms
platform = _PickleableCallable(new_platform)
all_platforms = _PickleableCallable([type(new_platform)])
# Clear configuration and compiler caches
spack.config.config.clear_caches()
spack.compilers._cache_config_files = []
try:
platform = _PickleableCallable(new_platform)
all_platforms = _PickleableCallable([type(new_platform)])
yield new_platform
# Clear configuration and compiler caches
spack.config.config.clear_caches()
spack.compilers._cache_config_files = []
platform, all_platforms = original_platform_fn, original_all_platforms_fn
yield new_platform
# Clear configuration and compiler caches
spack.config.config.clear_caches()
spack.compilers._cache_config_files = []
finally:
platform, all_platforms = original_platform_fn, original_all_platforms_fn
# Clear configuration and compiler caches
spack.config.config.clear_caches()
spack.compilers._cache_config_files = []

View file

@ -1238,11 +1238,12 @@ def use_configuration(*scopes_or_paths):
saved_config, config = config, configuration
yield configuration
# Restore previous config files
spack.compilers._cache_config_file = saved_compiler_cache
config = saved_config
try:
yield configuration
finally:
# Restore previous config files
spack.compilers._cache_config_file = saved_compiler_cache
config = saved_config
@llnl.util.lang.memoized

View file

@ -1299,19 +1299,24 @@ def use_repositories(*paths_and_repos):
"""
global path
remove_from_meta = None
# Construct a temporary RepoPath object from
temporary_repositories = RepoPath(*paths_and_repos)
# Swap the current repository out
saved = path
remove_from_meta = set_path(temporary_repositories)
yield temporary_repositories
try:
remove_from_meta = set_path(temporary_repositories)
# Restore _path and sys.meta_path
if remove_from_meta:
sys.meta_path.remove(temporary_repositories)
path = saved
yield temporary_repositories
finally:
# Restore _path and sys.meta_path
if remove_from_meta:
sys.meta_path.remove(temporary_repositories)
path = saved
class RepoError(spack.error.SpackError):

View file

@ -301,9 +301,10 @@ def use_store(store_or_path):
db, layout = store.db, store.layout
root, unpadded_root = store.root, store.unpadded_root
yield temporary_store
# Restore the original store
store = original_store
db, layout = original_store.db, original_store.layout
root, unpadded_root = original_store.root, original_store.unpadded_root
try:
yield temporary_store
finally:
# Restore the original store
store = original_store
db, layout = original_store.db, original_store.layout
root, unpadded_root = original_store.root, original_store.unpadded_root