> On Jul 5, 2016, at 5: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.

This thread is really confusing, so I'm going to try to just attack this axiom 
(which isn't really axiomatic, it's a conclusion drawn from a few other 
properties of the interpreter and the event loop) and see if it holds :-).

Yury already pointed out that coroutines run under a scheduler that keeps 
strong references to them.  Backing that up a little bit - by definition, if 
your coroutine is not strongly referenced by a scheduler, it can't be doing 
anything interesting; nobody's going to call .send on it.  This is why 'foo()' 
is a no-op whereas 'await foo()' actually causes something to happen.  
Similarly, this is why you need Task() to do something in parallel, and you 
can't just toss a coroutine out into the void.

Furthermore, Task.cancel()'s documentation holds another clue about 
asynchronous cleanup:

"Unlike Future.cancel(), this does not guarantee that the task will be 
cancelled: the exception might be caught and acted upon, delaying cancellation 
of the task or preventing cancellation completely".

Deferred.cancel() behaves in much the same way, for the same reason.  It is 
explicitly allowed that an asynchronous task do asynchronous clean-up.

Now, if you have a task that was scheduled but has come forcibly detached from 
its scheduler, you are in a bit of a mess.  But this is an inherently 
unresolvable mess, for the same reason that Thread.kill() is an inherently 
unresolvable mess: you cannot forcibly terminate a thread of execution and end 
up with your program in a known state.  It's OK to kill a generator (as 
distinct from a 'coroutine' in the sense that it does not expect .send to be 
called on it) from the GC because a generator is just yielding values and since 
it doesn't expect .send it can't expect to keep running, and it can do purely 
synchronous try/finally.  But as soon as you are allowed to invoke asynchronous 
work, you have to be allowed to let that asynchronous work complete.

So: async functions should not and cannot be prepared for the case where they 
get garbage collected; this is not a thing that can happen unless the coroutine 
scheduler is damaged beyond repair and it's time to crash your process.

-glyph
_______________________________________________
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