-
-
Notifications
You must be signed in to change notification settings - Fork 32k
GH-117881: fix athrow().throw()/asend().throw() concurrent access #117882
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-117881: fix athrow().throw()/asend().throw() concurrent access #117882
Conversation
Misc/NEWS.d/next/Core and Builtins/2024-04-15-07-37-09.gh-issue-117881.07H0wI.rst
Outdated
Show resolved
Hide resolved
…e-117881.07H0wI.rst
@@ -1771,6 +1771,7 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg) | |||
|
|||
if (o->ags_state == AWAITABLE_STATE_INIT) { | |||
if (o->ags_gen->ag_running_async) { | |||
o->ags_state = AWAITABLE_STATE_CLOSED; |
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 was set in async_gen_athrow_send
but forgotten in async_gen_asend_send
, and also results in an unawaited coroutine warning
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.
Lines 2098 to 2113 in 8418dcc
if (o->agt_state == AWAITABLE_STATE_INIT) { | |
if (o->agt_gen->ag_running_async) { | |
o->agt_state = AWAITABLE_STATE_CLOSED; | |
if (o->agt_args == NULL) { | |
PyErr_SetString( | |
PyExc_RuntimeError, | |
"aclose(): asynchronous generator is already running"); | |
} | |
else { | |
PyErr_SetString( | |
PyExc_RuntimeError, | |
"athrow(): asynchronous generator is already running"); | |
} | |
return NULL; | |
} | |
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.
probably could do with a test
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.
test added in 1220aee
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.
As in #117851: I'm not an expert in this area.
It makes sense to start the generator in send/throw.
What I don't get is the purpose of all the synchronization between ags_state
and ags_gen->ag_running_async
/ags_gen->ag_closed
. What's the difference between what they represent? Should they go out of sync at some point?
I think it's possible for them to go out of sync, but I think I have a fix for that here #117906 |
Is it a bug if they go out of sync? |
you can have multiple of each |
this is where import types
import itertools
@types.coroutine
def _async_yield(v):
return (yield v)
async def agenfn():
for i in itertools.count():
await _async_yield(i)
return
yield
agen = agenfn()
gen = agen.__anext__()
print(f"{gen.send(None)=}")
print(f"{agen.ag_running=}")
gen.close() # uh-oh, gen->ags_state is CLOSED
print(f"{agen.ag_running=}") # but the async generator is still running
agen.aclose().send(None) # and it's broken so we can't aclose it |
Ah! Got it, thank you! |
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.
The PR looks good to me. But, it would be great to have a more comprehensive way to find issues like this. I commented on the issue.
This comment was marked as resolved.
This comment was marked as resolved.
No need for me to review, I was only testing the bot earlier. 👍 |
@@ -1809,9 +1957,56 @@ class MyException(Exception): | |||
g = gen() | |||
with self.assertRaises(MyException): | |||
g.aclose().throw(MyException) | |||
del g |
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.
driveby: oops this wasn't running
@encukou is there anything else I need to do on this? I'd like to start looking at fixing athrow().close() and asend().close() next which builds on this work |
No, sorry for the delay! |
Thanks @graingert for the PR, and @encukou for merging it 🌮🎉.. I'm working now to backport this PR to: 3.12. |
Sorry, @graingert and @encukou, I could not cleanly backport this to
|
GH-118458 is a backport of this pull request to the 3.12 branch. |
Uh oh!
There was an error while loading. Please reload this page.