Skip to content

Commit 51c6625

Browse files
committed
Fix refleak tests.
Revert back to Py_DECREF() instead of the Py_SET_REFCNT(dict, 0) and fix check that this thread owns the only reference to the dict. That ensures that the final Py_DECREF call immediately frees the dict instead of possibly enqueuing it to be merged.
1 parent 459638f commit 51c6625

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

Objects/dictobject.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5989,6 +5989,18 @@ _PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values)
59895989
return make_dict_from_instance_attributes(interp, keys, values);
59905990
}
59915991

5992+
static bool
5993+
has_unique_reference(PyObject *op)
5994+
{
5995+
#ifdef Py_GIL_DISABLED
5996+
return (_Py_IsOwnedByCurrentThread(op) &&
5997+
op->ob_ref_local == 1 &&
5998+
_Py_atomic_load_ssize_relaxed(&op->ob_ref_shared) == 0);
5999+
#else
6000+
return Py_REFCNT(op) == 1;
6001+
#endif
6002+
}
6003+
59926004
// Return true if the dict was dematerialized, false otherwise.
59936005
bool
59946006
_PyObject_MakeInstanceAttributesFromDict(PyObject *obj, PyDictOrValues *dorv)
@@ -6005,7 +6017,9 @@ _PyObject_MakeInstanceAttributesFromDict(PyObject *obj, PyDictOrValues *dorv)
60056017
return false;
60066018
}
60076019
assert(_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_HEAPTYPE));
6008-
if (dict->ma_keys != CACHED_KEYS(Py_TYPE(obj)) || Py_REFCNT(dict) != 1) {
6020+
if (dict->ma_keys != CACHED_KEYS(Py_TYPE(obj)) ||
6021+
!has_unique_reference((PyObject *)dict))
6022+
{
60096023
return false;
60106024
}
60116025
assert(dict->ma_values);
@@ -6016,8 +6030,7 @@ _PyObject_MakeInstanceAttributesFromDict(PyObject *obj, PyDictOrValues *dorv)
60166030
// Don't try this at home, kids:
60176031
dict->ma_keys = NULL;
60186032
dict->ma_values = NULL;
6019-
Py_SET_REFCNT(dict, 0);
6020-
_Py_Dealloc((PyObject *)dict);
6033+
Py_DECREF(dict);
60216034
return true;
60226035
}
60236036

Python/gc_free_threading.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ merge_queued_objects(_PyThreadStateImpl *tstate, struct collection_state *state)
300300
// non-GC objects here. Add one to the refcount so that we can
301301
// decref and deallocate the object once we start the world again.
302302
op->ob_ref_shared += (1 << _Py_REF_SHARED_SHIFT);
303+
#ifdef Py_REF_DEBUG
304+
_Py_IncRefTotal(_PyInterpreterState_GET());
305+
#endif
303306
worklist_push(&state->objs_to_decref, op);
304307
}
305308
}

0 commit comments

Comments
 (0)