-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
extmod/asyncio: Support gather of tasks that finish early. #13474
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
extmod/asyncio: Support gather of tasks that finish early. #13474
Conversation
@iabdalkader FYI |
Code size report:
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #13474 +/- ##
=======================================
Coverage 98.36% 98.36%
=======================================
Files 159 159
Lines 21088 21088
=======================================
Hits 20743 20743
Misses 345 345 ☔ View full report in Codecov by Sentry. |
cc5d4e8
to
49e78d4
Compare
I found and fixed an edge case where all sub-tasks finish early. |
Adds support to asyncio.gather() for the case that one or more (or all) sub-tasks finish and/or raise an exception before the gather starts. Signed-off-by: Damien George <damien@micropython.org>
49e78d4
to
2ecbad4
Compare
@dpgeorge Thank you very much for this much needed fix 🙏🏼 I had a chance to test this today, and even though it fixes the main issue for me (
Also it seems the task exception is now saved, and I can retrieve it after # Save exception raised by the coro for later use.
t.data = exc |
Yes that's expected. Because of the difference in GC vs reference counting, MicroPython and CPython necessarily differ in when exceptions like this are printed. You can see in the test in this PR that those messages are sent to a dummy
You should also be able to retrieve the exception from the return value of the
If the return value of |
This is how I catch the task exception: task_except = None
try:
await asyncio.gather(*self.tasks.values(), return_exceptions=False)
except Exception as e:
task_except = e
# Then later
for name in list(self.tasks):
task = self.tasks[name]
try:
if task.done():
if isinstance(task_except, DoneException)
break # Break after the first task is removed. This counts on tasks being processed by |
Adds support to asyncio.gather() for the following cases: