classification
Title: RuntimeError('Event loop is closed') after cancelling getaddrinfo and closing loop
Type: Stage: patch review
Components: asyncio Versions: Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: asvetlov, benjamin.peterson, njs, vitaly.krug, yselivanov
Priority: normal Keywords: patch

Created on 2018-03-26 22:50 by vitaly.krug, last changed 2018-04-14 22:05 by benjamin.peterson.

Pull Requests
URL Status Linked Edit
PR 6474 closed steve.dower, 2018-04-14 21:53
Messages (3)
msg314484 - (view) Author: Vitaly Kruglikov (vitaly.krug) Date: 2018-03-26 22:50
I see this exception on the terminal:
```
exception calling callback for <Future at 0x10722ee48 state=finished returned list>
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.6.4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/_base.py", line 324, in _invoke_callbacks
    callback(self)
  File "/usr/local/Cellar/python/3.6.4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/futures.py", line 414, in _call_set_state
    dest_loop.call_soon_threadsafe(_set_state, destination, source)
  File "/usr/local/Cellar/python/3.6.4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 620, in call_soon_threadsafe
    self._check_closed()
  File "/usr/local/Cellar/python/3.6.4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
```

When executing this code:
```
import asyncio

while True:
    loop = asyncio.new_event_loop()

    coro = loop.getaddrinfo('www.google.com', 80)

    task = asyncio.ensure_future(coro, loop=loop)

    task.cancel()

    loop.call_soon_threadsafe(loop.stop)

    loop.run_forever()

    loop.close()
```

Shouldn't a cancelled operation go away (or at least pretend to go away) cleanly?
msg314488 - (view) Author: Nathaniel Smith (njs) * (Python committer) Date: 2018-03-27 00:55
Yeah, getaddrinfo isn't actually cancellable (because it's a blocking call that has to be run in a thread), but it's side-effect-free so if the user requests that it be cancelled then it's safe to return immediately while it keeps running in the background, and asyncio does so. But if we've already decided to discard the result then it's better to do that silently, like you say.

When trio hits this case, it does silently throw away the result: https://github.com/python-trio/trio/blob/aebb42888dd0978c3b74f8c9cdf8aec2ce2cbd73/trio/_threads.py#L372-L377
It's a little bit more obvious in trio's case because there we 100% know that if the call to `trio.run` has finished, then there's no-one listening for the result, and that the user has explicitly requested this behavior. In asyncio's case, I guess in *theory* someone could still be hoping the Future's done callback will be invoked even after the loop is closed. This seems unlikely though... and in general when the loop is closed then every other registered callback is silently discarded, so doing that for run_in_executor seems fine too.
msg315306 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2018-04-14 22:05
New changeset bba2ba180de91177a73d28551dce71696d472c47 by Benjamin Peterson (Steve Dower) in branch '2.7':
bpo-33148: Update Windows build to use OpenSSL 1.0.2o
https://github.com/python/cpython/commit/bba2ba180de91177a73d28551dce71696d472c47
History
Date User Action Args
2018-04-14 22:05:05benjamin.petersonsetnosy: + benjamin.peterson
messages: + msg315306
2018-04-14 21:53:15steve.dowersetkeywords: + patch
stage: patch review
pull_requests: + pull_request6173
2018-03-27 00:55:18njssetnosy: + njs
messages: + msg314488
2018-03-26 22:50:43vitaly.krugcreate