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.
This commit is contained in:
parent
682124ccc3
commit
c8bd53f815
|
@ -268,7 +268,15 @@ class BaseEventLoop(events.AbstractEventLoop):
|
|||
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.')
|
||||
|
|
|
@ -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,26 @@ class BaseEventLoopTests(test_utils.TestCase):
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue