gh-112182: Replace StopIteration with RuntimeError for future#113220
Conversation
When an `StopIteration` raises into `asyncio.Future`, this will cause a thread to hang. This commit address this by not raising an exception and silently transforming the `StopIteration` with a `RuntimeError`, which the caller can reconstruct from `fut.exception().__cause__`
gvanrossum
left a comment
There was a problem hiding this comment.
Hey @ordinary-jamie, your Python's pretty good, your C could use a bit more care with reference counts and such. I think I caught everything. (BTW did you see the similar code in intrinsics.c in stopiteration_error()? It could serve as a useful comparison.)
@NewUserHa -- do you have any feedback on this PR? Do you have a version of your own that's further developed?
Thanks for the detailed review @gvanrossum! Yes, sorry about my C, got a bit too eager to try and contribute before finishing my studies with CPython/C. I'll address your comments asap and let you know :)
👀 thanks! |
… asyncio-future-stopiteration
serhiy-storchaka
left a comment
There was a problem hiding this comment.
Agree with all of Guido's comments.
…-future-stopiteration
gvanrossum
left a comment
There was a problem hiding this comment.
I have a nit for the blurb, otherwise LGTM. But let's make sure @serhiy-storchaka also agrees (I might have missed something).
|
Happy holidays @gvanrossum @serhiy-storchaka -- sorry for the slow response on this, just came back from leave. Side question: should |
I have no idea. I don't even know where that is generated -- I don't see it in the .rst file. |
I believe its set here: Doc/data/refcounts.dat edit: I can look into it and raise a separate issue ticket |
…-future-stopiteration
|
Sorry @gvanrossum -- missed out a fix in the Python stub |
gvanrossum
left a comment
There was a problem hiding this comment.
LG -- waiting for @serhiy-storchaka
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
| assert(PyExceptionInstance_Check(err)); | ||
|
|
||
| PyException_SetCause(err, Py_NewRef(exc_val)); | ||
| PyException_SetContext(err, Py_NewRef(exc_val)); |
There was a problem hiding this comment.
You need set this to exc_val.__context__ not exc_val itself.
There was a problem hiding this comment.
This was taken from the similar, existing code in intrinsics.c that also handles StopIteration for asyncio:
Line 181 in 36aab34
Would this need updating as well?
…-future-stopiteration
|
Sorry about the mistakes @serhiy-storchaka and @kumaraditya303 I've addressed the comments, except for one RE: setting the context. The current code copies over the logic from |
serhiy-storchaka
left a comment
There was a problem hiding this comment.
I was surprised that the Python code set exception.__context__. Was there any reason for this or it was a typo? There are no tests for this.
Besides this minor question, LGTM.
typo 😳 sorry about that! |
@ordinary-jamie I lost track of the state of this PR. Did you fix that typo yet? |
Yes! The typo is already fixed (sorry for the comment spam) |
|
Thanks @ordinary-jamie ! We'll get the other thing sorted too. Happy to work with you more. |
…ython#113220) When an `StopIteration` raises into `asyncio.Future`, this will cause a thread to hang. This commit address this by not raising an exception and silently transforming the `StopIteration` with a `RuntimeError`, which the caller can reconstruct from `fut.exception().__cause__`
…ython#113220) When an `StopIteration` raises into `asyncio.Future`, this will cause a thread to hang. This commit address this by not raising an exception and silently transforming the `StopIteration` with a `RuntimeError`, which the caller can reconstruct from `fut.exception().__cause__`
|
What version was this fixed in? |
|
It was not backported to 3.12. Taking into account that the current behavior is wrong, and it is very unlikely that any code depends on it (how can you depend on hanging code?), I think that it is reasonable to backport this change (if there was no other changes that can prevent this). |
|
Thanks @ordinary-jamie for the PR, and @gvanrossum for merging it 🌮🎉.. I'm working now to backport this PR to: 3.12. |
…ythonGH-113220) When an `StopIteration` raises into `asyncio.Future`, this will cause a thread to hang. This commit address this by not raising an exception and silently transforming the `StopIteration` with a `RuntimeError`, which the caller can reconstruct from `fut.exception().__cause__` (cherry picked from commit 4826d52) Co-authored-by: Jamie Phan <jamie@ordinarylab.dev>
|
GH-123033 is a backport of this pull request to the 3.12 branch. |
…H-113220) (GH-123033) When an `StopIteration` raises into `asyncio.Future`, this will cause a thread to hang. This commit address this by not raising an exception and silently transforming the `StopIteration` with a `RuntimeError`, which the caller can reconstruct from `fut.exception().__cause__` (cherry picked from commit 4826d52) Co-authored-by: Jamie Phan <jamie@ordinarylab.dev>
…ython#113220) When an `StopIteration` raises into `asyncio.Future`, this will cause a thread to hang. This commit address this by not raising an exception and silently transforming the `StopIteration` with a `RuntimeError`, which the caller can reconstruct from `fut.exception().__cause__`
Issue: #112182
When an
StopIterationraises intoasyncio.Future, this will cause a thread to hang. This commit address this by not raising an exception and silently transforming theStopIterationwith aRuntimeError, which the caller can reconstruct fromfut.exception().__cause__StopIterationin a generator in a thread hanging on asyncio #112182