diff options
author | Thomas Waldmann <tw@waldmann-edv.de> | 2023-11-16 14:40:06 +0100 |
---|---|---|
committer | Thomas Waldmann <tw@waldmann-edv.de> | 2023-11-16 15:59:28 +0100 |
commit | ec17b00411a2a9566fea2756c5f6f9ee7b8717c4 (patch) | |
tree | 063f170922db1e58bda943dc995ef517caacc379 /src | |
parent | 2341ba62d39d485fd7199105812792d24a4772b8 (diff) |
LockRoster.modify: no KeyError if element was already gone, fixes #7937
The intention of LockRoster.modify(key, REMOVE) is to remove self.id.
Using set.discard will just ignore it if self.id is not present there anymore.
Previously, using set.remove triggered a KeyError that has been frequently
seen in tracebacks of teardowns involving Repository.__del__ and Repository.__exit__.
I added a REMOVE2 op to serve one caller that needs to get the KeyError if
self.id was not present.
Thanks to @herrmanntom for the workaround!
Diffstat (limited to 'src')
-rw-r--r-- | src/borg/locking.py | 9 | ||||
-rw-r--r-- | src/borg/testsuite/locking.py | 2 |
2 files changed, 8 insertions, 3 deletions
diff --git a/src/borg/locking.py b/src/borg/locking.py index 4192f1f10..7ddb6df74 100644 --- a/src/borg/locking.py +++ b/src/borg/locking.py @@ -8,7 +8,7 @@ from . import platform from .helpers import Error, ErrorWithTraceback from .logger import create_logger -ADD, REMOVE = 'add', 'remove' +ADD, REMOVE, REMOVE2 = 'add', 'remove', 'remove2' SHARED, EXCLUSIVE = 'shared', 'exclusive' logger = create_logger(__name__) @@ -313,6 +313,11 @@ class LockRoster: if op == ADD: elements.add(self.id) elif op == REMOVE: + # note: we ignore it if the element is already not present anymore. + # this has been frequently seen in teardowns involving Repository.__del__ and Repository.__exit__. + elements.discard(self.id) + elif op == REMOVE2: + # needed for callers that do not want to ignore. elements.remove(self.id) else: raise ValueError('Unknown LockRoster op %r' % op) @@ -327,7 +332,7 @@ class LockRoster: killing, self.kill_stale_locks = self.kill_stale_locks, False try: try: - self.modify(key, REMOVE) + self.modify(key, REMOVE2) except KeyError: # entry was not there, so no need to add a new one, but still update our id self.id = new_id diff --git a/src/borg/testsuite/locking.py b/src/borg/testsuite/locking.py index b8fb67797..5c593bdda 100644 --- a/src/borg/testsuite/locking.py +++ b/src/borg/testsuite/locking.py @@ -241,7 +241,7 @@ class TestLock: assert roster.get(SHARED) == {our_id} assert roster.get(EXCLUSIVE) == set() assert roster.get(SHARED) == set() - with pytest.raises(KeyError): + with pytest.raises(NotLocked): dead_lock.release() with Lock(lockpath, id=cant_know_if_dead_id, exclusive=True): |