diff Include/weakrefobject.h @ 80762:7e771f0363e2 2.7

Issue #16602: When a weakref's target was part of a long deallocation chain, the object could remain reachable through its weakref even though its refcount had dropped to zero. Thanks to Eugene Toder for diagnosing and reporting the issue.
author Antoine Pitrou <solipsis@pitrou.net>
date Sat, 08 Dec 2012 21:15:26 +0100
parents 86a2679dca46
children 39e5ab118602
line wrap: on
line diff
--- a/Include/weakrefobject.h	Sat Dec 08 18:01:27 2012 +0200
+++ b/Include/weakrefobject.h	Sat Dec 08 21:15:26 2012 +0100
@@ -66,7 +66,17 @@
 
 PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self);
 
-#define PyWeakref_GET_OBJECT(ref) (((PyWeakReference *)(ref))->wr_object)
+/* Explanation for the Py_REFCNT() check: when a weakref's target is part
+   of a long chain of deallocations which triggers the trashcan mechanism,
+   clearing the weakrefs can be delayed long after the target's refcount
+   has dropped to zero.  In the meantime, code accessing the weakref will
+   be able to "see" the target object even though it is supposed to be
+   unreachable.  See issue #16602. */
+
+#define PyWeakref_GET_OBJECT(ref)                           \
+    (Py_REFCNT(((PyWeakReference *)(ref))->wr_object) > 0   \
+     ? ((PyWeakReference *)(ref))->wr_object                \
+     : Py_None)
 
 
 #ifdef __cplusplus