divmod-dev team mailing list archive
-
divmod-dev team
-
Mailing list archive
-
Message #00467
Re: lp:~divmod-dev/divmod.org/829879-pypy-finalization-semantics into lp:divmod.org
So the cause of the problem seems to be this PyPy behavior, which differs from behavior we can observer on CPython: the object a weakref refers to may be collected and then, before the weakref's callback is called, some more Python code gets a chance to run. This means that the callback which cleans up the `data` dict might not run until after some code uses the `get` method. This confuses `get` because it thinks only an internal bookkeeping error can result in a key being present in `data` but the value of the weakref being `None`. On PyPy this is actually a legitimate case, since it's only a matter of the callback not having run /yet/.
This hypothesis is testable, actually. Adding any observable side-effect to the callback will prove that the callback is not being called in time - or that it is.
And some experimentation seems to bear this out. A print statement at the top of `remove` doesn't show up until *after* the first Axiom test which fails this way - that is, the weakref callback has not been called until after the test has failed.
So I am probably convinced this is the right direction to be going now. That said:
1) The `assert` in the `cache` method seems like it may run afoul of this very issue. The key may be present in `data` after the associated object has been collected. It seems this check needs to include inspection of the value of `self.data[k]()`. It is not an error to re-use a cache key if a weakref remains in `data` for the key, but the value of the weakref is `None`.
2) The code could probably use a few more comments. This stuff is not obvious. ;)
3) I think I convinced myself that the new try/except KeyError inside `remove` is also necessary - in case the weakref callback runs after the weakref has been discarded by the new `del` in `get` but PyPy runs its callback anyway (because the garbage collector hasn't collected the weakref object yet). Again, a comment or two explaining this would help the code a bunch, I think.
4) If you don't mind, `w`, `k`, and `f` are not ideal argument names for `createCacheRemoveCallback` (not to mention undocumented).
Changes elsewhere in Axiom seem fine. Thanks! Feel free to merge after addressing the above. I'm also happy to take another look if you like.
--
https://code.launchpad.net/~divmod-dev/divmod.org/829879-pypy-finalization-semantics/+merge/173053
Your team Divmod-dev is subscribed to branch lp:divmod.org.
References