diff options
author | Victor Stinner <vstinner@python.org> | 2023-06-20 06:52:40 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-20 06:52:40 (GMT) |
commit | cb388c9a85a8dd6817ea7d969f53657002df6272 (patch) | |
tree | 9f7307d840a33aaae2d28643b399bf825a800d5d /Include | |
parent | 03f1a132eeb34c738812161947ef171b21d58c25 (diff) | |
download | cpython-cb388c9a85a8dd6817ea7d969f53657002df6272.zip cpython-cb388c9a85a8dd6817ea7d969f53657002df6272.tar.gz cpython-cb388c9a85a8dd6817ea7d969f53657002df6272.tar.bz2 |
gh-105927: Add _PyWeakref_GET_REF() internal function (#105929)
Add new pycore_weakref.h internal header file.
Diffstat (limited to 'Include')
-rw-r--r-- | Include/internal/pycore_weakref.h | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/Include/internal/pycore_weakref.h b/Include/internal/pycore_weakref.h new file mode 100644 index 0000000..4e2b979 --- /dev/null +++ b/Include/internal/pycore_weakref.h @@ -0,0 +1,40 @@ +#ifndef Py_INTERNAL_WEAKREF_H +#define Py_INTERNAL_WEAKREF_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +static inline PyObject* _PyWeakref_GET_REF(PyObject *ref_obj) { + assert(PyWeakref_Check(ref_obj)); + PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj); + PyObject *obj = ref->wr_object; + + if (obj == Py_None) { + // clear_weakref() was called + return NULL; + } + + // 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 gh-60806. + Py_ssize_t refcnt = Py_REFCNT(obj); + if (refcnt == 0) { + return NULL; + } + + assert(refcnt > 0); + return Py_NewRef(obj); +} + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_WEAKREF_H */ + |