From 098eb3d445c6bef738b3b318075d27d7e2a2c30f Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Fri, 5 Jan 2024 22:12:26 -0500 Subject: [PATCH] gh-113750: Fix object resurrection in free-threaded builds (gh-113751) gh-113750: Fix object resurrection on free-threaded builds This avoids the undesired re-initializing of fields like `ob_gc_bits`, `ob_mutex`, and `ob_tid` when an object is resurrected due to its finalizer being called. This change has no effect on the default (with GIL) build. --- Include/cpython/object.h | 1 + Modules/_testcapi/gc.c | 4 +--- Objects/object.c | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Include/cpython/object.h b/Include/cpython/object.h index d6482f4bc689a1b..c93931634fee051 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -4,6 +4,7 @@ PyAPI_FUNC(void) _Py_NewReference(PyObject *op); PyAPI_FUNC(void) _Py_NewReferenceNoTotal(PyObject *op); +PyAPI_FUNC(void) _Py_ResurrectReference(PyObject *op); #ifdef Py_REF_DEBUG /* These are useful as debugging aids when chasing down refleaks. */ diff --git a/Modules/_testcapi/gc.c b/Modules/_testcapi/gc.c index 829200ad12cd3ce..f4feaaafbdc6cc9 100644 --- a/Modules/_testcapi/gc.c +++ b/Modules/_testcapi/gc.c @@ -126,9 +126,7 @@ slot_tp_del(PyObject *self) * never happened. */ { - Py_ssize_t refcnt = Py_REFCNT(self); - _Py_NewReferenceNoTotal(self); - Py_SET_REFCNT(self, refcnt); + _Py_ResurrectReference(self); } assert(!PyType_IS_GC(Py_TYPE(self)) || PyObject_GC_IsTracked(self)); } diff --git a/Objects/object.c b/Objects/object.c index d970a26756173bd..587c5528c01345b 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -509,9 +509,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self) /* tp_finalize resurrected it! Make it look like the original Py_DECREF * never happened. */ - Py_ssize_t refcnt = Py_REFCNT(self); - _Py_NewReferenceNoTotal(self); - Py_SET_REFCNT(self, refcnt); + _Py_ResurrectReference(self); _PyObject_ASSERT(self, (!_PyType_IS_GC(Py_TYPE(self)) @@ -2389,6 +2387,17 @@ _Py_NewReferenceNoTotal(PyObject *op) new_reference(op); } +void +_Py_ResurrectReference(PyObject *op) +{ + if (_PyRuntime.tracemalloc.config.tracing) { + _PyTraceMalloc_NewReference(op); + } +#ifdef Py_TRACE_REFS + _Py_AddToAllObjects(op); +#endif +} + #ifdef Py_TRACE_REFS void