> 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/