Repository navigation
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 inlock()forever. On free-threaded builds that attached waiter could also stall agc.collect()stop-the-world pause. Lock waits now useMutexExt::lock_py_attached, which detaches while blocked. Regression tests cover all cache types. - On free-threaded CPython, iterating
keys(),values(), oritems()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 onLRUCache). Free-threaded builds now increment the generation on replace, so a live iterator raisesRuntimeErrorinstead of reading freed memory. GIL builds are unchanged: onlyLRUCachestill invalidates iterators on replace. - A cache subclass whose
__init__does not callsuper().__init__(), or a second call to__init__, now raisesRuntimeErrorinstead of aborting the process (#96). Release builds usepanic = "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