This commit is contained in:
Georg Brandl 2014-10-11 15:08:12 +02:00
commit 983db8905c
2 changed files with 30 additions and 2 deletions

View File

@ -268,7 +268,15 @@ class BaseEventLoop(events.AbstractEventLoop):
future._log_destroy_pending = False future._log_destroy_pending = False
future.add_done_callback(_raise_stop_error) 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) future.remove_done_callback(_raise_stop_error)
if not future.done(): if not future.done():
raise RuntimeError('Event loop stopped before Future completed.') raise RuntimeError('Event loop stopped before Future completed.')

View File

@ -9,7 +9,7 @@ import time
import unittest import unittest
from unittest import mock from unittest import mock
from test.script_helper import assert_python_ok from test.script_helper import assert_python_ok
from test.support import IPV6_ENABLED from test.support import IPV6_ENABLED, gc_collect
import asyncio import asyncio
from asyncio import base_events from asyncio import base_events
@ -618,6 +618,26 @@ class BaseEventLoopTests(test_utils.TestCase):
task._log_destroy_pending = False task._log_destroy_pending = False
coro.close() 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): class MyProto(asyncio.Protocol):
done = None done = None