You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Reading from an LRUCache while iterating it crashes the process #75
On LRUCache a read promotes the entry: in, get(), cache[key] and setdefault() move it to the back of the internal list. Doing that while an iterator is alive leaves the iterator on a relinked list, and the process dies with an access violation.
importcacheboxcache=cachebox.LRUCache(10)
forkeyin ('a', 'b', 'c'):
cache[key] =1it=cache.keys()
print('promoting "a" with a lookup ...', flush=True)
assert'a'incacheprint('walking the live iterator ...', flush=True)
print('got:', list(it))
What list(it) gives after that promotion, by version:
6.2.1 and 6.2.2
6.2.3 and 6.2.4
with the fix
list(it)
got: ['a'], two of the three keys silently vanish
the process dies with an access violation
RuntimeError, same as after an insert
cache.get('a'), cache['a'] and cache.setdefault('a') behave the same as 'a' in cache. Checked on Windows, CPython 3.12.
The missing bump is old, only its price changed. On 6.2.1 and 6.2.2 the iterator follows the promoted entry to the back of the list and ends right after it, so keys quietly vanish. The linked list rework from #66 made the same walk die instead, which is actually a step forward: a loud failure gets noticed, while the quiet one had been eating keys unnoticed all along.
An insert under a live iterator raises RuntimeError. A promoting read rewires the same list, it just does not bump the generation, so the iterator never notices.
Activity