Further thread safety changes for Python 3.13 free threading

See #1683
This commit is contained in:
rdb
2024-09-19 20:43:06 +02:00
parent 4b2fa45578
commit beff684af3
14 changed files with 171 additions and 78 deletions
+7 -3
View File
@@ -72,6 +72,9 @@ convert_points(pvector<LPoint3> &vec, PyObject *points) {
return false;
}
bool success = true;
Py_BEGIN_CRITICAL_SECTION(seq);
PyObject **items = PySequence_Fast_ITEMS(seq);
Py_ssize_t len = PySequence_Fast_GET_SIZE(seq);
void *ptr;
@@ -90,13 +93,14 @@ convert_points(pvector<LPoint3> &vec, PyObject *points) {
}
else {
Dtool_Raise_TypeError("Argument must be of LPoint3 type.");
Py_DECREF(seq);
return false;
success = false;
break;
}
}
Py_END_CRITICAL_SECTION();
Py_DECREF(seq);
return true;
return success;
}
#endif
+4 -2
View File
@@ -106,12 +106,13 @@ __init__(PyObject *self, PyObject *source) {
// We need to initialize the this pointer before we can call push_back.
DtoolInstance_INIT_PTR(self, this->_this);
Py_BEGIN_CRITICAL_SECTION(source);
Py_ssize_t size = PySequence_Size(source);
this->_this->reserve(size);
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject *item = PySequence_GetItem(source, i);
if (item == nullptr) {
return;
break;
}
PyObject *result = PyObject_CallFunctionObjArgs(push_back, self, item, nullptr);
Py_DECREF(item);
@@ -121,10 +122,11 @@ __init__(PyObject *self, PyObject *source) {
PyErr_Format(PyExc_TypeError,
"Element %zd in sequence passed to PointerToArray "
"constructor could not be added", i);
return;
break;
}
Py_DECREF(result);
}
Py_END_CRITICAL_SECTION();
}
/**
+4 -4
View File
@@ -31,13 +31,14 @@ __init__(PyObject *self, PyObject *sequence) {
return;
}
Py_BEGIN_CRITICAL_SECTION(fast);
Py_ssize_t size = PySequence_Fast_GET_SIZE(fast);
_this->reserve(size);
for (int i = 0; i < size; ++i) {
PyObject *item = PySequence_Fast_GET_ITEM(fast, i);
if (item == nullptr) {
return;
break;
}
Texture *tex;
@@ -48,13 +49,12 @@ __init__(PyObject *self, PyObject *sequence) {
stream << "Element " << i << " in sequence passed to TextureCollection constructor is not a Texture";
std::string str = stream.str();
PyErr_SetString(PyExc_TypeError, str.c_str());
Py_DECREF(fast);
return;
break;
} else {
_this->add_texture(tex);
}
}
Py_END_CRITICAL_SECTION();
Py_DECREF(fast);
}
+4 -4
View File
@@ -36,13 +36,14 @@ __init__(PyObject *self, PyObject *sequence) {
return;
}
Py_BEGIN_CRITICAL_SECTION(fast);
Py_ssize_t size = PySequence_Fast_GET_SIZE(fast);
_this->reserve(size);
for (int i = 0; i < size; ++i) {
PyObject *item = PySequence_Fast_GET_ITEM(fast, i);
if (item == nullptr) {
return;
break;
}
NodePath *path;
@@ -52,13 +53,12 @@ __init__(PyObject *self, PyObject *sequence) {
stream << "Element " << i << " in sequence passed to NodePathCollection constructor is not a NodePath";
std::string str = stream.str();
PyErr_SetString(PyExc_TypeError, str.c_str());
Py_DECREF(fast);
return;
break;
} else {
_this->add_path(*path);
}
}
Py_END_CRITICAL_SECTION();
Py_DECREF(fast);
}
+6 -7
View File
@@ -89,26 +89,25 @@ init(PyObject *loader) {
return false;
}
PyObject *sequence = PySequence_Fast(extensions, "extensions must be a sequence");
PyObject **items = PySequence_Fast_ITEMS(sequence);
Py_ssize_t num_items = PySequence_Fast_GET_SIZE(sequence);
PyObject *tuple = PySequence_Tuple(extensions);
Py_ssize_t num_items = PyTuple_GET_SIZE(tuple);
Py_DECREF(extensions);
if (num_items == 0) {
PyErr_SetString(PyExc_ValueError, "extensions list may not be empty");
Py_DECREF(sequence);
Py_DECREF(tuple);
return false;
}
bool found_extension = false;
for (Py_ssize_t i = 0; i < num_items; ++i) {
PyObject *extension = items[i];
PyObject *extension = PyTuple_GET_ITEM(tuple, i);
const char *extension_str;
Py_ssize_t extension_len;
extension_str = PyUnicode_AsUTF8AndSize(extension, &extension_len);
if (extension_str == nullptr) {
Py_DECREF(sequence);
Py_DECREF(tuple);
return false;
}
@@ -127,7 +126,7 @@ init(PyObject *loader) {
}
}
}
Py_DECREF(sequence);
Py_DECREF(tuple);
if (!found_extension) {
PyObject *repr = PyObject_Repr(loader);
+12 -1
View File
@@ -269,12 +269,20 @@ __init__(CPT_InternalName name, PyObject *value, int priority) {
} else if (PySequence_Check(value) && !PyUnicode_CheckExact(value)) {
// Iterate over the sequence to make sure all have the same type.
#ifdef Py_GIL_DISABLED
PyObject *fast = PySequence_Tuple(value);
#else
PyObject *fast = PySequence_Fast(value, "unknown type passed to ShaderInput");
#endif
if (fast == nullptr) {
return;
}
#ifdef Py_GIL_DISABLED
Py_ssize_t num_items = PyTuple_GET_SIZE(fast);
#else
Py_ssize_t num_items = PySequence_Fast_GET_SIZE(fast);
#endif
if (num_items <= 0) {
// We can't determine the type of a list of size 0.
_this->_type = ShaderInput::M_numeric;
@@ -289,6 +297,9 @@ __init__(CPT_InternalName name, PyObject *value, int priority) {
for (Py_ssize_t i = 0; i < num_items; ++i) {
PyObject *item = items[i];
//FIXME: if these items are not tuples, this is not thread-safe in the
// free-threaded build. Convert everything to tuples, and push to a
// vector?
if (PySequence_Check(item)) {
Py_ssize_t itemsize = PySequence_Size(item);
if (known_itemsize >= 0 && itemsize != known_itemsize) {
@@ -310,7 +321,7 @@ __init__(CPT_InternalName name, PyObject *value, int priority) {
Dtool_Raise_TypeError("unknown element type in sequence passed as element of sequence passed to ShaderInput");
Py_DECREF(subitem);
Py_DECREF(fast);
break;
return;
}
Py_DECREF(subitem);
}
+18 -11
View File
@@ -349,17 +349,24 @@ find_global_decode(PyObject *this_class, const char *func_name) {
PyObject *bases = PyObject_GetAttrString(this_class, "__bases__");
if (bases != nullptr) {
if (PySequence_Check(bases)) {
Py_ssize_t size = PySequence_Size(bases);
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject *base = PySequence_GetItem(bases, i);
if (base != nullptr) {
PyObject *func = find_global_decode(base, func_name);
Py_DECREF(base);
if (func != nullptr) {
Py_DECREF(bases);
return func;
}
{
PyObject *tuple = PySequence_Tuple(bases);
Py_DECREF(bases);
if (tuple == nullptr) {
PyErr_Clear();
return nullptr;
}
bases = tuple;
}
Py_ssize_t size = PyTuple_GET_SIZE(bases);
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject *base = PyTuple_GET_ITEM(bases, i);
if (base != nullptr) {
PyObject *func = find_global_decode(base, func_name);
if (func != nullptr) {
Py_DECREF(bases);
return func;
}
}
}