Skip to content

Conversation

@dpgeorge
Copy link
Member

When a tasks raises an exception which is uncaught, and no other task await's on that task, then an error message is printed (or a user function called) via a call to Loop.call_exception_handler. In CPython this call is made when the Task object is freed (eg via reference counting) because it's at that point that it is known that the exception that was raised will never be handled.

MicroPython does not have reference counting and the current behaviour is to deal with uncaught exceptions as early as possible, ie as soon as they terminate the task. But this can be undesirable because in certain cases a task can start and raise an exception immediately (before any await is executed in that task's coro) and before any other task gets a chance to await on it to catch the exception.

This commit changes the behaviour so that tasks which end due to an uncaught exception are scheduled one more time for execution, and if they are not await'ed on by the next scheduling loop, then the exception handler is called (eg the exception is printed out).

As part of this, task.coro==None is no longer the way to detect if a task is finished, so the Task.done() method is added.

IMO this fix is useful in its own right, but it's also a precursor to fix wait_for() cancellation in a clean way (see also #5931).

@dpgeorge dpgeorge added the extmod Relates to extmod/ directory in source label Nov 30, 2020
@dpgeorge dpgeorge force-pushed the extmod-uasyncio-delayed-detached-tasks branch from 9d35ee6 to e405936 Compare December 1, 2020 00:59
When a tasks raises an exception which is uncaught, and no other task
await's on that task, then an error message is printed (or a user function
called) via a call to Loop.call_exception_handler.  In CPython this call is
made when the Task object is freed (eg via reference counting) because it's
at that point that it is known that the exception that was raised will
never be handled.

MicroPython does not have reference counting and the current behaviour is
to deal with uncaught exceptions as early as possible, ie as soon as they
terminate the task.  But this can be undesirable because in certain cases
a task can start and raise an exception immediately (before any await is
executed in that task's coro) and before any other task gets a chance to
await on it to catch the exception.

This commit changes the behaviour so that tasks which end due to an
uncaught exception are scheduled one more time for execution, and if they
are not await'ed on by the next scheduling loop, then the exception handler
is called (eg the exception is printed out).

Signed-off-by: Damien George <[email protected]>
This is added because task.coro==None is no longer the way to detect if a
task is finished.  Providing a (CPython compatible) function for this
allows the implementation to be abstracted away.

Signed-off-by: Damien George <[email protected]>
@dpgeorge dpgeorge force-pushed the extmod-uasyncio-delayed-detached-tasks branch from e405936 to 309dfe3 Compare December 2, 2020 01:08
@dpgeorge dpgeorge merged commit 309dfe3 into micropython:master Dec 2, 2020
@dpgeorge dpgeorge deleted the extmod-uasyncio-delayed-detached-tasks branch December 2, 2020 01:31
tannewt added a commit to tannewt/circuitpython that referenced this pull request Jul 28, 2022
Add board.LED (alias of board.LED_R part of RGB)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extmod Relates to extmod/ directory in source

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant