diff -r cca2ed4e8b41 Include/genobject.h --- a/Include/genobject.h Thu Dec 17 10:35:05 2015 +0000 +++ b/Include/genobject.h Thu Dec 17 16:21:15 2015 -0500 @@ -43,6 +43,7 @@ PyAPI_FUNC(int) PyGen_NeedsFinalizing(PyGenObject *); PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); PyObject *_PyGen_Send(PyGenObject *, PyObject *); +PyObject *_PyGen_yf(PyGenObject *); PyAPI_FUNC(void) _PyGen_Finalize(PyObject *self); #ifndef Py_LIMITED_API diff -r cca2ed4e8b41 Lib/test/test_coroutines.py --- a/Lib/test/test_coroutines.py Thu Dec 17 10:35:05 2015 +0000 +++ b/Lib/test/test_coroutines.py Thu Dec 17 16:21:15 2015 -0500 @@ -801,6 +801,24 @@ with self.assertRaises(Marker): c.throw(ZeroDivisionError) + def test_await_15(self): + @types.coroutine + def nop(): + yield + + async def coroutine(): + await nop() + + async def waiter(coro): + await coro + + coro = coroutine() + coro.send(None) + + with self.assertRaisesRegex(RuntimeError, + "coroutine is being awaited already"): + waiter(coro).send(None) + def test_with_1(self): class Manager: def __init__(self, name): diff -r cca2ed4e8b41 Objects/genobject.c --- a/Objects/genobject.c Thu Dec 17 10:35:05 2015 +0000 +++ b/Objects/genobject.c Thu Dec 17 16:21:15 2015 -0500 @@ -258,8 +258,8 @@ return 0; } -static PyObject * -gen_yf(PyGenObject *gen) +PyObject * +_PyGen_yf(PyGenObject *gen) { PyObject *yf = NULL; PyFrameObject *f = gen->gi_frame; @@ -281,7 +281,7 @@ gen_close(PyGenObject *gen, PyObject *args) { PyObject *retval; - PyObject *yf = gen_yf(gen); + PyObject *yf = _PyGen_yf(gen); int err = 0; if (yf) { @@ -321,7 +321,7 @@ PyObject *typ; PyObject *tb = NULL; PyObject *val = NULL; - PyObject *yf = gen_yf(gen); + PyObject *yf = _PyGen_yf(gen); _Py_IDENTIFIER(throw); if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) @@ -555,7 +555,7 @@ static PyObject * gen_getyieldfrom(PyGenObject *gen) { - PyObject *yf = gen_yf(gen); + PyObject *yf = _PyGen_yf(gen); if (yf == NULL) Py_RETURN_NONE; return yf; @@ -790,7 +790,7 @@ static PyObject * coro_get_cr_await(PyCoroObject *coro) { - PyObject *yf = gen_yf((PyGenObject *) coro); + PyObject *yf = _PyGen_yf((PyGenObject *) coro); if (yf == NULL) Py_RETURN_NONE; return yf; diff -r cca2ed4e8b41 Python/ceval.c --- a/Python/ceval.c Thu Dec 17 10:35:05 2015 +0000 +++ b/Python/ceval.c Thu Dec 17 16:21:15 2015 -0500 @@ -2021,6 +2021,21 @@ Py_DECREF(iterable); + if (iter != NULL && PyCoro_CheckExact(iter)) { + PyObject *yf = _PyGen_yf((PyGenObject*)iter); + if (yf != NULL) { + /* `iter` is a coroutine object that is being + awaited, `yf` is a pointer the current awaitable + being awaited on. */ + Py_DECREF(yf); + Py_CLEAR(iter); + PyErr_SetString( + PyExc_RuntimeError, + "coroutine is being awaited already"); + /* The code below jumps to `error` if `iter` is NULL. */ + } + } + SET_TOP(iter); /* Even if it's NULL */ if (iter == NULL) {