[Python-checkins] cpython (3.4): Issue #22601: run_forever() now consumes BaseException of the temporary task

victor.stinner python-checkins at python.org
Sat Oct 11 14:36:34 CEST 2014


https://hg.python.org/cpython/rev/fb65b9ed8023
changeset:   92949:fb65b9ed8023
branch:      3.4
parent:      92945:4563fff4e099
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Sat Oct 11 14:30:18 2014 +0200
summary:
  Issue #22601: run_forever() now consumes BaseException of the temporary task

If the coroutine raised a BaseException, consume the exception to not log a
warning. The caller doesn't have access to the local task.

files:
  Lib/asyncio/base_events.py                |  10 ++++-
  Lib/test/test_asyncio/test_base_events.py |  22 ++++++++++-
  2 files changed, 30 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
@@ -268,7 +268,15 @@
             future._log_destroy_pending = False
 
         future.add_done_callback(_raise_stop_error)
-        self.run_forever()
+        try:
+            self.run_forever()
+        except:
+            if new_task and future.done() and not future.cancelled():
+                # The coroutine raised a BaseException. Consume the exception
+                # to not log a warning, the caller doesn't have access to the
+                # local task.
+                future.exception()
+            raise
         future.remove_done_callback(_raise_stop_error)
         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
@@ -9,7 +9,7 @@
 import unittest
 from unittest import mock
 from test.script_helper import assert_python_ok
-from test.support import IPV6_ENABLED
+from test.support import IPV6_ENABLED, gc_collect
 
 import asyncio
 from asyncio import base_events
@@ -618,6 +618,26 @@
         task._log_destroy_pending = False
         coro.close()
 
+    def test_run_forever_keyboard_interrupt(self):
+        # Python issue #22601: ensure that the temporary task created by
+        # run_forever() consumes the KeyboardInterrupt and so don't log
+        # a warning
+        @asyncio.coroutine
+        def raise_keyboard_interrupt():
+            raise KeyboardInterrupt
+
+        self.loop._process_events = mock.Mock()
+        self.loop.call_exception_handler = mock.Mock()
+
+        try:
+            self.loop.run_until_complete(raise_keyboard_interrupt())
+        except KeyboardInterrupt:
+            pass
+        self.loop.close()
+        gc_collect()
+
+        self.assertFalse(self.loop.call_exception_handler.called)
+
 
 class MyProto(asyncio.Protocol):
     done = None

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list