@@ -78,7 +78,7 @@ gen_dealloc(PyGenObject *gen)
7878}
7979
8080static PyObject *
81- gen_send_ex (PyGenObject * gen , PyObject * arg , int exc )
81+ gen_send_ex (PyGenObject * gen , PyObject * arg , int exc , int closing )
8282{
8383 PyThreadState * tstate = PyThreadState_GET ();
8484 PyFrameObject * f = gen -> gi_frame ;
@@ -92,9 +92,18 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
9292 return NULL ;
9393 }
9494 if (f == NULL || f -> f_stacktop == NULL ) {
95- /* Only set exception if called from send() */
96- if (arg && !exc )
95+ if (PyCoro_CheckExact (gen ) && !closing ) {
96+ /* `gen` is an exhausted coroutine: raise an error,
97+ except when called from gen_close(), which should
98+ always be a silent method. */
99+ PyErr_SetString (
100+ PyExc_RuntimeError ,
101+ "cannot reuse already awaited coroutine" );
102+ } else if (arg && !exc ) {
103+ /* `gen` is an exhausted generator:
104+ only set exception if called from send(). */
97105 PyErr_SetNone (PyExc_StopIteration );
106+ }
98107 return NULL ;
99108 }
100109
@@ -220,7 +229,7 @@ return next yielded value or raise StopIteration.");
220229PyObject *
221230_PyGen_Send (PyGenObject * gen , PyObject * arg )
222231{
223- return gen_send_ex (gen , arg , 0 );
232+ return gen_send_ex (gen , arg , 0 , 0 );
224233}
225234
226235PyDoc_STRVAR (close_doc ,
@@ -292,7 +301,7 @@ gen_close(PyGenObject *gen, PyObject *args)
292301 }
293302 if (err == 0 )
294303 PyErr_SetNone (PyExc_GeneratorExit );
295- retval = gen_send_ex (gen , Py_None , 1 );
304+ retval = gen_send_ex (gen , Py_None , 1 , 1 );
296305 if (retval ) {
297306 char * msg = "generator ignored GeneratorExit" ;
298307 if (PyCoro_CheckExact (gen ))
@@ -336,7 +345,7 @@ gen_throw(PyGenObject *gen, PyObject *args)
336345 gen -> gi_running = 0 ;
337346 Py_DECREF (yf );
338347 if (err < 0 )
339- return gen_send_ex (gen , Py_None , 1 );
348+ return gen_send_ex (gen , Py_None , 1 , 0 );
340349 goto throw_here ;
341350 }
342351 if (PyGen_CheckExact (yf )) {
@@ -369,10 +378,10 @@ gen_throw(PyGenObject *gen, PyObject *args)
369378 /* Termination repetition of YIELD_FROM */
370379 gen -> gi_frame -> f_lasti ++ ;
371380 if (_PyGen_FetchStopIterationValue (& val ) == 0 ) {
372- ret = gen_send_ex (gen , val , 0 );
381+ ret = gen_send_ex (gen , val , 0 , 0 );
373382 Py_DECREF (val );
374383 } else {
375- ret = gen_send_ex (gen , Py_None , 1 );
384+ ret = gen_send_ex (gen , Py_None , 1 , 0 );
376385 }
377386 }
378387 return ret ;
@@ -426,7 +435,7 @@ gen_throw(PyGenObject *gen, PyObject *args)
426435 }
427436
428437 PyErr_Restore (typ , val , tb );
429- return gen_send_ex (gen , Py_None , 1 );
438+ return gen_send_ex (gen , Py_None , 1 , 0 );
430439
431440failed_throw :
432441 /* Didn't use our arguments, so restore their original refcounts */
@@ -440,7 +449,7 @@ gen_throw(PyGenObject *gen, PyObject *args)
440449static PyObject *
441450gen_iternext (PyGenObject * gen )
442451{
443- return gen_send_ex (gen , NULL , 0 );
452+ return gen_send_ex (gen , NULL , 0 , 0 );
444453}
445454
446455/*
@@ -893,13 +902,13 @@ coro_wrapper_dealloc(PyCoroWrapper *cw)
893902static PyObject *
894903coro_wrapper_iternext (PyCoroWrapper * cw )
895904{
896- return gen_send_ex ((PyGenObject * )cw -> cw_coroutine , NULL , 0 );
905+ return gen_send_ex ((PyGenObject * )cw -> cw_coroutine , NULL , 0 , 0 );
897906}
898907
899908static PyObject *
900909coro_wrapper_send (PyCoroWrapper * cw , PyObject * arg )
901910{
902- return gen_send_ex ((PyGenObject * )cw -> cw_coroutine , arg , 0 );
911+ return gen_send_ex ((PyGenObject * )cw -> cw_coroutine , arg , 0 , 0 );
903912}
904913
905914static PyObject *
0 commit comments