Skip to content

Release v6.2.8

Latest

Choose a tag to compare

@awolverp awolverp released this 08 Oct 16:13
· 7 commits to main since this release

This is a patch release that fixes three correctness bugs: a deadlock when eviction runs a __del__, a free-threaded iterator segfault, and an interpreter abort when a cache subclass skips super().__init__().

What's Changed

  • Stops a deadlock when two threads insert into a full cache and an evicted value has __del__ (#95). Eviction used to drop the old value while holding the cache lock; if __del__ released the GIL, the other thread could take the GIL and block in lock() forever. On free-threaded builds that attached waiter could also stall a gc.collect() stop-the-world pause. Lock waits now use MutexExt::lock_py_attached, which detaches while blocked. Regression tests cover all cache types.
  • On free-threaded CPython, iterating keys(), values(), or items() while another thread replaces an existing key's value no longer segfaults (#94). Those views checked the generation counter and then read the table without the lock, and a value replace did not bump the generation (except on LRUCache). Free-threaded builds now increment the generation on replace, so a live iterator raises RuntimeError instead of reading freed memory. GIL builds are unchanged: only LRUCache still invalidates iterators on replace.
  • A cache subclass whose __init__ does not call super().__init__(), or a second call to __init__, now raises RuntimeError instead of aborting the process (#96). Release builds use panic = "abort", so the old panic killed the interpreter before Python could catch it. Applies to all seven cache classes.

Thanks to

Full Changelog: v6.2.7...v6.2.8