Skip to content
Merged
Prev Previous commit
Next Next commit
fix races in WeakKeyDict and WeakValueDict
  • Loading branch information
graingert committed Aug 24, 2021
commit 738dc9acf73d8721702b9300019b06eb7223259f
27 changes: 18 additions & 9 deletions Lib/weakref.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,17 @@ def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
self.update(other, **kw)

def _commit_removals(self):
l = self._pending_removals
pop = self._pending_removals.pop
Comment thread
graingert marked this conversation as resolved.
d = self.data
# We shouldn't encounter any KeyError, because this method should
# always be called *before* mutating the dict.
while l:
key = l.pop()
_remove_dead_weakref(d, key)
while True:
try:
key = pop()
except IndexError:
return
else:
_remove_dead_weakref(d, key)
Comment thread
ambv marked this conversation as resolved.
Outdated
Comment thread
graingert marked this conversation as resolved.
Outdated

def __getitem__(self, key):
if self._pending_removals:
Expand Down Expand Up @@ -384,13 +388,18 @@ def _commit_removals(self):
# because a dead weakref never compares equal to a live weakref,
# even if they happened to refer to equal objects.
# However, it means keys may already have been removed.
l = self._pending_removals
pop = self._pending_removals.pop
d = self.data
while l:
while True:
try:
del d[l.pop()]
except KeyError:
pass
key = pop()
except IndexError:
return
else:
try:
del d[key]
except KeyError:
pass
Comment thread
graingert marked this conversation as resolved.
Outdated

def _scrub_removals(self):
d = self.data
Expand Down