bpo-39386: Prevent double awaiting of async iterator (GH-18081)

(cherry picked from commit a96e06db77dcbd3433d39761ddb4615d7d96284a)

Co-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>
diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py
index 58d8aee..24b20be 100644
--- a/Lib/test/test_asyncgen.py
+++ b/Lib/test/test_asyncgen.py
@@ -1128,6 +1128,42 @@
 
         self.assertEqual([], messages)
 
+    def test_async_gen_await_anext_twice(self):
+        async def async_iterate():
+            yield 1
+            yield 2
+
+        async def run():
+            it = async_iterate()
+            nxt = it.__anext__()
+            await nxt
+            with self.assertRaisesRegex(
+                    RuntimeError,
+                    r"cannot reuse already awaited __anext__\(\)/asend\(\)"
+            ):
+                await nxt
+
+            await it.aclose()  # prevent unfinished iterator warning
+
+        self.loop.run_until_complete(run())
+
+    def test_async_gen_await_aclose_twice(self):
+        async def async_iterate():
+            yield 1
+            yield 2
+
+        async def run():
+            it = async_iterate()
+            nxt = it.aclose()
+            await nxt
+            with self.assertRaisesRegex(
+                    RuntimeError,
+                    r"cannot reuse already awaited aclose\(\)/athrow\(\)"
+            ):
+                await nxt
+
+        self.loop.run_until_complete(run())
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-01-20-21-40-57.bpo-39386.ULqD8t.rst b/Misc/NEWS.d/next/Core and Builtins/2020-01-20-21-40-57.bpo-39386.ULqD8t.rst
new file mode 100644
index 0000000..f24e1f4
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-01-20-21-40-57.bpo-39386.ULqD8t.rst
@@ -0,0 +1 @@
+Prevent double awaiting of async iterator.
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 5643553..72aa872 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -1533,7 +1533,9 @@
     PyObject *result;
 
     if (o->ags_state == AWAITABLE_STATE_CLOSED) {
-        PyErr_SetNone(PyExc_StopIteration);
+        PyErr_SetString(
+            PyExc_RuntimeError,
+            "cannot reuse already awaited __anext__()/asend()");
         return NULL;
     }
 
@@ -1576,7 +1578,9 @@
     PyObject *result;
 
     if (o->ags_state == AWAITABLE_STATE_CLOSED) {
-        PyErr_SetNone(PyExc_StopIteration);
+        PyErr_SetString(
+            PyExc_RuntimeError,
+            "cannot reuse already awaited __anext__()/asend()");
         return NULL;
     }
 
@@ -1810,7 +1814,9 @@
 
     if (f == NULL || f->f_stacktop == NULL ||
             o->agt_state == AWAITABLE_STATE_CLOSED) {
-        PyErr_SetNone(PyExc_StopIteration);
+        PyErr_SetString(
+            PyExc_RuntimeError,
+            "cannot reuse already awaited aclose()/athrow()");
         return NULL;
     }
 
@@ -1932,7 +1938,9 @@
     PyObject *retval;
 
     if (o->agt_state == AWAITABLE_STATE_CLOSED) {
-        PyErr_SetNone(PyExc_StopIteration);
+        PyErr_SetString(
+            PyExc_RuntimeError,
+            "cannot reuse already awaited aclose()/athrow()");
         return NULL;
     }