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):
# 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:
# 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.')
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