[Python-checkins] cpython (3.4): Closes #22429, asyncio: Fix EventLoop.run_until_complete(), don't stop the
victor.stinner
python-checkins at python.org
Fri Dec 5 01:45:37 CET 2014
https://hg.python.org/cpython/rev/83bddbfbd3a4
changeset: 93727:83bddbfbd3a4
branch: 3.4
user: Victor Stinner <victor.stinner at gmail.com>
date: Fri Dec 05 01:44:10 2014 +0100
summary:
Closes #22429, asyncio: Fix EventLoop.run_until_complete(), don't stop the
event loop if a BaseException is raised, because the event loop is already
stopped.
files:
Lib/asyncio/base_events.py | 14 +++++-
Lib/test/test_asyncio/test_base_events.py | 25 +++++++++++
2 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -102,6 +102,16 @@
raise _StopError
+def _run_until_complete_cb(fut):
+ exc = fut._exception
+ if (isinstance(exc, BaseException)
+ and not isinstance(exc, Exception)):
+ # Issue #22429: run_forever() already finished, no need to
+ # stop it.
+ return
+ _raise_stop_error()
+
+
class Server(events.AbstractServer):
def __init__(self, loop, sockets):
@@ -268,7 +278,7 @@
# is no need to log the "destroy pending task" message
future._log_destroy_pending = False
- future.add_done_callback(_raise_stop_error)
+ future.add_done_callback(_run_until_complete_cb)
try:
self.run_forever()
except:
@@ -278,7 +288,7 @@
# local task.
future.exception()
raise
- future.remove_done_callback(_raise_stop_error)
+ future.remove_done_callback(_run_until_complete_cb)
if not future.done():
raise RuntimeError('Event loop stopped before Future completed.')
diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -638,6 +638,31 @@
self.assertFalse(self.loop.call_exception_handler.called)
+ def test_run_until_complete_baseexception(self):
+ # Python issue #22429: run_until_complete() must not schedule a pending
+ # call to stop() if the future raised a BaseException
+ @asyncio.coroutine
+ def raise_keyboard_interrupt():
+ raise KeyboardInterrupt
+
+ self.loop._process_events = mock.Mock()
+
+ try:
+ self.loop.run_until_complete(raise_keyboard_interrupt())
+ except KeyboardInterrupt:
+ pass
+
+ def func():
+ self.loop.stop()
+ func.called = True
+ func.called = False
+ try:
+ self.loop.call_soon(func)
+ self.loop.run_forever()
+ except KeyboardInterrupt:
+ pass
+ self.assertTrue(func.called)
+
class MyProto(asyncio.Protocol):
done = None
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list