GH-117881: fix athrow().throw()/asend().throw() concurrent access#117882
GH-117881: fix athrow().throw()/asend().throw() concurrent access#117882encukou merged 10 commits intopython:mainfrom
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
|
|
||
| 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.
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.
probably could do with a test
There was a problem hiding this comment.
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! |
encukou
left a comment
There was a problem hiding this comment.
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. 👍 |
| g = gen() | ||
| with self.assertRaises(MyException): | ||
| g.aclose().throw(MyException) | ||
| del g |
There was a problem hiding this comment.
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.