Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
gh-112069: Make setiter_iternext to be thread-safe
  • Loading branch information
corona10 committed Apr 16, 2024
commit ab18f4e9b199755d5d84286eaed79031e48d48bd
21 changes: 15 additions & 6 deletions Objects/setobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -843,29 +843,38 @@ 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)
if (key == NULL) {
Comment thread
corona10 marked this conversation as resolved.
goto fail;
}
si->len--;
key = entry[i].key;
return Py_NewRef(key);
return key;

fail:
si->si_set = NULL;
Py_DECREF(so);
Py_XDECREF(key);
return NULL;
}

Expand Down