mirror of
https://github.com/python/cpython.git
synced 2025-10-10 00:43:41 +00:00
gh-112069: Make setiter_iternext to be thread-safe (gh-117935)
This commit is contained in:
parent
3284b84c43
commit
a734fd5cf7
1 changed files with 17 additions and 12 deletions
|
@ -834,7 +834,7 @@ static PyMethodDef setiter_methods[] = {
|
||||||
|
|
||||||
static PyObject *setiter_iternext(setiterobject *si)
|
static PyObject *setiter_iternext(setiterobject *si)
|
||||||
{
|
{
|
||||||
PyObject *key;
|
PyObject *key = NULL;
|
||||||
Py_ssize_t i, mask;
|
Py_ssize_t i, mask;
|
||||||
setentry *entry;
|
setentry *entry;
|
||||||
PySetObject *so = si->si_set;
|
PySetObject *so = si->si_set;
|
||||||
|
@ -843,31 +843,36 @@ static PyObject *setiter_iternext(setiterobject *si)
|
||||||
return NULL;
|
return NULL;
|
||||||
assert (PyAnySet_Check(so));
|
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,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"Set changed size during iteration");
|
"Set changed size during iteration");
|
||||||
si->si_used = -1; /* Make this state sticky */
|
si->si_used = -1; /* Make this state sticky */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(so);
|
||||||
i = si->si_pos;
|
i = si->si_pos;
|
||||||
assert(i>=0);
|
assert(i>=0);
|
||||||
entry = so->table;
|
entry = so->table;
|
||||||
mask = so->mask;
|
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++;
|
i++;
|
||||||
|
}
|
||||||
|
if (i <= mask) {
|
||||||
|
key = Py_NewRef(entry[i].key);
|
||||||
|
}
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
si->si_pos = i+1;
|
si->si_pos = i+1;
|
||||||
if (i > mask)
|
if (key == NULL) {
|
||||||
goto fail;
|
|
||||||
si->len--;
|
|
||||||
key = entry[i].key;
|
|
||||||
return Py_NewRef(key);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
si->si_set = NULL;
|
si->si_set = NULL;
|
||||||
Py_DECREF(so);
|
Py_DECREF(so);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
si->len--;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
PyTypeObject PySetIter_Type = {
|
PyTypeObject PySetIter_Type = {
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue