summaryrefslogtreecommitdiffstats
path: root/Include
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2012-12-08 20:17:03 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2012-12-08 20:17:03 (GMT)
commitf93ed3fa67260fa0023a1360a37ab7e320550455 (patch)
treec99dddd7b3460544a57415d8f53ecbd097b975ec /Include
parenta7129d38edb1a9db17fbd8b40d9eaf135a857f8e (diff)
parent62a0d6ea402d18f528629c6e84ed6f46e7c0912a (diff)
downloadcpython-f93ed3fa67260fa0023a1360a37ab7e320550455.zip
cpython-f93ed3fa67260fa0023a1360a37ab7e320550455.tar.gz
cpython-f93ed3fa67260fa0023a1360a37ab7e320550455.tar.bz2
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.
Diffstat (limited to 'Include')
-rw-r--r--Include/weakrefobject.h12
1 files changed, 11 insertions, 1 deletions
diff --git a/Include/weakrefobject.h b/Include/weakrefobject.h
index 7258387..537e7eb 100644
--- a/Include/weakrefobject.h
+++ b/Include/weakrefobject.h
@@ -70,7 +70,17 @@ PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head);
PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self);
#endif
-#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