The Wayback Machine - https://web.archive.org/web/20240112011629/https://github.com/python/cpython/pull/113754
Skip to content
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

Merged
merged 5 commits into from Jan 10, 2024

Conversation

colesbury
Copy link
Contributor

@colesbury colesbury commented Jan 5, 2024

The PyAsyncGenASend may have their "finalized" bit set from previous use.

@colesbury
Copy link
Contributor Author

@gvanrossum - this leads to a warning "RuntimeWarning: coroutine method 'asend' of 'AsyncGenTest.test_async_gen_exception_12..gen' was never awaited" in test_async_gen_exception_12. I can't figure out how to avoid or suppress the warning in this test case. Do you know how to deal with it?

def test_async_gen_exception_12(self):
async def gen():
await anext(me)
yield 123
me = gen()
ai = me.__aiter__()
an = ai.__anext__()
with self.assertRaisesRegex(RuntimeError,
r'anext\(\): asynchronous generator is already running'):
an.__next__()

Comment on lines +123 to 127
static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) {
PyGC_Head *gc = _Py_AS_GC(op);
gc->_gc_prev &= ~_PyGC_PREV_MASK_FINALIZED;
}

Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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?

@gvanrossum
Copy link
Member

Cool. Undraft it and I'll merge it.

@gvanrossum
Copy link
Member

Whoops didn't see the last msg. Will look at it later.

@gvanrossum
Copy link
Member

I am totally baffled by this as well. That test always seems to give that warning:

test_async_gen_exception_12 (test.test_asyncgen.AsyncGenTest.test_async_gen_exception_12) ... /Users/guido/cpython/Lib/test/test_asyncgen.py:382: RuntimeWarning: coroutine method 'asend' of 'AsyncGenTest.test_async_gen_exception_12.<locals>.gen' was never awaited
  await anext(me)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
ok

But I have no idea why in the CI for your PR it complains about a partial tracemalloc module -- it doesn't do that when I test it locally.

The only other clue I have is that if I run it locally and add --fast-ci to the test module's argument list it doesn't print that warning. The logic that leads to this result however eludes me. :-(

@gvanrossum
Copy link
Member

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 (AttributeError: partially initialized module 'tracemalloc' from '/home/runner/work/cpython/cpython-ro-srcdir/Lib/tracemalloc.py' has no attribute 'is_tracing' (most likely due to a circular import)). I wonder if the tracemalloc thing is unrelated and turns various warnings into errors.

@gvanrossum
Copy link
Member

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 (AttributeError: partially initialized module 'tracemalloc' from '/home/runner/work/cpython/cpython-ro-srcdir/Lib/tracemalloc.py' has no attribute 'is_tracing' (most likely due to a circular import)). I wonder if the tracemalloc thing is unrelated and turns various warnings into errors.

That problem is now fixed by GH-113813. I'll update the branch and maybe the tests will pass.

@gvanrossum
Copy link
Member

Hah! This time all checks are passing.

@colesbury colesbury marked this pull request as ready for review January 10, 2024 14:36
@colesbury
Copy link
Contributor Author

Thanks Guido!

Objects/genobject.c Outdated Show resolved Hide resolved
@@ -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);
Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Member

@gvanrossum gvanrossum left a 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.

@gvanrossum gvanrossum merged commit 73ae202 into python:main Jan 10, 2024
32 checks passed
@colesbury colesbury deleted the gh-113753-asend branch January 10, 2024 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.13 new features, bugs and security fixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants