dabeaz / curio

Good Curio!
Other
4.01k stars 240 forks source link

TaskGroup exiting on cancellation #362

Closed skumargupta-1 closed 11 months ago

skumargupta-1 commented 11 months ago

I'm more than happy to accept bug reports and may continue to work on it from time to time as the mood strikes.

I think this is a bug, but please let me know if this is intended behavior and I will close the issue.

Consider this sample program:

import curio
from curio import TaskGroup

async def multiply(by):
    num = 1
    while True:
        num *= by
        print(f"{num=}")
        await curio.sleep(by)

async def stopper(m2):
    await curio.sleep(10)
    await m2.cancel()

async def main():
    async with TaskGroup() as group:
        m2 = await group.spawn(multiply, 2)
        await group.spawn(multiply, 3)
        await group.spawn(stopper, m2)

if __name__ == "__main__":
    curio.run(main)

This program exits out when multiply2 is cancelled.

$ py test.py 
num=2
num=3
num=4
num=9
num=8
num=27
num=16
num=32
num=81
$ 

I would have expected the program to continue ad infinitum printing multiples of 3.

asyncio documentation says:

The first time any of the tasks belonging to the group fails with an exception other than asyncio.CancelledError, the remaining tasks in the group are cancelled.

However, curio makes no such exception for curio.TaskCancelledError and always exits out:

https://github.com/dabeaz/curio/blob/5d8ecb2333761b4fd629e14d940f3807d143c0ed/curio/task.py#L548

dabeaz commented 11 months ago

The curio TaskGroup implementation predates the one in asyncio so any similarities between the two are purely coincidental (and I can't honesty remember if Curio ever made a special exception for cancellation here). If you want to handle this case in Curio, a task that could be potentially cancelled should probably be written with an explicit try/except to catch it and return.