Skip to content

Incorrect uasyncio behaviour: tasks are not correctly terminated #7471

Open

Description

@mattytrentini

(First reported on the forum)

The following snippet:

try:
    import uasyncio as asyncio
except ImportError:
    import asyncio

async def count():
    i = 0
    while True:
        print(i)
        i += 1
        await asyncio.sleep(1)

async def main():
    asyncio.create_task(count())
    await asyncio.sleep(5)

asyncio.run(main())
asyncio.run(main())

Produces the following in CPython:

0
1
2
3
4
0
1
2
3
4

But in MicroPython:

0
1
2
3
4
0
5
1
6
2
7
3
8
4
9

It appears that tasks are not correctly terminated (?).

A workaround that produces the correct output is to run the second task in a second event loop:

try:
    import uasyncio as asyncio
except ImportError:
    import asyncio
async def count():
    i = 0
    while True:
        print(i)
        i += 1
        await asyncio.sleep(1)
async def main():
    asyncio.create_task(count())
    await asyncio.sleep(5)
asyncio.run(main())
asyncio.new_event_loop() # Added line
asyncio.run(main())

Note that running either of the snippets repeatedly causes more confusing output because all previous tasks are still running on the queue.

Activity

  1. peterhinch commented on Jun 29, 2021

    @peterhinch
    Contributor

    By default uasyncio retains state, as discussed here. Arguably in the interests of CPython compatibility it shouldn't, but on occasion this behaviour can be useful. Currently the user has the choice of whether to allow retained state.

  2. added
    extmodRelates to extmod/ directory in source
    on Jun 29, 2021
  3. mattytrentini commented on Jun 29, 2021

    @mattytrentini
    SponsorContributorAuthor

    By default uasyncio retains state, as discussed here.

    I did look through your docs to see if this was covered but missed this; I knew you'd be aware of this @peterhinch!

    Arguably in the interests of CPython compatibility it shouldn't, but on occasion this behaviour can be useful. Currently the user has the choice of whether to allow retained state.

    That behaviour was very unexpected to me; not just because it was different to CPython but because it didn't make any logical sense. I'd strongly prefer to see CPython compatibility in this case. I'm also concerned that there will be subtle issues porting CPython libraries that may inadvertently stumble on this problem...

  4. jimmo commented on Jul 5, 2021

    @jimmo
    Member

    Related: It would be worth considering making asyncio.run() detect that it's been (incorrectly) called recursively (or worse, from an interrupt handler).

  5. added a commit that references this issue on Mar 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extmodRelates to extmod/ directory in source

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions