Pārlūkot izejas kodu

Merge pull request #7941 from ThomasWaldmann/lockroster-remove-fix-master

LockRoster.modify: no KeyError if element was already gone, fixes #7937
TW 1 gadu atpakaļ
vecāks
revīzija
6a5feaffac
3 mainītis faili ar 10 papildinājumiem un 4 dzēšanām
  1. 7 2
      src/borg/locking.py
  2. 2 1
      src/borg/repository.py
  3. 1 1
      src/borg/testsuite/locking.py

+ 7 - 2
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__)
@@ -326,6 +326,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)
@@ -340,7 +345,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

+ 2 - 1
src/borg/repository.py

@@ -11,6 +11,7 @@ from configparser import ConfigParser
 from datetime import datetime, timezone
 from functools import partial
 from itertools import islice
+from typing import Callable, DefaultDict
 
 from .constants import *  # NOQA
 from .hashindex import NSIndexEntry, NSIndex, NSIndex1, hashindex_variant
@@ -48,7 +49,7 @@ TAG_PUT2 = 3
 # may not be able to handle the new tags.
 MAX_TAG_ID = 15
 
-FreeSpace = partial(defaultdict, int)
+FreeSpace: Callable[[], DefaultDict] = partial(defaultdict, int)
 
 
 def header_size(tag):

+ 1 - 1
src/borg/testsuite/locking.py

@@ -280,7 +280,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):