> On Jul 5, 2016, at 8:56 PM, Nathaniel Smith <n...@pobox.com> wrote:
[..]
> Starting axiom: async functions / async generators need to be prepared
> for the case where they get garbage collected before being run to
> completion, because, well... this is a thing that can happen.
[..]
> Dismaying conclusion: inside an async function / async generator,
> finally: blocks must never yield (and neither can __aexit__
> callbacks), because they might be invoked during garbage collection.

I agree with David here: coroutines are always running under a scheduler
which, in one way or another, keeps strong references to them.  In curio
it’s a global table of all tasks, in asyncio it’s a chain of references
to callbacks of Tasks/Futures.  The only time a coroutine can be GC’ed 
in asyncio is when the caller did not use ‘await’ on it.

A running coroutine being GC’ed is an exceptional situation, that means 
that there is a bug in your scheduler.  And people actually rely on this
thing.  It’s not so much about __aexit__ returning an awaitable, it’s
about people writing code that awaits in ‘finally’ statements.

That’s why I’m big -1 on changing __aexit__.  If we change __aexit__, 
we should also prohibit awaiting in finally blocks, which is not an 
option.


> For async functions this is... arguably a problem but not super
> urgent, because async functions rarely get garbage collected without
> being run to completion. For async generators it's a much bigger
> problem.

I’m not sure I understand why it’d a problem for async generators.
Since coroutines shouldn’t ever be GC’ed while running, async generators
generally won’t be GC’ed while running too, because they will have
a strong ref from the running coroutine.

I think to makes things simple, we shouldn’t have a ‘close()’
method on async generators at all.  When a running async generator is
GC’ed we’ll make the interpreter to issue a warning.

We might want to add an ‘aclose()’ coroutine method, which will throw 
a GeneratorExit exception (or GeneratorAsyncExit) with the following
semantics:

1. If the running async generator ignores GeneratorAsyncExit and keeps
‘async yielding’, we throw a RuntimeError.

2. If the running async generator receives a GeneratorAsyncExit exception
outside of a try..finally block, the async generator is closed silently.

3. If the running async generator receives a GeneratorAsyncExit exception
inside a ‘finally’ block, it will be able to await on any number of
coroutines inside that block.

Thanks,
Yury

_______________________________________________
Async-sig mailing list
Async-sig@python.org
https://mail.python.org/mailman/listinfo/async-sig
Code of Conduct: https://www.python.org/psf/codeofconduct/

Reply via email to