GH-124715: trashcan protection for all GC objects#124716
Closed
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is an update of my GH-89060 PR, ported to current 'main' branch. The issue and fix are still the same as when the original Roundup bug was created: https://bugs.python.org/issue44897
Integrate the functionality of Py_TRASHCAN_BEGIN and Py_TRASHCAN_END into
_Py_Dealloc. There are a few advantages:all container objects have the risk of overflowing the C stack if a long reference chain of them is created and then deallocated. So, to be safe, the tp_dealloc methods for those objects should be protected from overflowing the stack.
the Py_TRASHCAN_BEGIN and Py_TRASHCAN_END macros are hard to understand and a bit hard to use correctly. Making the mechanism internal avoids confusion. The code can be slightly simplified as well.
This is a conceptually simple change but there are some subtle issues to take care with. Previous to this change, tp_dealloc was called with the object tracked. After this change, _Py_Dealloc will automatically call untrack for you.
For types using the internal API, they are changed to not call
_PyObject_GC_UNTRACK(). It's not safe to call that twice. For the public API, callingPyObject_GC_UnTrack()multiple times is safe and so types that use that API in their tp_dealloc should work without change.Another subtle issue is that if an object ends up resurrected inside tp_dealloc, the object should end up being tracked again. I've changed
PyObject_CallFinalizerFromDealloc()to do that.This still has the risk of breaking 3rd party extensions. E.g. if they assert that the object is tracked when entering their tp_dealloc, that will now fail. I think that risk is worth the extra robustness Python will gain by having this protection for all GC types.