]> granicus.if.org Git - python/commitdiff
Issue #27972: Prohibit Tasks to await on themselves.
authorYury Selivanov <yury@magic.io>
Sun, 9 Oct 2016 16:19:12 +0000 (12:19 -0400)
committerYury Selivanov <yury@magic.io>
Sun, 9 Oct 2016 16:19:12 +0000 (12:19 -0400)
Lib/asyncio/tasks.py
Lib/test/test_asyncio/test_tasks.py
Misc/NEWS

index f735b44dc015a342bde3df51b86a2beafd20ff86..14949d1340719c1149da3c07d412dabdaa270d79 100644 (file)
@@ -241,7 +241,7 @@ class Task(futures.Future):
                 result = coro.throw(exc)
         except StopIteration as exc:
             self.set_result(exc.value)
-        except futures.CancelledError as exc:
+        except futures.CancelledError:
             super().cancel()  # I.e., Future.cancel(self).
         except Exception as exc:
             self.set_exception(exc)
@@ -259,12 +259,19 @@ class Task(futures.Future):
                             'Task {!r} got Future {!r} attached to a '
                             'different loop'.format(self, result)))
                 elif blocking:
-                    result._asyncio_future_blocking = False
-                    result.add_done_callback(self._wakeup)
-                    self._fut_waiter = result
-                    if self._must_cancel:
-                        if self._fut_waiter.cancel():
-                            self._must_cancel = False
+                    if result is self:
+                        self._loop.call_soon(
+                            self._step,
+                            RuntimeError(
+                                'Task cannot await on itself: {!r}'.format(
+                                    self)))
+                    else:
+                        result._asyncio_future_blocking = False
+                        result.add_done_callback(self._wakeup)
+                        self._fut_waiter = result
+                        if self._must_cancel:
+                            if self._fut_waiter.cancel():
+                                self._must_cancel = False
                 else:
                     self._loop.call_soon(
                         self._step,
index 2863c423b5190ee8bcb905db4d634c627bd3d040..a5af7d18cf34e21a484257ee53dd44f1afbb35c6 100644 (file)
@@ -92,6 +92,17 @@ class TaskTests(test_utils.TestCase):
         finally:
             other_loop.close()
 
+    def test_task_awaits_on_itself(self):
+        @asyncio.coroutine
+        def test():
+            yield from task
+
+        task = asyncio.ensure_future(test(), loop=self.loop)
+
+        with self.assertRaisesRegex(RuntimeError,
+                                    'Task cannot await on itself'):
+            self.loop.run_until_complete(task)
+
     def test_task_class(self):
         @asyncio.coroutine
         def notmuch():
index 90eed7d5c98693d17f2297e66c598605845f6e68..4c4bb8eb86ce5d83e3260fe612825d2190213d9e 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -388,6 +388,8 @@ Library
 - Issue #28399: Remove UNIX socket from FS before binding.
   Patch by Коренберг Марк.
 
+- Issue #27972: Prohibit Tasks to await on themselves.
+
 IDLE
 ----