diff -r 5f773540e2ef Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py Fri Oct 10 13:04:08 2014 +0200 +++ b/Lib/asyncio/base_events.py Fri Oct 10 14:00:53 2014 +0200 @@ -268,7 +268,16 @@ class BaseEventLoop(events.AbstractEvent 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 raises an exception which don't inherit from + # Exception (ex: KeyboardInterrupt). 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 -r 5f773540e2ef Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py Fri Oct 10 13:04:08 2014 +0200 +++ b/Lib/test/test_asyncio/test_base_events.py Fri Oct 10 14:00:53 2014 +0200 @@ -9,7 +9,7 @@ import time 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,23 @@ class BaseEventLoopTests(test_utils.Test task._log_destroy_pending = False coro.close() + def test_run_forever_keyboard_interrupt(self): + @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