Bug report
There is a subtle possible race condition in _Py_ExplicitMergeRefcount: we set ob_ref_local and ob_tid to zero after writing the merged refcount to ob_ref_shared.
That's not safe, because another thread might possibly deallocate the object after we merged refcount. For example:
- Assume that the merged refcount is
1
- Some other thread calls
Py_DECREF() and immediately frees the object
- We write zero to
ob_ref_local and ob_tid -- BUG!
|
} while (!_Py_atomic_compare_exchange_ssize(&op->ob_ref_shared, |
|
&shared, new_shared)); |
|
|
|
#ifdef Py_REF_DEBUG |
|
_Py_AddRefTotal(_PyThreadState_GET(), extra); |
|
#endif |
|
|
|
_Py_atomic_store_uint32_relaxed(&op->ob_ref_local, 0); |
|
_Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0); |
|
return refcnt; |
Linked PRs
Bug report
There is a subtle possible race condition in
_Py_ExplicitMergeRefcount: we setob_ref_localandob_tidto zero after writing the merged refcount toob_ref_shared.That's not safe, because another thread might possibly deallocate the object after we merged refcount. For example:
1Py_DECREF()and immediately frees the objectob_ref_localandob_tid-- BUG!cpython/Objects/object.c
Lines 413 to 422 in 41c1cef
Linked PRs
_Py_ExplicitMergeRefcount#120000_Py_ExplicitMergeRefcount(GH-120000) #120073