This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: asyncio: call_soon() should raise an exception if the event loop is closed
Type: Stage: resolved
Components: asyncio Versions: Python 3.4, Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: gvanrossum, python-dev, terry.reedy, torsten, vstinner, yselivanov
Priority: normal Keywords: easy, patch

Created on 2014-11-23 09:32 by vstinner, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
call_soon_after_close.diff torsten, 2014-11-27 23:01 review
Messages (14)
msg231549 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-11-23 09:32
call_soon() call be called before the event loop starts and after run_forever(), the call will be executed by the next call to run_forever() (or run_until_complete).

But calling call_soon() after close() does not make sense and the user may be surprised to not see its function called. It can be obvious in a simple program, but not in a large application.
msg231788 - (view) Author: Torsten Landschoff (torsten) * Date: 2014-11-27 23:01
If anybody cares, here is a small patch to implement this. I ran the test suite and nothing else fails because of this change.

However I wonder if this is a slippery slope to go: If call_soon raises after the event loop is closed than everything else that registers an action with the loop should raise as well.

So for consistency this patch should grow quite a bit (unless create_connection, add_reader etc. already raise in this case).

If the decision is to go this path I would also suggest to add a new exception type for "Event loop is closed" so that it can be caught in client code.

YMMV
msg231789 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-11-27 23:42
> If the decision is to go this path I would also suggest to add a new exception type for "Event loop is closed" so that it can be caught in client code.

I don't see the purpose of handling such exception. It's an obvious
bug, you must not handle bugs :)
msg231790 - (view) Author: Torsten Landschoff (torsten) * Date: 2014-11-27 23:44
> > If the decision is to go this path I would also suggest to add a new exception type for "Event loop is closed" so that it can be caught in client code.

> I don't see the purpose of handling such exception. It's an obvious
bug, you must not handle bugs :)

Unless you can't directly fix them. They might be inside a library and triggered during application shutdown.
msg231791 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-11-27 23:47
> They might be inside a library and triggered during application shutdown.

In this case, fix the library.
msg231810 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-11-28 12:48
call_soon_after_close.diff looks good but also incomplete: call_later, call_at and run_in_executor should also raise an exception if the event loop is closed.

You should also add call_soon_threadsafe to the test.

> So for consistency this patch should grow quite a bit (unless create_connection, add_reader etc. already raise in this case).

Yes, add_reader raises an exception and there is an unit test to ensure that.

create_task() is a little bit special, it does not schedule immediatly a coroutine. IMO it makes sense to fail if the loop was closed, I don't see how the task can be executed if the loop was executed, so calling create_task() on a closed loop looks like a bug.

I suggest to modify the following methods:
- call_soon, call_soon_threadsafe
- call_at, call_later
- run_in_executor
- create_task
- add_signal_handler
- subprocess_exec, subprocess_shell

Did I miss something?

I'm not sure that *all* asyncio methods should must call _check_closed(), it may make the code harder to read. If the basic functions like call_soon and add_reader already handle the closed status, I guess that all other methods will fail loudly, so they don't need to be modified.

For example, stop() calls call_soon() and so will also raises an exception if the loop is closed.

Maybe we should add almost all methods to the test checking that calling these methods on a closed loop fail.
msg231844 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-11-29 00:33
Adding minimal code checks to make multiple tests pass sounds good to me.
msg232155 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2014-12-04 22:09
New changeset 226f870b387d by Victor Stinner in branch '3.4':
Closes #22922: More EventLoop methods fail if the loop is closed. Initial patch
https://hg.python.org/cpython/rev/226f870b387d
msg232157 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-12-04 22:12
I didn't change subprocess_exec() nor subprocess_shell() because they are coroutine. A coroutine object can only raise an exception when they are executed, whereas a closed loop cannot execute a coroutine object. I modified create_task() to fail if the event loop is closed, it should be enough.

Thanks Torsten Landschoff for your fix.
msg232158 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-12-04 23:02
Windows buildbots are not happy:

http://buildbot.python.org/all/builders/AMD64%20Windows7%20SP1%203.x/builds/5385/steps/test/logs/stdio


======================================================================
ERROR: test_close (test.test_asyncio.test_windows_events.ProactorTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\asyncio\proactor_events.py", line 394, in close
    self._close_self_pipe()
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\asyncio\proactor_events.py", line 423, in _close_self_pipe
    self._self_reading_future.cancel()
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\asyncio\windows_events.py", line 70, in cancel
    return super().cancel()
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\asyncio\futures.py", line 230, in cancel
    self._schedule_callbacks()
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\asyncio\futures.py", line 245, in _schedule_callbacks
    self._loop.call_soon(callback, self)
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\asyncio\base_events.py", line 384, in call_soon
    handle = self._call_soon(callback, args, check_loop=True)
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\asyncio\base_events.py", line 395, in _call_soon
    self._check_closed()
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\asyncio\base_events.py", line 234, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
msg232163 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2014-12-05 00:27
New changeset 6a955db1f78f by Victor Stinner in branch 'default':
Issue #22922: Fix ProactorEventLoop.close()
https://hg.python.org/cpython/rev/6a955db1f78f
msg232164 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2014-12-05 00:45
New changeset 0a7d956a2f2d by Victor Stinner in branch '3.4':
Issue #22922: Fix ProactorEventLoop.close()
https://hg.python.org/cpython/rev/0a7d956a2f2d
msg232778 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-12-16 23:56
> Windows buildbots are not happy:

test_asyncio pass again on Windows buildbots, I close the issue.
msg233943 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2015-01-13 15:26
New changeset 6c473f82309d by Victor Stinner in branch '3.4':
Issue #22922: Fix ProactorEventLoop.close()
https://hg.python.org/cpython/rev/6c473f82309d
History
Date User Action Args
2022-04-11 14:58:10adminsetgithub: 67111
2015-01-13 15:26:28python-devsetmessages: + msg233943
2014-12-16 23:56:17vstinnersetstatus: open -> closed
resolution: fixed
messages: + msg232778
2014-12-05 00:45:35python-devsetmessages: + msg232164
2014-12-05 00:27:50python-devsetmessages: + msg232163
2014-12-04 23:02:53vstinnersetstatus: closed -> open
resolution: fixed -> (no value)
messages: + msg232158
2014-12-04 22:12:35vstinnersetmessages: + msg232157
2014-12-04 22:09:53python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg232155

resolution: fixed
stage: resolved
2014-11-29 00:33:46terry.reedysetnosy: + terry.reedy
messages: + msg231844
2014-11-28 12:48:44vstinnersetmessages: + msg231810
2014-11-27 23:47:34vstinnersetmessages: + msg231791
2014-11-27 23:44:57torstensetmessages: + msg231790
2014-11-27 23:42:10vstinnersetmessages: + msg231789
2014-11-27 23:01:18torstensetfiles: + call_soon_after_close.diff

nosy: + torsten
messages: + msg231788

keywords: + patch
2014-11-23 09:32:03vstinnercreate