But what if the task catches the exception and ignores it? That is
legitimate behavior. The task should be allowed to continue in the
background if it wishes.


On Fri, Feb 7, 2014 at 7:26 AM, Victor Stinner <[email protected]>wrote:

> Hi,
>
> I have a complex issue in Trollius, and I just realized that Tulip has
> the same behaviour (but the consequence are less important). Do you
> think that the issue should be fixed in Tulip too? I mean apply this
> patch to Tulip:
> https://bitbucket.org/enovance/trollius/commits/e8e82dc
>
> Ok, now let's see the whole story.
>
> * * *
>
> The following script displays "Task cancelled on timeout? False":
> ---
> import asyncio
>
> @asyncio.coroutine
> def coro():
>     task = asyncio.async(asyncio.wait_for(asyncio.sleep(1.0), 0.1))
>     try:
>         yield from task
>     except asyncio.TimeoutError:
>         print("Task cancelled on timeout? %s" % task.cancelled())
>
> loop = asyncio.get_event_loop()
> loop.run_until_complete(coro())
> ---
>
> The problem is that wait_for() calls fut.cancel(), but Task.cancel()
> cancels itself asynchronously if the task is waiting for a Future
> object. There is a pending call to Task._wakeup() which will be
> executed later.
>
> I found this surprising behaviour while trying to fix an issue in
> Trollius: test_wait_for() fails with Trollius.
>
> I modified wait_for() in Trollius to wait until the task is really
> cancelled, changset:
> https://bitbucket.org/enovance/trollius/commits/e8e82dc
>
> * * *
>
> In Trollius, the situation is worse than Tulip because there are more
> links between futures and tasks. See this example:
> ---
> @asyncio.coroutine
> def task2():
>     yield [from] asyncio.sleep(1.0)
>
> @asyncio.coroutine
> def task1():
>     yield [from] task2()
> ---
>
> With Tulip, task1() waits for sleep internal future:
>
>    task1 => sleep future
>
> With Trollius, task1() waits for task2() which itself waits for sleep
> which waits for sleep internal future:
>
>    task1 => task2 => sleep => sleep future
>
> Cancelling task1 is first propagated synchronously to the left (to
> child futures), and then come back asynchronously to the parents (to
> task1).
>
> In Tulip, test_wait_for() test pass because there is just one pending
> call to cancel task1. In Trollius, it takes more roundtips of event
> loop, because each cancellation requires one loop iteration.
>
> Victor
>



-- 
--Guido van Rossum (python.org/~guido)

Reply via email to