diff options
author | Thomas Grainger <tagrain@gmail.com> | 2024-05-01 06:44:01 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-01 06:44:01 (GMT) |
commit | fc7e1aa3c001bbce25973261fba457035719a559 (patch) | |
tree | 95b1780a0a50b79cfb748123668b4adffacad04c /Objects | |
parent | 2520eed0a529be3815f70c43e1a5006deeee5596 (diff) | |
download | cpython-fc7e1aa3c001bbce25973261fba457035719a559.zip cpython-fc7e1aa3c001bbce25973261fba457035719a559.tar.gz cpython-fc7e1aa3c001bbce25973261fba457035719a559.tar.bz2 |
GH-117881: fix athrow().throw()/asend().throw() concurrent access (GH-117882)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/genobject.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/Objects/genobject.c b/Objects/genobject.c index a1ed1cb..89bb21a 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -1774,6 +1774,7 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg) if (o->ags_state == AWAITABLE_STATE_INIT) { if (o->ags_gen->ag_running_async) { + o->ags_state = AWAITABLE_STATE_CLOSED; PyErr_SetString( PyExc_RuntimeError, "anext(): asynchronous generator is already running"); @@ -1817,10 +1818,24 @@ async_gen_asend_throw(PyAsyncGenASend *o, PyObject *const *args, Py_ssize_t narg return NULL; } + if (o->ags_state == AWAITABLE_STATE_INIT) { + if (o->ags_gen->ag_running_async) { + o->ags_state = AWAITABLE_STATE_CLOSED; + PyErr_SetString( + PyExc_RuntimeError, + "anext(): asynchronous generator is already running"); + return NULL; + } + + o->ags_state = AWAITABLE_STATE_ITER; + o->ags_gen->ag_running_async = 1; + } + result = gen_throw((PyGenObject*)o->ags_gen, args, nargs); result = async_gen_unwrap_value(o->ags_gen, result); if (result == NULL) { + o->ags_gen->ag_running_async = 0; o->ags_state = AWAITABLE_STATE_CLOSED; } @@ -2209,10 +2224,31 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na return NULL; } + if (o->agt_state == AWAITABLE_STATE_INIT) { + if (o->agt_gen->ag_running_async) { + o->agt_state = AWAITABLE_STATE_CLOSED; + if (o->agt_args == NULL) { + PyErr_SetString( + PyExc_RuntimeError, + "aclose(): asynchronous generator is already running"); + } + else { + PyErr_SetString( + PyExc_RuntimeError, + "athrow(): asynchronous generator is already running"); + } + return NULL; + } + + o->agt_state = AWAITABLE_STATE_ITER; + o->agt_gen->ag_running_async = 1; + } + retval = gen_throw((PyGenObject*)o->agt_gen, args, nargs); if (o->agt_args) { retval = async_gen_unwrap_value(o->agt_gen, retval); if (retval == NULL) { + o->agt_gen->ag_running_async = 0; o->agt_state = AWAITABLE_STATE_CLOSED; } return retval; @@ -2226,6 +2262,7 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na return NULL; } if (retval == NULL) { + o->agt_gen->ag_running_async = 0; o->agt_state = AWAITABLE_STATE_CLOSED; } if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) || |