From a5451c96a14ac0c3ee7cef7b5c52ab1d783ec613 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Sat, 29 Jan 2022 12:27:18 +0530 Subject: bpo-26552: Fixed case where failing `asyncio.ensure_future` did not close the coroutine (#30288) (#31003) --- Lib/asyncio/tasks.py | 10 ++++++++-- Lib/test/test_asyncio/test_base_events.py | 13 ++++++++++++- .../next/Library/2021-12-29-13-42-55.bpo-26552.1BqeAn.rst | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-12-29-13-42-55.bpo-26552.1BqeAn.rst diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 445a9f5..2bee5c0 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -621,17 +621,23 @@ def _ensure_future(coro_or_future, *, loop=None): raise ValueError('The future belongs to a different loop than ' 'the one specified as the loop argument') return coro_or_future - + called_wrap_awaitable = False if not coroutines.iscoroutine(coro_or_future): if inspect.isawaitable(coro_or_future): coro_or_future = _wrap_awaitable(coro_or_future) + called_wrap_awaitable = True else: raise TypeError('An asyncio.Future, a coroutine or an awaitable ' 'is required') if loop is None: loop = events._get_event_loop(stacklevel=4) - return loop.create_task(coro_or_future) + try: + return loop.create_task(coro_or_future) + except RuntimeError: + if not called_wrap_awaitable: + coro_or_future.close() + raise @types.coroutine diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index f7ef23e..d77bf95 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -18,7 +18,7 @@ from test import support from test.support.script_helper import assert_python_ok from test.support import os_helper from test.support import socket_helper - +import warnings MOCK_ANY = mock.ANY PY34 = sys.version_info >= (3, 4) @@ -801,6 +801,17 @@ class BaseEventLoopTests(test_utils.TestCase): task._log_destroy_pending = False coro.close() + def test_create_task_error_closes_coro(self): + async def test(): + pass + loop = asyncio.new_event_loop() + loop.close() + with warnings.catch_warnings(record=True) as w: + with self.assertRaises(RuntimeError): + asyncio.ensure_future(test(), loop=loop) + self.assertEqual(len(w), 0) + + def test_create_named_task_with_default_factory(self): async def test(): pass diff --git a/Misc/NEWS.d/next/Library/2021-12-29-13-42-55.bpo-26552.1BqeAn.rst b/Misc/NEWS.d/next/Library/2021-12-29-13-42-55.bpo-26552.1BqeAn.rst new file mode 100644 index 0000000..85b6a64 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-29-13-42-55.bpo-26552.1BqeAn.rst @@ -0,0 +1 @@ +Fixed case where failing :func:`asyncio.ensure_future` did not close the coroutine. Patch by Kumar Aditya. \ No newline at end of file -- cgit v0.12