From ab18f4e9b199755d5d84286eaed79031e48d48bd Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Wed, 17 Apr 2024 00:40:12 +0900 Subject: [PATCH 1/2] gh-112069: Make setiter_iternext to be thread-safe --- Objects/setobject.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c index 592711f305cbaf..609bff15cfe975 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,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) { 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; } From 67a9efcbe015d4d3cb29d68703b978f7ae8fd130 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Wed, 17 Apr 2024 00:57:40 +0900 Subject: [PATCH 2/2] Address code review --- Objects/setobject.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Objects/setobject.c b/Objects/setobject.c index 609bff15cfe975..66ca80e8fc25f9 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -866,16 +866,12 @@ static PyObject *setiter_iternext(setiterobject *si) Py_END_CRITICAL_SECTION(); si->si_pos = i+1; if (key == NULL) { - goto fail; + si->si_set = NULL; + Py_DECREF(so); + return NULL; } si->len--; return key; - -fail: - si->si_set = NULL; - Py_DECREF(so); - Py_XDECREF(key); - return NULL; } PyTypeObject PySetIter_Type = {