diff options
author | Donghee Na <donghee.na@python.org> | 2024-04-16 16:31:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-16 16:31:42 (GMT) |
commit | a734fd5cf71ab8d7eb17ba5d6592fcc23679656b (patch) | |
tree | 4ee43fb082ca02e35d9b3d918a28bc77ba9b045e /Objects | |
parent | 3284b84c437e3b0b0a052471e8a6aabc528fc651 (diff) | |
download | cpython-a734fd5cf71ab8d7eb17ba5d6592fcc23679656b.zip cpython-a734fd5cf71ab8d7eb17ba5d6592fcc23679656b.tar.gz cpython-a734fd5cf71ab8d7eb17ba5d6592fcc23679656b.tar.bz2 |
gh-112069: Make setiter_iternext to be thread-safe (gh-117935)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/setobject.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c index 592711f..66ca80e 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -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,30 +843,35 @@ 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; + if (key == NULL) { + si->si_set = NULL; + Py_DECREF(so); + return NULL; + } si->len--; - key = entry[i].key; - return Py_NewRef(key); - -fail: - si->si_set = NULL; - Py_DECREF(so); - return NULL; + return key; } PyTypeObject PySetIter_Type = { |