GH-95899: fix asyncio.Runner to call set_event_loop only once (#95900)

This commit is contained in:
Kumar Aditya 2022-08-15 22:32:47 +05:30 committed by GitHub
parent 2fa03b1b07
commit 914f6367a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 3 deletions

View file

@ -114,8 +114,6 @@ class Runner:
self._interrupt_count = 0
try:
if self._set_event_loop:
events.set_event_loop(self._loop)
return self._loop.run_until_complete(task)
except exceptions.CancelledError:
if self._interrupt_count > 0:
@ -136,7 +134,11 @@ class Runner:
return
if self._loop_factory is None:
self._loop = events.new_event_loop()
self._set_event_loop = True
if not self._set_event_loop:
# Call set_event_loop only once to avoid calling
# attach_loop multiple times on child watchers
events.set_event_loop(self._loop)
self._set_event_loop = True
else:
self._loop = self._loop_factory()
if self._debug is not None:

View file

@ -455,6 +455,20 @@ class RunnerTests(BaseTest):
):
runner.run(coro())
def test_set_event_loop_called_once(self):
# See https://github.com/python/cpython/issues/95736
async def coro():
pass
policy = asyncio.get_event_loop_policy()
policy.set_event_loop = mock.Mock()
runner = asyncio.Runner()
runner.run(coro())
runner.run(coro())
self.assertEqual(1, policy.set_event_loop.call_count)
runner.close()
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1 @@
Fix :class:`asyncio.Runner` to call :func:`asyncio.set_event_loop` only once to avoid calling :meth:`~asyncio.AbstractChildWatcher.attach_loop` multiple times on child watchers. Patch by Kumar Aditya.