mirror of
https://github.com/python/cpython.git
synced 2025-11-25 21:11:09 +00:00
Change PyType_Ready() to use the READY and READYING flags. This makes
it possible to detect recursive calls early (as opposed to when the stack overflows :-).
This commit is contained in:
parent
d635e3c468
commit
d614f97733
1 changed files with 26 additions and 13 deletions
|
|
@ -1169,8 +1169,14 @@ PyType_Ready(PyTypeObject *type)
|
||||||
PyTypeObject *base;
|
PyTypeObject *base;
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
if (type->tp_dict != NULL)
|
if (type->tp_flags & Py_TPFLAGS_READY) {
|
||||||
return 0; /* Already initialized */
|
assert(type->tp_dict != NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert((type->tp_flags & Py_TPFLAGS_READYING) == 0);
|
||||||
|
assert(type->tp_dict == NULL);
|
||||||
|
|
||||||
|
type->tp_flags |= Py_TPFLAGS_READYING;
|
||||||
|
|
||||||
/* Initialize tp_base (defaults to BaseObject unless that's us) */
|
/* Initialize tp_base (defaults to BaseObject unless that's us) */
|
||||||
base = type->tp_base;
|
base = type->tp_base;
|
||||||
|
|
@ -1185,14 +1191,14 @@ PyType_Ready(PyTypeObject *type)
|
||||||
else
|
else
|
||||||
bases = Py_BuildValue("(O)", base);
|
bases = Py_BuildValue("(O)", base);
|
||||||
if (bases == NULL)
|
if (bases == NULL)
|
||||||
return -1;
|
goto error;
|
||||||
type->tp_bases = bases;
|
type->tp_bases = bases;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the base class */
|
/* Initialize the base class */
|
||||||
if (base && base->tp_dict == NULL) {
|
if (base && base->tp_dict == NULL) {
|
||||||
if (PyType_Ready(base) < 0)
|
if (PyType_Ready(base) < 0)
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize tp_defined */
|
/* Initialize tp_defined */
|
||||||
|
|
@ -1200,24 +1206,24 @@ PyType_Ready(PyTypeObject *type)
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
dict = PyDict_New();
|
dict = PyDict_New();
|
||||||
if (dict == NULL)
|
if (dict == NULL)
|
||||||
return -1;
|
goto error;
|
||||||
type->tp_defined = dict;
|
type->tp_defined = dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add type-specific descriptors to tp_defined */
|
/* Add type-specific descriptors to tp_defined */
|
||||||
if (add_operators(type) < 0)
|
if (add_operators(type) < 0)
|
||||||
return -1;
|
goto error;
|
||||||
if (type->tp_methods != NULL) {
|
if (type->tp_methods != NULL) {
|
||||||
if (add_methods(type, type->tp_methods) < 0)
|
if (add_methods(type, type->tp_methods) < 0)
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
if (type->tp_members != NULL) {
|
if (type->tp_members != NULL) {
|
||||||
if (add_members(type, type->tp_members) < 0)
|
if (add_members(type, type->tp_members) < 0)
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
if (type->tp_getset != NULL) {
|
if (type->tp_getset != NULL) {
|
||||||
if (add_getset(type, type->tp_getset) < 0)
|
if (add_getset(type, type->tp_getset) < 0)
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Temporarily make tp_dict the same object as tp_defined.
|
/* Temporarily make tp_dict the same object as tp_defined.
|
||||||
|
|
@ -1228,7 +1234,7 @@ PyType_Ready(PyTypeObject *type)
|
||||||
|
|
||||||
/* Calculate method resolution order */
|
/* Calculate method resolution order */
|
||||||
if (mro_internal(type) < 0) {
|
if (mro_internal(type) < 0) {
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize tp_dict properly */
|
/* Initialize tp_dict properly */
|
||||||
|
|
@ -1240,7 +1246,7 @@ PyType_Ready(PyTypeObject *type)
|
||||||
Py_DECREF(type->tp_dict);
|
Py_DECREF(type->tp_dict);
|
||||||
type->tp_dict = PyDict_New();
|
type->tp_dict = PyDict_New();
|
||||||
if (type->tp_dict == NULL)
|
if (type->tp_dict == NULL)
|
||||||
return -1;
|
goto error;
|
||||||
bases = type->tp_mro;
|
bases = type->tp_mro;
|
||||||
assert(bases != NULL);
|
assert(bases != NULL);
|
||||||
assert(PyTuple_Check(bases));
|
assert(PyTuple_Check(bases));
|
||||||
|
|
@ -1250,16 +1256,23 @@ PyType_Ready(PyTypeObject *type)
|
||||||
assert(PyType_Check(base));
|
assert(PyType_Check(base));
|
||||||
x = base->tp_defined;
|
x = base->tp_defined;
|
||||||
if (x != NULL && PyDict_Update(type->tp_dict, x) < 0)
|
if (x != NULL && PyDict_Update(type->tp_dict, x) < 0)
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inherit slots from direct base */
|
/* Inherit slots from direct base */
|
||||||
if (type->tp_base != NULL)
|
if (type->tp_base != NULL)
|
||||||
if (inherit_slots(type, type->tp_base) < 0)
|
if (inherit_slots(type, type->tp_base) < 0)
|
||||||
return -1;
|
goto error;
|
||||||
|
|
||||||
|
assert(type->tp_dict != NULL);
|
||||||
|
type->tp_flags =
|
||||||
|
(type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
type->tp_flags &= ~Py_TPFLAGS_READYING;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue