]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-113753: Clear finalized bit when putting PyAsyncGenASend back into free list ...
authorSam Gross <colesbury@gmail.com>
Wed, 10 Jan 2024 18:18:38 +0000 (13:18 -0500)
committerGitHub <noreply@github.com>
Wed, 10 Jan 2024 18:18:38 +0000 (10:18 -0800)
Include/internal/pycore_gc.h
Lib/test/test_asyncgen.py
Misc/NEWS.d/next/Core and Builtins/2024-01-05-21-28-48.gh-issue-113753.2HNiuq.rst [new file with mode: 0644]
Objects/genobject.c

index 2a0730eebb8db75eab51c879fae01c3ff7f0993c..753763a5a502207d0ce36ff9c5d474ab7a61afa7 100644 (file)
@@ -122,6 +122,10 @@ static inline void _PyGC_SET_FINALIZED(PyObject *op) {
     PyGC_Head *gc = _Py_AS_GC(op);
     _PyGCHead_SET_FINALIZED(gc);
 }
+static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) {
+    PyGC_Head *gc = _Py_AS_GC(op);
+    gc->_gc_prev &= ~_PyGC_PREV_MASK_FINALIZED;
+}
 
 
 /* GC runtime state */
index a49630112af5106d37ad57bf872c7def1e55a82e..7fa0a85100a581baba4a7ec7fa11764d3e779d9a 100644 (file)
@@ -1701,6 +1701,14 @@ class TestUnawaitedWarnings(unittest.TestCase):
         async def gen():
             yield 1
 
+        # gh-113753: asend objects allocated from a free-list should warn.
+        # Ensure there is a finalized 'asend' object ready to be reused.
+        try:
+            g = gen()
+            g.asend(None).send(None)
+        except StopIteration:
+            pass
+
         msg = f"coroutine method 'asend' of '{gen.__qualname__}' was never awaited"
         with self.assertWarnsRegex(RuntimeWarning, msg):
             g = gen()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-05-21-28-48.gh-issue-113753.2HNiuq.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-05-21-28-48.gh-issue-113753.2HNiuq.rst
new file mode 100644 (file)
index 0000000..32cf2cb
--- /dev/null
@@ -0,0 +1,2 @@
+Fix an issue where the finalizer of ``PyAsyncGenASend`` objects might not be
+called if they were allocated from a free list.
index 9614713883741c390208733dc73d68a2dd936628..f03919c75d70a591e80579629cbc18bc3e0b99a9 100644 (file)
@@ -6,6 +6,7 @@
 #include "pycore_call.h"          // _PyObject_CallNoArgs()
 #include "pycore_ceval.h"         // _PyEval_EvalFrame()
 #include "pycore_frame.h"         // _PyInterpreterFrame
+#include "pycore_gc.h"            // _PyGC_CLEAR_FINALIZED()
 #include "pycore_genobject.h"     // struct _Py_async_gen_state
 #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
 #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
@@ -1739,6 +1740,7 @@ async_gen_asend_dealloc(PyAsyncGenASend *o)
 #endif
     if (state->asend_numfree < _PyAsyncGen_MAXFREELIST) {
         assert(PyAsyncGenASend_CheckExact(o));
+        _PyGC_CLEAR_FINALIZED((PyObject *)o);
         state->asend_freelist[state->asend_numfree++] = o;
     }
     else