summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorDonghee Na <donghee.na@python.org>2024-04-16 16:31:42 (GMT)
committerGitHub <noreply@github.com>2024-04-16 16:31:42 (GMT)
commita734fd5cf71ab8d7eb17ba5d6592fcc23679656b (patch)
tree4ee43fb082ca02e35d9b3d918a28bc77ba9b045e /Objects
parent3284b84c437e3b0b0a052471e8a6aabc528fc651 (diff)
downloadcpython-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.c29
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 = {