diff --git a/lib/spack/spack/database.py b/lib/spack/spack/database.py index 7fe1b8fcef..3c7258728f 100644 --- a/lib/spack/spack/database.py +++ b/lib/spack/spack/database.py @@ -358,6 +358,14 @@ def __init__(self, root, db_dir=None, upstream_dbs=None, self.is_upstream = is_upstream self.last_seen_verifier = '' + # Failed write transactions (interrupted by exceptions) will alert + # _write. When that happens, we set this flag to indicate that + # future read/write transactions should re-read the DB. Normally it + # would make more sense to resolve this at the end of the transaction + # but typically a failed transaction will terminate the running + # instance of Spack and we don't want to incur an extra read in that + # case, so we defer the cleanup to when we begin the next transaction + self._state_is_inconsistent = False # initialize rest of state. self.db_lock_timeout = ( @@ -992,6 +1000,10 @@ def _write(self, type, value, traceback): """ # Do not write if exceptions were raised if type is not None: + # A failure interrupted a transaction, so we should record that + # the Database is now in an inconsistent state: we should + # restore it in the next transaction + self._state_is_inconsistent = True return temp_file = self._index_path + ( @@ -1030,6 +1042,9 @@ def _read(self): self.last_seen_verifier = current_verifier # Read from file if a database exists self._read_from_file(self._index_path) + elif self._state_is_inconsistent: + self._read_from_file(self._index_path) + self._state_is_inconsistent = False return elif self.is_upstream: raise UpstreamDatabaseLockingError(