-
-
Notifications
You must be signed in to change notification settings - Fork 32k
gh-127582: Make object resurrection thread-safe for free threading. #127612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ing. Objects may be temporarily "resurrected" in destructors when calling finalizers or watcher callbacks. We previously undid the resurrection by decrementing the reference count using `Py_SET_REFCNT`. This was not thread-safe because other threads might be accessing the object (modifying its reference count) if it was exposed by the finalizer, watcher callback, or temporarily accessed by a racy dictionary or list access. This adds internal-only thread-safe functions for temporary object resurrection during destructors.
🤖 New build scheduled with the buildbot fleet by @colesbury for commit a7b41c8 🤖 If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, the change LGTM, I just have a suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
return 0; | ||
} | ||
// Slow-path: object has a shared refcount or is not owned by this thread | ||
return _PyObject_ResurrectEndSlow(op); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume the slow path isn't inline so that compiler will inline the fast path and code will be smaller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that exact split of what's in the "fast-path" vs. "slow-path" doesn't matter too much here, but it would be unwieldy to try to put everything in the inline function. In particular, _Py_DecRefSharedIsDead
is big and not exposed outside of object.c
.
Include/internal/pycore_object.h
Outdated
// Temporarily resurrects an object during deallocation. The refcount is set | ||
// to one. | ||
static inline void | ||
_PyObject_Resurrect(PyObject *op) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about naming it something like _PyObject_ResurrectStart
? That would make its corresponding _PyObject_ResurrectEnd
more obvious or maybe change _PyObject_ResurrectEnd
-> _PyObject_UnResurrect
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to _PyObject_ResurrectStart
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks @colesbury for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13. |
Sorry, @colesbury, I could not cleanly backport this to
|
… threading. (pythonGH-127612) Objects may be temporarily "resurrected" in destructors when calling finalizers or watcher callbacks. We previously undid the resurrection by decrementing the reference count using `Py_SET_REFCNT`. This was not thread-safe because other threads might be accessing the object (modifying its reference count) if it was exposed by the finalizer, watcher callback, or temporarily accessed by a racy dictionary or list access. This adds internal-only thread-safe functions for temporary object resurrection during destructors. (cherry picked from commit f4f5308) Co-authored-by: Sam Gross <[email protected]>
GH-127659 is a backport of this pull request to the 3.13 branch. |
…ding. (GH-127612) (GH-127659) Objects may be temporarily "resurrected" in destructors when calling finalizers or watcher callbacks. We previously undid the resurrection by decrementing the reference count using `Py_SET_REFCNT`. This was not thread-safe because other threads might be accessing the object (modifying its reference count) if it was exposed by the finalizer, watcher callback, or temporarily accessed by a racy dictionary or list access. This adds internal-only thread-safe functions for temporary object resurrection during destructors. (cherry picked from commit f4f5308)
…ing. (pythonGH-127612) Objects may be temporarily "resurrected" in destructors when calling finalizers or watcher callbacks. We previously undid the resurrection by decrementing the reference count using `Py_SET_REFCNT`. This was not thread-safe because other threads might be accessing the object (modifying its reference count) if it was exposed by the finalizer, watcher callback, or temporarily accessed by a racy dictionary or list access. This adds internal-only thread-safe functions for temporary object resurrection during destructors.
Objects may be temporarily "resurrected" in destructors when calling finalizers or watcher callbacks. We previously undid the resurrection by decrementing the reference count using
Py_SET_REFCNT
. This was not thread-safe because other threads might be accessing the object (modifying its reference count) if it was exposed by the finalizer, watcher callback, or temporarily accessed by a racy dictionary or list access.This adds internal-only thread-safe functions for temporary object resurrection during destructors.
Py_SET_REFCNT
in destructors #127582