← index #15941Issue #6893
Related · high · value 0.088
QUERY · ISSUE

Unexpected asyncio code exec between exc in task and call of global asyncio crash handler

openby mirkoopened 2024-10-01updated 2024-10-01
bug

Port, board and/or hardware

unix and esp32

MicroPython version

MicroPython v1.23.0-preview.436.gc8021842c

Reproduction

import asyncio

class Loop():
    async def run(self):
        print("---", self.__class__.__name__, "---")

    async def run_forever(self):
        while True:
            try:
                await self.run()
                await asyncio.sleep(0.1)
            except Exception as exc:
                print("EEE", exc)
                raise

class Loop_1(Loop):
    pass

class Loop_2(Loop):
    async def run(self):
        await super().run()
        raise Exception("MOEP!")

class Loop_3(Loop):
    pass

def async_crash_hdlr(loop, ctx):
    # called when unhandled exceptions thrown in asyncio tasks.
    # this function is called from within a task running in the mainloop.
    print("Global asyncio exception handler called -> FREEZE")
    while True:
        pass

async def main():
    asyncio.get_event_loop().set_exception_handler(async_crash_hdlr)
    loop1 = Loop_1()
    loop2 = Loop_2()
    loop3 = Loop_3()
    print("Starting loop1")
    asyncio.create_task(loop1.run_forever())
    print("Starting loop2")
    asyncio.create_task(loop2.run_forever())
    print("Starting loop3")
    asyncio.create_task(loop3.run_forever())
    while True:
        print("--- MAINLOOP ---")
        await asyncio.sleep(1)

print("Entering main program")
asyncio.run(main())

Expected behaviour

Expected the defined global asyncio exception handler (async_crash_hdlr) being called immediately.

Expected output from above code (as per CPython3):

Entering main program
Starting loop1
Starting loop2
Starting loop3
--- MAINLOOP ---
--- Loop_1 ---
--- Loop_2 ---
EEE MOEP!
Global asyncio exception handler called -> FREEZE

Observed behaviour

Unexpected to me, between the exception being raised in Loop2 and async_crash_hdlr() being called, there is still asyncio code being executed, despite no fruther await or alike in between.
In this very case (code from) Loop3 is being run:

Entering main program
Starting loop1
Starting loop2
Starting loop3
--- MAINLOOP ---
--- Loop_1 ---
--- Loop_2 ---
EEE MOEP!
--- Loop_3 --- # <<<<<-------------------------
Global asyncio exception handler called -> FREEZE

Additional Information

No, I've provided everything above.

Code of Conduct

Yes, I agree

CANDIDATE · ISSUE

uasyncio Event unexpected behaviour with only one task

closedby peterhinchopened 2021-02-13updated 2024-09-13

[EDIT] Apologies, @kevinkk525 has pointed out that this is a duplcate of https://github.com/micropython/micropython/issues/5843

This prints "start" then runs to completion where I would expect it to wait indefinitely on the Event:

import uasyncio as asyncio

evt = asyncio.Event()

async def main_loop():
    while True:
        print("start")
        await evt.wait()
        await asyncio.sleep(1)
        print("Got event")

asyncio.run(main_loop())

If an additional task is running the main_loop task behaves as expected, waiting forever:

import uasyncio as asyncio

evt = asyncio.Event()

async def main_loop():
    while True:
        print("start")
        await evt.wait()
        await asyncio.sleep(1)
        print("Got event")

async def main():
    asyncio.create_task(main_loop())
    while True:
        await asyncio.sleep(1)

asyncio.run(main())

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied