gh-112069: Make setiter_iternext to be thread-safe (gh-117935)

This commit is contained in:
Donghee Na 2024-04-17 01:31:42 +09:00 committed by GitHub
parent 3284b84c43
commit a734fd5cf7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 17 additions and 12 deletions

View File

@ -834,7 +834,7 @@ static PyMethodDef setiter_methods[] = {
static PyObject *setiter_iternext(setiterobject *si)
{
PyObject *key;
PyObject *key = NULL;
Py_ssize_t i, mask;
setentry *entry;
PySetObject *so = si->si_set;
@ -843,31 +843,36 @@ static PyObject *setiter_iternext(setiterobject *si)
return NULL;
assert (PyAnySet_Check(so));
if (si->si_used != so->used) {
Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE(so->used);
Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE(si->si_used);
if (si_used != so_used) {
PyErr_SetString(PyExc_RuntimeError,
"Set changed size during iteration");
si->si_used = -1; /* Make this state sticky */
return NULL;
}
Py_BEGIN_CRITICAL_SECTION(so);
i = si->si_pos;
assert(i>=0);
entry = so->table;
mask = so->mask;
while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy))
while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
i++;
}
if (i <= mask) {
key = Py_NewRef(entry[i].key);
}
Py_END_CRITICAL_SECTION();
si->si_pos = i+1;
if (i > mask)
goto fail;
si->len--;
key = entry[i].key;
return Py_NewRef(key);
fail:
if (key == NULL) {
si->si_set = NULL;
Py_DECREF(so);
return NULL;
}
si->len--;
return key;
}
PyTypeObject PySetIter_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)