-
-
Notifications
You must be signed in to change notification settings - Fork 29.9k
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
_Py_MergeZeroLocalRefcount should not set ob_tid to zero in fast-path dealloc
#121794
Labels
3.13
bugs and security fixes
3.14
new features, bugs and security fixes
topic-free-threading
type-bug
An unexpected behavior, bug, or error
Comments
colesbury
added a commit
to colesbury/cpython
that referenced
this issue
Jul 15, 2024
We should maintain the invariant that a zero `ob_tid` implies the refcount fields are merged. * Move the assignment in `_Py_MergeZeroLocalRefcount` to immediately before the refcount merge. * Update `_PyTrash_thread_destroy_chain` to set `ob_ref_shared` to `_Py_REF_MERGED` when setting `ob_tid` to zero. Also check this invariant with assertions in the GC in debug builds. That uncovered a bug when running out of memory during GC.
colesbury
added a commit
that referenced
this issue
Jul 15, 2024
We should maintain the invariant that a zero `ob_tid` implies the refcount fields are merged. * Move the assignment in `_Py_MergeZeroLocalRefcount` to immediately before the refcount merge. * Update `_PyTrash_thread_destroy_chain` to set `ob_ref_shared` to `_Py_REF_MERGED` when setting `ob_tid` to zero. Also check this invariant with assertions in the GC in debug builds. That uncovered a bug when running out of memory during GC.
miss-islington
pushed a commit
to miss-islington/cpython
that referenced
this issue
Jul 15, 2024
…honGH-121799) We should maintain the invariant that a zero `ob_tid` implies the refcount fields are merged. * Move the assignment in `_Py_MergeZeroLocalRefcount` to immediately before the refcount merge. * Update `_PyTrash_thread_destroy_chain` to set `ob_ref_shared` to `_Py_REF_MERGED` when setting `ob_tid` to zero. Also check this invariant with assertions in the GC in debug builds. That uncovered a bug when running out of memory during GC. (cherry picked from commit d23be39) Co-authored-by: Sam Gross <colesbury@gmail.com>
colesbury
added a commit
that referenced
this issue
Jul 15, 2024
…-121799) (#121821) We should maintain the invariant that a zero `ob_tid` implies the refcount fields are merged. * Move the assignment in `_Py_MergeZeroLocalRefcount` to immediately before the refcount merge. * Update `_PyTrash_thread_destroy_chain` to set `ob_ref_shared` to `_Py_REF_MERGED` when setting `ob_tid` to zero. Also check this invariant with assertions in the GC in debug builds. That uncovered a bug when running out of memory during GC. (cherry picked from commit d23be39) Co-authored-by: Sam Gross <colesbury@gmail.com>
estyxx
pushed a commit
to estyxx/cpython
that referenced
this issue
Jul 17, 2024
…hon#121799) We should maintain the invariant that a zero `ob_tid` implies the refcount fields are merged. * Move the assignment in `_Py_MergeZeroLocalRefcount` to immediately before the refcount merge. * Update `_PyTrash_thread_destroy_chain` to set `ob_ref_shared` to `_Py_REF_MERGED` when setting `ob_tid` to zero. Also check this invariant with assertions in the GC in debug builds. That uncovered a bug when running out of memory during GC.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
3.13
bugs and security fixes
3.14
new features, bugs and security fixes
topic-free-threading
type-bug
An unexpected behavior, bug, or error

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.

Bug report
The
_Py_MergeZeroLocalRefcountfunction is called when the local refcount field reaches zero. We generally maintain the invariant 1 thatob_tid == 0implies that the refcount fields are merged (i.e.,ob_ref_sharedflags are_Py_REF_MERGED) and vice versa.The current implementation breaks the invariant by setting
ob_tidto zero when the refcount fields aren't merged. Typically, this isn't a problem because:subtype_dealloc(e.g., for a finalizer), we usePy_SET_REFCNT, which will mark the fields as merged, restoring the invariantHowever, if resurrection is done slightly differently, such as by
Py_INCREF(), then things can break in very strange ways:ob_tidfrom the allocator (because it's not merged), butob_ref_localis still zero. The nextPy_DECREFthen leads to a "negative refcount" error.Summary
We should maintain the invariant that
ob_tid == 0<=>_Py_REF_IS_MERGED()and check it with assertions when possible.cpython/Objects/object.c
Lines 373 to 398 in 8303d32
Originally reported by @albanD
Linked PRs
ob_tidto zero in fast-path dealloc #121799ob_tidto zero in fast-path dealloc (GH-121799) #121821Footnotes
There are a few places where we deliberately re-use
ob_tidfor other purposes, such as the trashcan mechanism and during GC, but these objects are not visible to other parts of the program. ↩The text was updated successfully, but these errors were encountered: