New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-113753: Clear finalized bit when allocating PyAsyncGenASend from free-list #113754
Conversation
@gvanrossum - this leads to a warning "RuntimeWarning: coroutine method 'asend' of 'AsyncGenTest.test_async_gen_exception_12..gen' was never awaited" in cpython/Lib/test/test_asyncgen.py Lines 380 to 391 in 99854ce
|
static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) { | ||
PyGC_Head *gc = _Py_AS_GC(op); | ||
gc->_gc_prev &= ~_PyGC_PREV_MASK_FINALIZED; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is expedient, but why not follow the patter used by FINALIZED
and SET_FINALIZED
that have a helper that skips the _Py_AS_GC()
call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think those functions (_PyGCHead_SET_FINALIZED
and _PyGCHead_FINALIZED
) are likely to be removed in other PRs as I work on making the GC thread-safe in free-threaded builds. It's easier to support both builds when the functions take PyObject*
instead of PyGC_Head*
because the free-threaded builds will store the GC flags on the PyObject*
itself (and eventually may not even have a PyGC_Head
prefix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also OK with following the existing pattern for now and dealing with any potential removal later if you prefer.
Mostly I'm stuck on the warning generated in test_async_gen_exception_12
. I don't know how to deal with it. Maybe @kumaraditya303 has suggestions?
Cool. Undraft it and I'll merge it. |
Whoops didn't see the last msg. Will look at it later. |
I am totally baffled by this as well. That test always seems to give that warning:
But I have no idea why in the CI for your PR it complains about a partial The only other clue I have is that if I run it locally and add |
Interesting, a similar error occurs in an unrelated PR (gh-11166), which also touches async generators. It's a different test, but the same phenomenon ( |
That problem is now fixed by GH-113813. I'll update the branch and maybe the tests will pass. |
Hah! This time all checks are passing. |
Thanks Guido! |
Objects/genobject.c
Outdated
@@ -1951,6 +1952,7 @@ async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o) | |||
#endif | |||
if (state->value_numfree < _PyAsyncGen_MAXFREELIST) { | |||
assert(_PyAsyncGenWrappedValue_CheckExact(o)); | |||
_PyGC_CLEAR_FINALIZED((PyObject *)o); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh clicked wrong button, you need to call this in async_gen_asend_dealloc on asend_freelist
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. I fixed the location of _PyGC_CLEAR_FINALIZED
and updated test_asend
in test_asyncgen.py
so that it would catch this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess that test will fail if MAXFREELIST is zero. Fine.
I'll merge now.
The
PyAsyncGenASend
may have their "finalized" bit set from previous use.PyAsyncGenASend
objects allocated from freelists may not have their finalizers called #113753