Skip to content

Commit 17b7acf

Browse files
committed
Fix races with gi_frame_state
1 parent 55ea54d commit 17b7acf

File tree

2 files changed

+113
-12
lines changed

2 files changed

+113
-12
lines changed

Objects/clinic/genobject.c.h

Lines changed: 87 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/genobject.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ raise GeneratorExit inside generator.
404404

405405
static PyObject *
406406
gen_close_impl(PyGenObject *self)
407-
/*[clinic end generated code: output=2d7adf450173059c input=6c40e85559b6f098]*/
407+
/*[clinic end generated code: output=2d7adf450173059c input=417e6161842080c9]*/
408408
{
409409
PyGenObject *gen = _PyGen_CAST(self);
410410

@@ -787,27 +787,40 @@ gen_getyieldfrom(PyObject *gen, void *Py_UNUSED(ignored))
787787
return yf;
788788
}
789789

790+
/*[clinic input]
791+
@getter
792+
@critical_section
793+
generator.gi_running as gen_getrunning
794+
[clinic start generated code]*/
790795

791796
static PyObject *
792-
gen_getrunning(PyObject *self, void *Py_UNUSED(ignored))
797+
gen_getrunning_get_impl(PyGenObject *self)
798+
/*[clinic end generated code: output=a7233b957ce88a6f input=d3d995cf1581b21b]*/
793799
{
794-
PyGenObject *gen = _PyGen_CAST(self);
795-
if (gen->gi_frame_state == FRAME_EXECUTING) {
800+
if (self->gi_frame_state == FRAME_EXECUTING) {
796801
Py_RETURN_TRUE;
797802
}
798803
Py_RETURN_FALSE;
799804
}
800805

806+
/*[clinic input]
807+
@getter
808+
@critical_section
809+
generator.gi_suspended as gen_getsuspended
810+
[clinic start generated code]*/
811+
801812
static PyObject *
802-
gen_getsuspended(PyObject *self, void *Py_UNUSED(ignored))
813+
gen_getsuspended_get_impl(PyGenObject *self)
814+
/*[clinic end generated code: output=a0345f9be186eda3 input=880e9fb8436726cb]*/
803815
{
804816
PyGenObject *gen = _PyGen_CAST(self);
805817
return PyBool_FromLong(FRAME_STATE_SUSPENDED(gen->gi_frame_state));
806818
}
807819

808820
static PyObject *
809-
_gen_getframe(PyGenObject *gen, const char *const name)
821+
_gen_getframe(PyGenObject *self, const char *name)
810822
{
823+
PyGenObject *gen = _PyGen_CAST(self);
811824
if (PySys_Audit("object.__getattr__", "Os", gen, name) < 0) {
812825
return NULL;
813826
}
@@ -821,7 +834,11 @@ static PyObject *
821834
gen_getframe(PyObject *self, void *Py_UNUSED(ignored))
822835
{
823836
PyGenObject *gen = _PyGen_CAST(self);
824-
return _gen_getframe(gen, "gi_frame");
837+
PyObject *res;
838+
Py_BEGIN_CRITICAL_SECTION(gen);
839+
res = _gen_getframe(gen, "gi_frame");
840+
Py_END_CRITICAL_SECTION();
841+
return res;
825842
}
826843

827844
static PyObject *
@@ -847,9 +864,9 @@ static PyGetSetDef gen_getsetlist[] = {
847864
PyDoc_STR("qualified name of the generator")},
848865
{"gi_yieldfrom", gen_getyieldfrom, NULL,
849866
PyDoc_STR("object being iterated by yield from, or None")},
850-
{"gi_running", gen_getrunning, NULL, NULL},
867+
GEN_GETRUNNING_GETSETDEF
868+
GEN_GETSUSPENDED_GETSETDEF
851869
{"gi_frame", gen_getframe, NULL, NULL},
852-
{"gi_suspended", gen_getsuspended, NULL, NULL},
853870
{"gi_code", gen_getcode, NULL, NULL},
854871
{NULL} /* Sentinel */
855872
};

0 commit comments

Comments
 (0)