diff --git a/Include/weakrefobject.h b/Include/weakrefobject.h index 17051568f3..3133cab1e7 100644 --- a/Include/weakrefobject.h +++ b/Include/weakrefobject.h @@ -25,6 +25,10 @@ struct _PyWeakReference { /* A callable to invoke when wr_object dies, or NULL if none. */ PyObject *wr_callback; + /* True if the weak reference was found to be trash by GC, wr_callback + * will not be called in that case. */ + int wr_trash; + /* A cache for wr_object's hash code. As usual for hashes, this is -1 * if the hash code isn't known yet. */ diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 0cf00e8396..9d85a5be83 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -676,6 +690,10 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) op = FROM_GC(gc); next = GC_NEXT(gc); + if (PyWeakref_Check(op)) { + ((PyWeakReference *)op)->wr_trash = 1; + } + if (! PyType_SUPPORTS_WEAKREFS(Py_TYPE(op))) continue; diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 8b8e71031a..7914ae50a1 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -23,6 +23,7 @@ static void init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback) { self->hash = -1; + self->wr_trash = 0; self->wr_object = ob; self->wr_prev = NULL; self->wr_next = NULL; @@ -874,6 +875,9 @@ PyWeakref_GetObject(PyObject *ref) static void handle_callback(PyWeakReference *ref, PyObject *callback) { + if (ref->wr_trash) { + return; /* weakref is trash, suppress callback */ + } PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL); if (cbresult == NULL)