[Python-checkins] bpo-26552: Fixed case where failing `asyncio.ensure_future` did not close the coroutine (#30288)

gvanrossum webhook-mailer at python.org
Fri Jan 28 17:24:43 EST 2022


https://github.com/python/cpython/commit/24cc6411adbfe5555ecd8901f1ea50caa414c908
commit: 24cc6411adbfe5555ecd8901f1ea50caa414c908
branch: main
author: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com>
committer: gvanrossum <gvanrossum at gmail.com>
date: 2022-01-28T14:24:35-08:00
summary:

bpo-26552: Fixed case where failing `asyncio.ensure_future` did not close the coroutine (#30288)

files:
A Misc/NEWS.d/next/Library/2021-12-29-13-42-55.bpo-26552.1BqeAn.rst
M Lib/asyncio/tasks.py
M Lib/test/test_asyncio/test_base_events.py

diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 445a9f51226ed..2bee5c050ded7 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 17e8396cfe2ef..c64e1623a0395 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.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
 
@@ -796,6 +796,17 @@ def create_task(self, coro):
         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 0000000000000..85b6a64ef53d1
--- /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



More information about the Python-checkins mailing list